Skip to content

Commit 76bc806

Browse files
committed
Add support for editing custom flags for coding agents in agentic search mode
- on each agent add 'edit' action, allowing appending user-typed flags (as continous string) to the command. Store them globally. - add missing translations to `apps/editor/src/i18n/translations/features/search-files.ts` - 'edit flags' action should appear to the left of the globe icon - place example as placeholder, shortening the desc below it - don't provide example in placeholder, just a word 'Flags' (tranlated) - use 'flag' codicon instead of 'edit' - change '[Fragment]' to 'Invoke CLI headlessly' and add translations └── apps └── editor └── src ├── commands │ ├── copy-paths-command.ts │ └── duplicate-workspace-command.ts ├── constants │ └── state-keys.ts ├── context │ └── context-initialization.ts ├── features │ ├── context-restoration │ │ └── utils │ │ └── source-selector.ts │ └── search-files │ └── search-modes │ └── perform-agent-search-mode │ ├── agents │ │ ├── antigravity.ts │ │ ├── claude.ts │ │ ├── codex.ts │ │ └── opencode.ts │ ├── index.ts │ ├── types.ts │ └── utils.ts ├── i18n │ └── translations │ └── features │ └── search-files.ts └── views └── prompt └── backend ├── message-handlers │ ├── handle-autofill.ts │ ├── handle-save-edit-format.ts │ ├── handle-select-edit-format-instructions.ts │ ├── handle-template-quick-pick.ts │ └── handle-update-last-used-web-configuration.ts └── prompt-view-provider.ts
1 parent a1909af commit 76bc806

3 files changed

Lines changed: 180 additions & 42 deletions

File tree

‎apps/editor/src/constants/state-keys.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ export const LAST_SEARCH_FILES_FOR_CONTEXT_MODE_STATE_KEY =
8585
export const LAST_SELECTED_WORKSPACE_IN_AGENT_SEARCH_STATE_KEY =
8686
'last-selected-workspace-in-agent-search'
8787

88+
export const get_agent_flags_state_key = (cmd: string) =>
89+
`agent-flags-${cmd}`
90+
8891
export const LAST_INTELLIGENT_FILE_SEARCH_SHRINK_STATE_KEY =
8992
'last-intelligent-file-search-shrink'
9093

‎apps/editor/src/features/search-files/search-modes/perform-agent-search-mode/index.ts‎

Lines changed: 77 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import * as path from 'path'
66
import * as fs from 'fs'
77
import {
88
LAST_SELECTED_WORKSPACE_IN_AGENT_SEARCH_STATE_KEY,
9-
LAST_SEARCH_FILES_AGENT_QUERY_STATE_KEY
9+
LAST_SEARCH_FILES_AGENT_QUERY_STATE_KEY,
10+
get_agent_flags_state_key
1011
} from '@/constants/state-keys'
1112
import { extract_paths_from_text } from '@/utils/extract-paths-from-text'
1213
import { get_all_workspace_files } from '@/context/helpers/get-all-workspace-files'
@@ -62,18 +63,22 @@ export const perform_agent_search_mode = async (params: {
6263
return undefined
6364
}
6465

66+
const edit_button = {
67+
iconPath: new vscode.ThemeIcon('flag'),
68+
tooltip: t('feature.search-files.agent.edit-flags')
69+
}
70+
const doc_button = {
71+
iconPath: new vscode.ThemeIcon('globe'),
72+
tooltip: t('feature.search-files.agent.learn-more')
73+
}
74+
6575
const agent_picks = available_agents.map((a) => {
6676
const pick: vscode.QuickPickItem & { cmd: string } = {
6777
label: a.label,
6878
cmd: a.cmd
6979
}
7080

71-
pick.buttons = [
72-
{
73-
iconPath: new vscode.ThemeIcon('globe'),
74-
tooltip: t('feature.search-files.agent.learn-more')
75-
}
76-
]
81+
pick.buttons = [edit_button, doc_button]
7782

7883
return pick
7984
})
@@ -94,32 +99,39 @@ export const perform_agent_search_mode = async (params: {
9499
agent_quick_pick.buttons = [vscode.QuickInputButtons.Back, close_button]
95100
agent_quick_pick.ignoreFocusOut = true
96101

97-
const selected_agent_cmd = await new Promise<string | undefined | 'back'>(
98-
(resolve) => {
99-
let is_resolved = false
100-
101-
agent_quick_pick.onDidTriggerButton((button) => {
102-
if (button === vscode.QuickInputButtons.Back) {
103-
is_resolved = true
104-
resolve('back')
105-
agent_quick_pick.hide()
106-
} else if (button === close_button) {
107-
is_resolved = true
108-
resolve(undefined)
109-
agent_quick_pick.hide()
110-
}
111-
})
102+
const selected_agent_cmd = await new Promise<
103+
string | undefined | 'back' | { edit_agent: string }
104+
>((resolve) => {
105+
let is_resolved = false
106+
107+
agent_quick_pick.onDidTriggerButton((button) => {
108+
if (button === vscode.QuickInputButtons.Back) {
109+
is_resolved = true
110+
resolve('back')
111+
agent_quick_pick.hide()
112+
} else if (button === close_button) {
113+
is_resolved = true
114+
resolve(undefined)
115+
agent_quick_pick.hide()
116+
}
117+
})
112118

113-
agent_quick_pick.onDidTriggerItemButton((e) => {
119+
agent_quick_pick.onDidTriggerItemButton((e) => {
120+
if (e.button === doc_button) {
114121
const agent = available_agents.find((a) => a.cmd == e.item.cmd)
115122
if (agent) {
116123
vscode.env.openExternal(
117124
vscode.Uri.parse(agent.get_documentation_url())
118125
)
119126
}
120-
})
127+
} else if (e.button === edit_button) {
128+
is_resolved = true
129+
resolve({ edit_agent: e.item.cmd })
130+
agent_quick_pick.hide()
131+
}
132+
})
121133

122-
agent_quick_pick.onDidAccept(() => {
134+
agent_quick_pick.onDidAccept(() => {
123135
const selected = agent_quick_pick.selectedItems[0]
124136
if (selected) {
125137
is_resolved = true
@@ -147,6 +159,29 @@ export const perform_agent_search_mode = async (params: {
147159
return undefined
148160
}
149161

162+
if (
163+
typeof selected_agent_cmd === 'object' &&
164+
'edit_agent' in selected_agent_cmd
165+
) {
166+
const cmd = selected_agent_cmd.edit_agent
167+
const key = get_agent_flags_state_key(cmd)
168+
const current_flags =
169+
params.extension_context.globalState.get<string>(key) || ''
170+
171+
const new_flags = await vscode.window.showInputBox({
172+
title: t('feature.search-files.agent.edit-flags'),
173+
prompt: t('feature.search-files.agent.edit-flags-prompt'),
174+
placeHolder: t('feature.search-files.agent.edit-flags-placeholder'),
175+
value: current_flags,
176+
ignoreFocusOut: true
177+
})
178+
179+
if (new_flags !== undefined) {
180+
await params.extension_context.globalState.update(key, new_flags)
181+
}
182+
continue
183+
}
184+
150185
let go_back_to_agent = false
151186

152187
while (true) {
@@ -293,7 +328,23 @@ export const perform_agent_search_mode = async (params: {
293328
if (!agent_info) break
294329

295330
const executable = agent_info.cmd
296-
const args = agent_info.get_args(query)
331+
const base_args = agent_info.get_args(query)
332+
333+
const flags_string =
334+
params.extension_context.globalState.get<string>(
335+
get_agent_flags_state_key(executable)
336+
) || ''
337+
338+
const custom_args: string[] = []
339+
if (flags_string.trim()) {
340+
const regex = /([^\s'"]+)|"([^"]*)"|'([^']*)'/g
341+
let match
342+
while ((match = regex.exec(flags_string)) !== null) {
343+
custom_args.push(match[1] || match[2] || match[3])
344+
}
345+
}
346+
347+
const args = [...base_args, ...custom_args]
297348

298349
let agent_output = ''
299350
let raw_stream_output = ''

‎apps/editor/src/i18n/translations/features/search-files.ts‎

Lines changed: 100 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,21 @@ export const translations = {
217217
},
218218
'feature.search-files.mode.phrase-description': {
219219
en: 'Type the exact phrase',
220+
pl: 'Wpisz dokładną frazę',
221+
'zh-cn': '输入确切的短语',
222+
ja: '完全なフレーズを入力',
223+
'zh-tw': '輸入確切的短語',
224+
de: 'Geben Sie die genaue Phrase ein',
225+
es: 'Escriba la frase exacta',
226+
fr: 'Tapez la phrase exacte',
227+
'pt-br': 'Digite a frase exata',
228+
ru: 'Введите точную фразу',
229+
ko: '정확한 구문을 입력하세요',
230+
it: 'Digita la frase esatta',
231+
tr: 'Tam ifadeyi yazın',
232+
cs: 'Zadejte přesnou frázi',
233+
hu: 'Írja be a pontos kifejezést',
234+
bg: 'Въведете точната фраза'
220235
},
221236
'feature.search-files.mode.keywords': {
222237
en: 'Keywords',
@@ -238,6 +253,21 @@ export const translations = {
238253
},
239254
'feature.search-files.mode.keywords-description': {
240255
en: 'List keywords to match',
256+
pl: 'Wypisz słowa kluczowe do dopasowania',
257+
'zh-cn': '列出要匹配的关键字',
258+
ja: '一致させるキーワードをリストアップ',
259+
'zh-tw': '列出要匹配的關鍵字',
260+
de: 'Schlüsselwörter zur Übereinstimmung auflisten',
261+
es: 'Listar palabras clave para coincidir',
262+
fr: 'Lister les mots-clés à faire correspondre',
263+
'pt-br': 'Listar palavras-chave para corresponder',
264+
ru: 'Перечислите ключевые слова для поиска',
265+
ko: '일치시킬 키워드 목록 작성',
266+
it: 'Elenca le parole chiave da far corrispondere',
267+
tr: 'Eşleştirilecek anahtar kelimeleri listeleyin',
268+
cs: 'Seznam klíčových slov k vyhledání',
269+
hu: 'Sorolja fel az egyeztetni kívánt kulcsszavakat',
270+
bg: 'Избройте ключови думи за съвпадение'
241271
},
242272
'feature.search-files.keywords.match-mode.title': {
243273
en: 'Keywords Match Mode',
@@ -438,22 +468,22 @@ export const translations = {
438468
bg: 'Агент'
439469
},
440470
'feature.search-files.mode.agent-description': {
441-
en: 'Invoke headless CLI',
442-
pl: 'Wywołaj headless CLI',
443-
'zh-cn': '调用无头 CLI',
444-
ja: 'ヘッドレスCLIを呼び出す',
445-
'zh-tw': '呼叫無頭 CLI',
446-
de: 'Headless-CLI aufrufen',
447-
es: 'Invocar CLI headless',
448-
fr: 'Invoquer la CLI headless',
449-
'pt-br': 'Invocar CLI headless',
450-
ru: 'Вызвать headless CLI',
451-
ko: '헤드리스 CLI 호출',
452-
it: 'Invoca CLI headless',
453-
tr: 'Headless CLI\'ı çağır',
454-
cs: 'Vyvolat headless CLI',
455-
hu: 'Headless CLI meghívása',
456-
bg: 'Извикване на headless CLI'
471+
en: 'Invoke CLI headlessly',
472+
pl: 'Uruchom CLI w trybie headless',
473+
'zh-cn': '以无头模式调用 CLI',
474+
ja: 'ヘッドレスでCLIを実行',
475+
'zh-tw': '以無頭模式呼叫 CLI',
476+
de: 'CLI headless aufrufen',
477+
es: 'Invocar CLI de forma headless',
478+
fr: 'Invoquer le CLI en mode headless',
479+
'pt-br': 'Invocar CLI de forma headless',
480+
ru: 'Запустить CLI в headless-режиме',
481+
ko: '헤드리스로 CLI 호출',
482+
it: 'Richiamare CLI in modalità headless',
483+
tr: 'CLIyi headless olarak çalıştır',
484+
cs: 'Spustit CLI headless',
485+
hu: 'CLI hívása headless módban',
486+
bg: 'Извикване на CLI в headless режим'
457487
},
458488
'feature.search-files.prompt.intelligent': {
459489
en: 'Enter natural language search query.',
@@ -1102,5 +1132,59 @@ export const translations = {
11021132
cs: 'Další informace',
11031133
hu: 'Tudjon meg többet',
11041134
bg: 'Научете повече'
1135+
},
1136+
'feature.search-files.agent.edit-flags': {
1137+
en: 'Edit flags',
1138+
pl: 'Edytuj flagi',
1139+
'zh-cn': '编辑标志',
1140+
ja: 'フラグを編集',
1141+
'zh-tw': '編輯標誌',
1142+
de: 'Flags bearbeiten',
1143+
es: 'Editar banderas',
1144+
fr: 'Modifier les drapeaux',
1145+
'pt-br': 'Editar flags',
1146+
ru: 'Редактировать флаги',
1147+
ko: '플래그 편집',
1148+
it: 'Modifica flag',
1149+
tr: 'Bayrakları düzenle',
1150+
cs: 'Upravit příznaky',
1151+
hu: 'Jelzők szerkesztése',
1152+
bg: 'Редактиране на флагове'
1153+
},
1154+
'feature.search-files.agent.edit-flags-prompt': {
1155+
en: 'Enter additional flags for this agent',
1156+
pl: 'Wprowadź dodatkowe flagi dla tego agenta',
1157+
'zh-cn': '输入此代理的其他标志',
1158+
ja: 'このエージェントの追加フラグを入力してください',
1159+
'zh-tw': '輸入此代理的其他標誌',
1160+
de: 'Geben Sie zusätzliche Flags für diesen Agenten ein',
1161+
es: 'Ingrese banderas adicionales para este agente',
1162+
fr: 'Entrez des drapeaux supplémentaires pour cet agent',
1163+
'pt-br': 'Insira flags adicionais para este agente',
1164+
ru: 'Введите дополнительные флаги для этого агента',
1165+
ko: '이 에이전트에 대한 추가 플래그를 입력하세요',
1166+
it: 'Inserisci flag aggiuntivi per questo agente',
1167+
tr: 'Bu ajan için ek bayraklar girin',
1168+
cs: 'Zadejte další příznaky pro tohoto agenta',
1169+
hu: 'Adjon meg további jelzőket ehhez az ügynökhöz',
1170+
bg: 'Въведете допълнителни флагове за този агент'
1171+
},
1172+
'feature.search-files.agent.edit-flags-placeholder': {
1173+
en: 'Flags',
1174+
pl: 'Flagi',
1175+
'zh-cn': '标志',
1176+
ja: 'フラグ',
1177+
'zh-tw': '標誌',
1178+
de: 'Flags',
1179+
es: 'Banderas',
1180+
fr: 'Drapeaux',
1181+
'pt-br': 'Flags',
1182+
ru: 'Флаги',
1183+
ko: '플래그',
1184+
it: 'Flag',
1185+
tr: 'Bayraklar',
1186+
cs: 'Příznaky',
1187+
hu: 'Jelzők',
1188+
bg: 'Флагове'
11051189
}
11061190
} as const

0 commit comments

Comments
 (0)