Skip to content

Commit e280175

Browse files
committed
Refactor editor commands into modular directories and extract utility logic for code completion, file searching, and import selection
1 parent 37db603 commit e280175

21 files changed

Lines changed: 1549 additions & 1509 deletions
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import * as vscode from 'vscode'
2+
import { PanelProvider } from '@/views/panel/backend/panel-provider'
3+
import { perform_code_at_cursor } from './utils/perform-code-at-cursor'
4+
5+
export const code_at_cursor_commands = (params: {
6+
file_tree_provider: any
7+
open_editors_provider: any
8+
context: vscode.ExtensionContext
9+
panel_provider: PanelProvider
10+
}) => {
11+
return [
12+
vscode.commands.registerCommand('codeWebChat.codeAtCursor', async () =>
13+
perform_code_at_cursor({
14+
file_tree_provider: params.file_tree_provider,
15+
open_editors_provider: params.open_editors_provider,
16+
context: params.context,
17+
with_completion_instructions: false,
18+
show_quick_pick: false
19+
})
20+
),
21+
vscode.commands.registerCommand(
22+
'codeWebChat.codeAtCursorWithInstructions',
23+
async () =>
24+
perform_code_at_cursor({
25+
file_tree_provider: params.file_tree_provider,
26+
open_editors_provider: params.open_editors_provider,
27+
context: params.context,
28+
with_completion_instructions: true,
29+
show_quick_pick: false
30+
})
31+
),
32+
vscode.commands.registerCommand('codeWebChat.codeAtCursorUsing', async () =>
33+
perform_code_at_cursor({
34+
file_tree_provider: params.file_tree_provider,
35+
open_editors_provider: params.open_editors_provider,
36+
context: params.context,
37+
with_completion_instructions: false,
38+
show_quick_pick: true,
39+
panel_provider: params.panel_provider
40+
})
41+
),
42+
vscode.commands.registerCommand(
43+
'codeWebChat.codeAtCursorWithInstructionsUsing',
44+
async () =>
45+
perform_code_at_cursor({
46+
file_tree_provider: params.file_tree_provider,
47+
open_editors_provider: params.open_editors_provider,
48+
context: params.context,
49+
with_completion_instructions: true,
50+
show_quick_pick: true,
51+
panel_provider: params.panel_provider
52+
})
53+
)
54+
]
55+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './code-at-cursor-commands'
Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
import * as vscode from 'vscode'
2+
import {
3+
ModelProvidersManager,
4+
get_tool_config_id,
5+
ToolConfig
6+
} from '../../../services/model-providers-manager'
7+
import { Logger } from '@shared/utils/logger'
8+
import { RECENTLY_USED_CODE_AT_CURSOR_CONFIG_IDS_STATE_KEY } from '@/constants/state-keys'
9+
import { PanelProvider } from '@/views/panel/backend/panel-provider'
10+
import { dictionary } from '@shared/constants/dictionary'
11+
import { t } from '@/i18n'
12+
13+
export const get_code_at_cursor_config = async (params: {
14+
api_providers_manager: ModelProvidersManager
15+
show_quick_pick?: boolean
16+
context: vscode.ExtensionContext
17+
config_id?: string
18+
panel_provider?: PanelProvider
19+
}): Promise<{ provider: any; config: any } | undefined> => {
20+
const code_at_cursor_configs =
21+
await params.api_providers_manager.get_code_completions_tool_configs()
22+
23+
if (code_at_cursor_configs.length == 0) {
24+
vscode.commands.executeCommand('codeWebChat.settings')
25+
vscode.window.showInformationMessage(
26+
dictionary.information_message.NO_CODE_AT_CURSOR_CONFIGURATIONS_FOUND
27+
)
28+
return
29+
}
30+
31+
let selected_config: ToolConfig | null = null
32+
33+
if (params.config_id !== undefined) {
34+
selected_config =
35+
code_at_cursor_configs.find(
36+
(c) => get_tool_config_id(c) === params.config_id
37+
) || null
38+
} else if (!params.show_quick_pick) {
39+
const default_config =
40+
await params.api_providers_manager.get_default_code_completions_config()
41+
if (default_config) {
42+
selected_config = default_config
43+
} else {
44+
const recents = params.context.workspaceState.get<string[]>(
45+
RECENTLY_USED_CODE_AT_CURSOR_CONFIG_IDS_STATE_KEY
46+
)
47+
const last_selected_id = recents?.[0]
48+
if (last_selected_id) {
49+
selected_config =
50+
code_at_cursor_configs.find(
51+
(c) => get_tool_config_id(c) == last_selected_id
52+
) || null
53+
}
54+
if (!selected_config && code_at_cursor_configs.length > 0) {
55+
selected_config = code_at_cursor_configs[0]
56+
}
57+
}
58+
}
59+
60+
if (!selected_config || params.show_quick_pick) {
61+
const create_items = () => {
62+
const recent_ids =
63+
params.context.workspaceState.get<string[]>(
64+
RECENTLY_USED_CODE_AT_CURSOR_CONFIG_IDS_STATE_KEY
65+
) || []
66+
67+
const matched_recent_configs: ToolConfig[] = []
68+
const remaining_configs: ToolConfig[] = []
69+
70+
code_at_cursor_configs.forEach((config) => {
71+
const id = get_tool_config_id(config)
72+
if (recent_ids.includes(id)) {
73+
matched_recent_configs.push(config)
74+
} else {
75+
remaining_configs.push(config)
76+
}
77+
})
78+
79+
matched_recent_configs.sort((a, b) => {
80+
const id_a = get_tool_config_id(a)
81+
const id_b = get_tool_config_id(b)
82+
return recent_ids.indexOf(id_a) - recent_ids.indexOf(id_b)
83+
})
84+
85+
const recent_configs = matched_recent_configs
86+
const other_configs = remaining_configs
87+
88+
const map_config_to_item = (config: ToolConfig) => {
89+
const description_parts = [config.provider_name]
90+
if (config.temperature != null) {
91+
description_parts.push(`${config.temperature}`)
92+
}
93+
if (config.reasoning_effort) {
94+
description_parts.push(`${config.reasoning_effort}`)
95+
}
96+
97+
const buttons: vscode.QuickInputButton[] = []
98+
99+
return {
100+
label: config.model,
101+
description: description_parts.join(' · '),
102+
buttons,
103+
config,
104+
id: get_tool_config_id(config)
105+
}
106+
}
107+
108+
const items: (vscode.QuickPickItem & {
109+
config?: ToolConfig
110+
id?: string
111+
})[] = []
112+
113+
if (recent_configs.length > 0) {
114+
items.push({
115+
label: t('common.separator.recently-used'),
116+
kind: vscode.QuickPickItemKind.Separator
117+
})
118+
items.push(...recent_configs.map(map_config_to_item))
119+
}
120+
121+
if (other_configs.length > 0) {
122+
if (recent_configs.length > 0) {
123+
items.push({
124+
label: t('common.config.other'),
125+
kind: vscode.QuickPickItemKind.Separator
126+
})
127+
}
128+
items.push(...other_configs.map(map_config_to_item))
129+
}
130+
131+
return items
132+
}
133+
134+
const quick_pick = vscode.window.createQuickPick()
135+
quick_pick.buttons = [
136+
{
137+
iconPath: new vscode.ThemeIcon('close'),
138+
tooltip: t('common.close')
139+
}
140+
]
141+
quick_pick.items = create_items()
142+
quick_pick.title = t('common.config.title')
143+
quick_pick.placeholder = t('command.code-at-cursor.config.placeholder')
144+
quick_pick.matchOnDescription = true
145+
146+
const items = quick_pick.items as (vscode.QuickPickItem & { id: string })[]
147+
148+
if (items.length > 0) {
149+
const first_selectable = items.find(
150+
(i) => i.kind != vscode.QuickPickItemKind.Separator
151+
)
152+
if (first_selectable) {
153+
quick_pick.activeItems = [first_selectable]
154+
}
155+
}
156+
157+
return new Promise<{ provider: any; config: any } | undefined>(
158+
(resolve) => {
159+
quick_pick.onDidTriggerButton((button) => {
160+
if (button.tooltip == t('common.close')) {
161+
quick_pick.hide()
162+
resolve(undefined)
163+
}
164+
})
165+
166+
quick_pick.onDidAccept(async () => {
167+
const selected = quick_pick.selectedItems[0] as any
168+
quick_pick.hide()
169+
170+
if (!selected || !selected.config) {
171+
resolve(undefined)
172+
return
173+
}
174+
175+
let recents =
176+
params.context.workspaceState.get<string[]>(
177+
RECENTLY_USED_CODE_AT_CURSOR_CONFIG_IDS_STATE_KEY
178+
) || []
179+
recents = [selected.id, ...recents.filter((id) => id != selected.id)]
180+
params.context.workspaceState.update(
181+
RECENTLY_USED_CODE_AT_CURSOR_CONFIG_IDS_STATE_KEY,
182+
recents
183+
)
184+
185+
if (params.panel_provider) {
186+
params.panel_provider.send_message({
187+
command: 'SELECTED_CONFIGURATION_CHANGED',
188+
prompt_type: 'code-at-cursor',
189+
id: selected.id
190+
})
191+
}
192+
193+
const provider = await params.api_providers_manager.get_provider(
194+
selected.config.provider_name
195+
)
196+
if (!provider) {
197+
vscode.window.showErrorMessage(
198+
dictionary.error_message.API_PROVIDER_NOT_FOUND
199+
)
200+
resolve(undefined)
201+
return
202+
}
203+
204+
resolve({
205+
provider,
206+
config: selected.config
207+
})
208+
})
209+
210+
quick_pick.onDidHide(() => {
211+
quick_pick.dispose()
212+
resolve(undefined)
213+
})
214+
215+
quick_pick.show()
216+
}
217+
)
218+
}
219+
220+
const provider = await params.api_providers_manager.get_provider(
221+
selected_config.provider_name
222+
)
223+
224+
if (!provider) {
225+
vscode.window.showErrorMessage(
226+
dictionary.error_message.API_PROVIDER_NOT_FOUND
227+
)
228+
Logger.warn({
229+
function_name: 'get_code_at_cursor_config',
230+
message: 'API provider not found for Code Completions tool.'
231+
})
232+
return
233+
}
234+
235+
return {
236+
provider,
237+
config: selected_config
238+
}
239+
}

0 commit comments

Comments
 (0)