Skip to content

Commit 43e3ba8

Browse files
committed
feat(github-copilot): fix model display timing and add manual refresh functionality
1 parent 45765b7 commit 43e3ba8

File tree

2 files changed

+245
-3
lines changed

2 files changed

+245
-3
lines changed

GITHUB_COPILOT_TIMING_FIX.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# GitHub Copilot 模型显示时机问题修复
2+
3+
## 问题描述
4+
5+
`SimplifiedLLMSettingComponent` 中,GitHub Copilot 模型只在添加新 LLM 时才会显示到下拉列表中,而不是在设置页面初始加载时就显示。
6+
7+
## 问题分析
8+
9+
### 原始代码问题
10+
```kotlin
11+
// 在 updateAllDropdowns() 方法中
12+
if (manager.isInitialized()) {
13+
// 只有当 GitHub Copilot Manager 已经初始化时才显示模型
14+
githubModels?.forEach { model ->
15+
// 添加模型到下拉框
16+
}
17+
} else {
18+
// 在后台初始化,但没有回调更新UI
19+
AutoDevAppScope.workerScope().launch {
20+
GithubCopilotManager.getInstance().initialize()
21+
// 缺少UI更新逻辑
22+
}
23+
}
24+
```
25+
26+
### 问题根源
27+
1. **初始化时机**:GitHub Copilot Manager 在设置页面首次加载时通常未初始化
28+
2. **缺少回调**:后台初始化完成后没有更新UI的机制
29+
3. **触发时机**:只有在添加新LLM时调用 `updateAllDropdowns()` 才会重新检查并显示GitHub Copilot模型
30+
31+
## 解决方案
32+
33+
### 1. 早期初始化
34+
在组件构造函数中就开始初始化GitHub Copilot:
35+
36+
```kotlin
37+
init {
38+
setupEventListeners()
39+
40+
// Try to initialize GitHub Copilot early
41+
initializeGitHubCopilot()
42+
43+
applySettings(settings)
44+
LanguageChangedCallback.language = AutoDevSettingsState.getInstance().language
45+
}
46+
47+
private fun initializeGitHubCopilot() {
48+
val manager = service<GithubCopilotManager>()
49+
if (!manager.isInitialized()) {
50+
AutoDevAppScope.workerScope().launch {
51+
try {
52+
manager.initialize()
53+
// After initialization, update the UI on the EDT
54+
SwingUtilities.invokeLater {
55+
updateAllDropdowns()
56+
updateLLMTable()
57+
}
58+
} catch (e: Exception) {
59+
// Silently handle initialization failures
60+
// GitHub Copilot might not be available
61+
}
62+
}
63+
}
64+
}
65+
```
66+
67+
### 2. 异步初始化回调
68+
`updateAllDropdowns()` 方法中添加回调机制:
69+
70+
```kotlin
71+
} else {
72+
// Initialize GitHub Copilot in background and update UI when ready
73+
AutoDevAppScope.workerScope().launch {
74+
try {
75+
GithubCopilotManager.getInstance().initialize()
76+
// After initialization, update the UI on the EDT
77+
SwingUtilities.invokeLater {
78+
updateAllDropdowns()
79+
updateLLMTable()
80+
}
81+
} catch (e: Exception) {
82+
// Silently handle initialization failures
83+
// GitHub Copilot might not be available
84+
}
85+
}
86+
}
87+
```
88+
89+
### 3. 手动刷新功能
90+
添加刷新按钮让用户可以手动刷新GitHub Copilot模型:
91+
92+
```kotlin
93+
// Create refresh button for GitHub Copilot models
94+
val refreshButton = JButton("Refresh GitHub Copilot Models")
95+
refreshButton.addActionListener { refreshGitHubCopilotModels() }
96+
97+
private fun refreshGitHubCopilotModels() {
98+
val manager = service<GithubCopilotManager>()
99+
100+
AutoDevAppScope.workerScope().launch {
101+
try {
102+
// Force refresh GitHub Copilot models
103+
manager.getSupportedModels(forceRefresh = true)
104+
105+
// Update UI on EDT
106+
SwingUtilities.invokeLater {
107+
updateAllDropdowns()
108+
updateLLMTable()
109+
Messages.showInfoMessage(
110+
"GitHub Copilot models refreshed successfully!",
111+
"Refresh Complete"
112+
)
113+
}
114+
} catch (e: Exception) {
115+
SwingUtilities.invokeLater {
116+
Messages.showErrorDialog(
117+
"Failed to refresh GitHub Copilot models: ${e.message}",
118+
"Refresh Failed"
119+
)
120+
}
121+
}
122+
}
123+
}
124+
```
125+
126+
## 修复效果
127+
128+
### 修复前
129+
- ❌ 设置页面首次加载时不显示GitHub Copilot模型
130+
- ❌ 需要添加新LLM才能触发显示
131+
- ❌ 用户体验差,容易误以为GitHub Copilot不可用
132+
133+
### 修复后
134+
- ✅ 组件初始化时就开始加载GitHub Copilot模型
135+
- ✅ 异步加载完成后自动更新UI
136+
- ✅ 提供手动刷新按钮
137+
- ✅ 更好的用户体验和错误处理
138+
139+
## 技术要点
140+
141+
### 1. 线程安全
142+
- 使用 `SwingUtilities.invokeLater` 确保UI更新在EDT线程执行
143+
- 后台初始化在工作线程中进行,不阻塞UI
144+
145+
### 2. 错误处理
146+
- 静默处理初始化失败(GitHub Copilot可能不可用)
147+
- 为用户提供明确的错误信息
148+
149+
### 3. 用户体验
150+
- 早期初始化减少等待时间
151+
- 手动刷新按钮提供用户控制
152+
- 成功/失败消息提供反馈
153+
154+
### 4. 性能优化
155+
- 避免重复初始化(检查 `isInitialized()`
156+
- 使用 `forceRefresh` 参数控制是否强制刷新
157+
158+
## 适用场景
159+
160+
这种修复方案适用于:
161+
- 需要异步加载外部资源的UI组件
162+
- 依赖第三方服务初始化的功能
163+
- 需要提供用户手动刷新能力的场景
164+
165+
## 注意事项
166+
167+
1. **初始化顺序**:确保在UI构建前开始异步初始化
168+
2. **线程切换**:UI更新必须在EDT线程执行
169+
3. **错误处理**:优雅处理初始化失败的情况
170+
4. **用户反馈**:提供适当的加载状态和结果反馈
171+
172+
这个修复彻底解决了GitHub Copilot模型显示时机问题,确保用户在打开设置页面时就能看到所有可用的模型选项。

core/src/main/kotlin/cc/unitmesh/devti/settings/SimplifiedLLMSettingComponent.kt

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,33 @@ class SimplifiedLLMSettingComponent(private val settings: AutoDevSettingsState)
7272

7373
init {
7474
setupEventListeners()
75+
76+
// Try to initialize GitHub Copilot early
77+
initializeGitHubCopilot()
78+
7579
applySettings(settings)
7680
LanguageChangedCallback.language = AutoDevSettingsState.getInstance().language
7781
}
7882

83+
private fun initializeGitHubCopilot() {
84+
val manager = service<GithubCopilotManager>()
85+
if (!manager.isInitialized()) {
86+
AutoDevAppScope.workerScope().launch {
87+
try {
88+
manager.initialize()
89+
// After initialization, update the UI on the EDT
90+
SwingUtilities.invokeLater {
91+
updateAllDropdowns()
92+
updateLLMTable()
93+
}
94+
} catch (e: Exception) {
95+
// Silently handle initialization failures
96+
// GitHub Copilot might not be available
97+
}
98+
}
99+
}
100+
}
101+
79102
private fun setupEventListeners() {
80103
// When checkbox changes, show/hide category dropdowns
81104
useDefaultForAllCheckbox.addActionListener {
@@ -282,9 +305,19 @@ class SimplifiedLLMSettingComponent(private val settings: AutoDevSettingsState)
282305
}
283306
}
284307
} else {
285-
// Initialize GitHub Copilot in background
308+
// Initialize GitHub Copilot in background and update UI when ready
286309
AutoDevAppScope.workerScope().launch {
287-
GithubCopilotManager.getInstance().initialize()
310+
try {
311+
GithubCopilotManager.getInstance().initialize()
312+
// After initialization, update the UI on the EDT
313+
SwingUtilities.invokeLater {
314+
updateAllDropdowns()
315+
updateLLMTable()
316+
}
317+
} catch (e: Exception) {
318+
// Silently handle initialization failures
319+
// GitHub Copilot might not be available
320+
}
288321
}
289322
}
290323

@@ -469,6 +502,34 @@ class SimplifiedLLMSettingComponent(private val settings: AutoDevSettingsState)
469502
}
470503
}
471504

505+
private fun refreshGitHubCopilotModels() {
506+
val manager = service<GithubCopilotManager>()
507+
508+
AutoDevAppScope.workerScope().launch {
509+
try {
510+
// Force refresh GitHub Copilot models
511+
manager.getSupportedModels(forceRefresh = true)
512+
513+
// Update UI on EDT
514+
SwingUtilities.invokeLater {
515+
updateAllDropdowns()
516+
updateLLMTable()
517+
Messages.showInfoMessage(
518+
"GitHub Copilot models refreshed successfully!",
519+
"Refresh Complete"
520+
)
521+
}
522+
} catch (e: Exception) {
523+
SwingUtilities.invokeLater {
524+
Messages.showErrorDialog(
525+
"Failed to refresh GitHub Copilot models: ${e.message}",
526+
"Refresh Failed"
527+
)
528+
}
529+
}
530+
}
531+
}
532+
472533
// Build the main settings panel
473534
fun applySettings(settings: AutoDevSettingsState, updateParams: Boolean = false) {
474535
panel.removeAll()
@@ -481,6 +542,15 @@ class SimplifiedLLMSettingComponent(private val settings: AutoDevSettingsState)
481542
val addLLMButton = JButton("Add New LLM")
482543
addLLMButton.addActionListener { createNewLLM() }
483544

545+
// Create refresh button for GitHub Copilot models
546+
val refreshButton = JButton("Refresh GitHub Copilot Models")
547+
refreshButton.addActionListener { refreshGitHubCopilotModels() }
548+
549+
// Create button panel
550+
val buttonPanel = JPanel()
551+
buttonPanel.add(addLLMButton)
552+
buttonPanel.add(refreshButton)
553+
484554
// Create category panel separately for dynamic visibility
485555
categoryPanel = createCategoryPanel()
486556

@@ -504,7 +574,7 @@ class SimplifiedLLMSettingComponent(private val settings: AutoDevSettingsState)
504574
formBuilder
505575
// Model Management Section
506576
.addLabeledComponent(JBLabel("Model Management"), JPanel(), 1, false)
507-
.addComponent(addLLMButton)
577+
.addComponent(buttonPanel)
508578
.addComponentFillVertically(JScrollPane(llmTable), 0)
509579
.addComponentFillVertically(JPanel(), 0)
510580

0 commit comments

Comments
 (0)