Skip to content

Commit f3c40f4

Browse files
committed
Enhance API tool configuration quick picks with direct reordering and default management capabilities
1 parent 3e0ae84 commit f3c40f4

4 files changed

Lines changed: 214 additions & 16 deletions

File tree

packages/vscode/src/commands/code-completion-commands.ts

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import he from 'he'
99
import { PROVIDERS } from '@shared/constants/providers'
1010
import { LAST_SELECTED_CODE_COMPLETION_CONFIG_INDEX_STATE_KEY } from '../constants/state-keys'
1111
import { DEFAULT_TEMPERATURE } from '@shared/constants/api-tools'
12+
import { ToolConfig } from '@/services/api-providers-manager'
1213

1314
async function build_completion_payload(params: {
1415
document: vscode.TextDocument
@@ -101,7 +102,7 @@ async function get_code_completion_config(
101102
context: vscode.ExtensionContext,
102103
config_index?: number
103104
): Promise<{ provider: any; config: any } | undefined> {
104-
const code_completions_configs =
105+
let code_completions_configs =
105106
await api_providers_manager.get_code_completions_tool_configs()
106107

107108
if (code_completions_configs.length == 0) {
@@ -125,8 +126,39 @@ async function get_code_completion_config(
125126
}
126127

127128
if (!selected_config || show_quick_pick) {
129+
const move_up_button = {
130+
iconPath: new vscode.ThemeIcon('chevron-up'),
131+
tooltip: 'Move up'
132+
}
133+
134+
const move_down_button = {
135+
iconPath: new vscode.ThemeIcon('chevron-down'),
136+
tooltip: 'Move down'
137+
}
138+
139+
const set_default_button = {
140+
iconPath: new vscode.ThemeIcon('pass'),
141+
tooltip: 'Set as default'
142+
}
143+
144+
const unset_default_button = {
145+
iconPath: new vscode.ThemeIcon('pass-filled'),
146+
tooltip: 'Unset default'
147+
}
148+
128149
const create_items = async () => {
129-
return code_completions_configs.map((config, index) => {
150+
const default_config =
151+
await api_providers_manager.get_default_code_completions_config()
152+
return code_completions_configs.map((config: ToolConfig, index) => {
153+
const is_default =
154+
default_config &&
155+
default_config.provider_type == config.provider_type &&
156+
default_config.provider_name == config.provider_name &&
157+
default_config.model == config.model &&
158+
default_config.temperature == config.temperature &&
159+
default_config.reasoning_effort == config.reasoning_effort &&
160+
default_config.max_concurrency == config.max_concurrency
161+
130162
const description_parts = [config.provider_name]
131163
if (config.temperature != DEFAULT_TEMPERATURE['code-completions']) {
132164
description_parts.push(`${config.temperature}`)
@@ -135,18 +167,44 @@ async function get_code_completion_config(
135167
description_parts.push(`${config.reasoning_effort}`)
136168
}
137169

170+
let buttons = []
171+
if (code_completions_configs.length > 1) {
172+
const is_first_item = index == 0
173+
const is_last_item = index == code_completions_configs.length - 1
174+
175+
const navigation_buttons = []
176+
if (!is_first_item) {
177+
navigation_buttons.push(move_up_button)
178+
}
179+
if (!is_last_item) {
180+
navigation_buttons.push(move_down_button)
181+
}
182+
183+
if (!is_default) {
184+
buttons = [...navigation_buttons, set_default_button]
185+
} else {
186+
buttons = [...navigation_buttons, unset_default_button]
187+
}
188+
} else {
189+
if (!is_default) {
190+
buttons = [set_default_button]
191+
} else {
192+
buttons = [unset_default_button]
193+
}
194+
}
195+
138196
return {
139-
label: config.model,
197+
label: is_default ? `$(check) ${config.model}` : config.model,
140198
description: description_parts.join(' · '),
199+
buttons,
141200
config,
142201
index
143202
}
144203
})
145204
}
146205

147206
const quick_pick = vscode.window.createQuickPick()
148-
const items = await create_items()
149-
quick_pick.items = items
207+
quick_pick.items = await create_items()
150208
quick_pick.placeholder = 'Select code completions configuration'
151209
quick_pick.matchOnDescription = true
152210

@@ -155,6 +213,7 @@ async function get_code_completion_config(
155213
0
156214
)
157215

216+
const items = quick_pick.items
158217
if (last_selected_index >= 0 && last_selected_index < items.length) {
159218
quick_pick.activeItems = [items[last_selected_index]]
160219
} else if (items.length > 0) {
@@ -163,6 +222,46 @@ async function get_code_completion_config(
163222

164223
return new Promise<{ provider: any; config: any } | undefined>(
165224
(resolve) => {
225+
quick_pick.onDidTriggerItemButton(async (event) => {
226+
const item = event.item as any
227+
228+
if (
229+
event.button === move_up_button ||
230+
event.button === move_down_button
231+
) {
232+
const current_index = item.index
233+
const is_moving_up = event.button === move_up_button
234+
235+
const min_index = 0
236+
const max_index = code_completions_configs.length - 1
237+
const new_index = is_moving_up
238+
? Math.max(min_index, current_index - 1)
239+
: Math.min(max_index, current_index + 1)
240+
241+
if (new_index == current_index) {
242+
return
243+
}
244+
245+
const reordered_configs = [...code_completions_configs]
246+
const [moved_config] = reordered_configs.splice(current_index, 1)
247+
reordered_configs.splice(new_index, 0, moved_config)
248+
code_completions_configs = reordered_configs
249+
await api_providers_manager.save_code_completions_tool_configs(
250+
code_completions_configs
251+
)
252+
253+
quick_pick.items = await create_items()
254+
} else if (event.button === set_default_button) {
255+
await api_providers_manager.set_default_code_completions_config(
256+
item.config
257+
)
258+
quick_pick.items = await create_items()
259+
} else if (event.button === unset_default_button) {
260+
await api_providers_manager.set_default_code_completions_config(null)
261+
quick_pick.items = await create_items()
262+
}
263+
})
264+
166265
quick_pick.onDidAccept(async () => {
167266
const selected = quick_pick.selectedItems[0] as any
168267
quick_pick.hide()

packages/vscode/src/commands/edit-context-commands.ts

Lines changed: 104 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ import { PROVIDERS } from '@shared/constants/providers'
88
import { DEFAULT_TEMPERATURE } from '@shared/constants/api-tools'
99
import { LAST_SELECTED_EDIT_CONTEXT_CONFIG_INDEX_STATE_KEY } from '@/constants/state-keys'
1010
import { EditFormat } from '@shared/types/edit-format'
11+
import { ToolConfig } from '@/services/api-providers-manager'
1112

1213
const get_edit_context_config = async (
1314
api_providers_manager: ApiProvidersManager,
1415
show_quick_pick: boolean = false,
1516
context: vscode.ExtensionContext,
1617
config_index?: number
1718
): Promise<{ provider: any; config: any } | undefined> => {
18-
const edit_context_configs =
19+
let edit_context_configs =
1920
await api_providers_manager.get_edit_context_tool_configs()
2021

2122
if (edit_context_configs.length == 0) {
@@ -37,8 +38,39 @@ const get_edit_context_config = async (
3738
}
3839

3940
if (!selected_config || show_quick_pick) {
41+
const move_up_button = {
42+
iconPath: new vscode.ThemeIcon('chevron-up'),
43+
tooltip: 'Move up'
44+
}
45+
46+
const move_down_button = {
47+
iconPath: new vscode.ThemeIcon('chevron-down'),
48+
tooltip: 'Move down'
49+
}
50+
51+
const set_default_button = {
52+
iconPath: new vscode.ThemeIcon('pass'),
53+
tooltip: 'Set as default'
54+
}
55+
56+
const unset_default_button = {
57+
iconPath: new vscode.ThemeIcon('pass-filled'),
58+
tooltip: 'Unset default'
59+
}
60+
4061
const create_items = async () => {
41-
return edit_context_configs.map((config, index) => {
62+
const default_config =
63+
await api_providers_manager.get_default_edit_context_config()
64+
return edit_context_configs.map((config: ToolConfig, index) => {
65+
const is_default =
66+
default_config &&
67+
default_config.provider_type == config.provider_type &&
68+
default_config.provider_name == config.provider_name &&
69+
default_config.model == config.model &&
70+
default_config.temperature == config.temperature &&
71+
default_config.reasoning_effort == config.reasoning_effort &&
72+
default_config.max_concurrency == config.max_concurrency
73+
4274
const description_parts = [config.provider_name]
4375
if (config.temperature != DEFAULT_TEMPERATURE['edit-context']) {
4476
description_parts.push(`${config.temperature}`)
@@ -47,18 +79,44 @@ const get_edit_context_config = async (
4779
description_parts.push(`${config.reasoning_effort}`)
4880
}
4981

82+
let buttons = []
83+
if (edit_context_configs.length > 1) {
84+
const is_first_item = index == 0
85+
const is_last_item = index == edit_context_configs.length - 1
86+
87+
const navigation_buttons = []
88+
if (!is_first_item) {
89+
navigation_buttons.push(move_up_button)
90+
}
91+
if (!is_last_item) {
92+
navigation_buttons.push(move_down_button)
93+
}
94+
95+
if (!is_default) {
96+
buttons = [...navigation_buttons, set_default_button]
97+
} else {
98+
buttons = [...navigation_buttons, unset_default_button]
99+
}
100+
} else {
101+
if (!is_default) {
102+
buttons = [set_default_button]
103+
} else {
104+
buttons = [unset_default_button]
105+
}
106+
}
107+
50108
return {
51-
label: config.model,
109+
label: is_default ? `$(check) ${config.model}` : config.model,
52110
description: description_parts.join(' · '),
111+
buttons,
53112
config,
54113
index
55114
}
56115
})
57116
}
58117

59118
const quick_pick = vscode.window.createQuickPick()
60-
const items = await create_items()
61-
quick_pick.items = items
119+
quick_pick.items = await create_items()
62120
quick_pick.placeholder = 'Select configuration'
63121
quick_pick.matchOnDescription = true
64122

@@ -67,6 +125,7 @@ const get_edit_context_config = async (
67125
0
68126
)
69127

128+
const items = quick_pick.items
70129
if (last_selected_index >= 0 && last_selected_index < items.length) {
71130
quick_pick.activeItems = [items[last_selected_index]]
72131
} else if (items.length > 0) {
@@ -75,6 +134,46 @@ const get_edit_context_config = async (
75134

76135
return new Promise<{ provider: any; config: any } | undefined>(
77136
(resolve) => {
137+
quick_pick.onDidTriggerItemButton(async (event) => {
138+
const item = event.item as any
139+
140+
if (
141+
event.button === move_up_button ||
142+
event.button === move_down_button
143+
) {
144+
const current_index = item.index
145+
const is_moving_up = event.button === move_up_button
146+
147+
const min_index = 0
148+
const max_index = edit_context_configs.length - 1
149+
const new_index = is_moving_up
150+
? Math.max(min_index, current_index - 1)
151+
: Math.min(max_index, current_index + 1)
152+
153+
if (new_index == current_index) {
154+
return
155+
}
156+
157+
const reordered_configs = [...edit_context_configs]
158+
const [moved_config] = reordered_configs.splice(current_index, 1)
159+
reordered_configs.splice(new_index, 0, moved_config)
160+
edit_context_configs = reordered_configs
161+
await api_providers_manager.save_edit_context_tool_configs(
162+
edit_context_configs
163+
)
164+
165+
quick_pick.items = await create_items()
166+
} else if (event.button === set_default_button) {
167+
await api_providers_manager.set_default_edit_context_config(
168+
item.config
169+
)
170+
quick_pick.items = await create_items()
171+
} else if (event.button === unset_default_button) {
172+
await api_providers_manager.set_default_edit_context_config(null)
173+
quick_pick.items = await create_items()
174+
}
175+
})
176+
78177
quick_pick.onDidAccept(async () => {
79178
const selected = quick_pick.selectedItems[0] as any
80179
quick_pick.hide()

packages/vscode/src/commands/open-settings-command/setup-api-tool-multi-config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,17 +114,17 @@ export const setup_api_tool_multi_config = async (params: {
114114

115115
const edit_button = {
116116
iconPath: new vscode.ThemeIcon('edit'),
117-
tooltip: 'Edit configuration'
117+
tooltip: 'Edit'
118118
}
119119

120120
const duplicate_button = {
121121
iconPath: new vscode.ThemeIcon('copy'),
122-
tooltip: 'Duplicate configuration'
122+
tooltip: 'Duplicate'
123123
}
124124

125125
const delete_button = {
126126
iconPath: new vscode.ThemeIcon('trash'),
127-
tooltip: 'Delete configuration'
127+
tooltip: 'Delete'
128128
}
129129

130130
const move_up_button = {
@@ -234,7 +234,7 @@ export const setup_api_tool_multi_config = async (params: {
234234
}
235235

236236
return {
237-
label: is_default ? `Default: ${config.model}` : config.model,
237+
label: is_default ? `$(check) ${config.model}` : config.model,
238238
description: description_parts.join(' · '),
239239
buttons,
240240
config,

packages/vscode/src/services/api-providers-manager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export class ApiProvidersManager {
132132
return this._validate_tool_config(config)
133133
}
134134

135-
public async set_default_code_completions_config(config: ToolConfig) {
135+
public async set_default_code_completions_config(config: ToolConfig | null) {
136136
await this._vscode.globalState.update(
137137
DEFAULT_CODE_COMPLETIONS_CONFIGURATION_STATE_KEY,
138138
config
@@ -169,7 +169,7 @@ export class ApiProvidersManager {
169169
return this._validate_tool_config(config)
170170
}
171171

172-
public async set_default_edit_context_config(config: ToolConfig) {
172+
public async set_default_edit_context_config(config: ToolConfig | null) {
173173
await this._vscode.globalState.update(
174174
DEFAULT_EDIT_CONTEXT_CONFIGURATION_STATE_KEY,
175175
config

0 commit comments

Comments
 (0)