Skip to content

Commit 1034c12

Browse files
authored
add manage prompt file/instructions commands (microsoft#250242)
1 parent 93a3972 commit 1034c12

File tree

5 files changed

+200
-80
lines changed

5 files changed

+200
-80
lines changed

src/vs/workbench/contrib/chat/browser/actions/promptActions/chatAttachInstructionsAction.ts

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { IChatWidget, IChatWidgetService } from '../../chat.js';
6+
import { ChatViewId, IChatWidget, IChatWidgetService } from '../../chat.js';
77
import { CHAT_CATEGORY } from '../chatActions.js';
88
import { URI } from '../../../../../../base/common/uri.js';
99
import { localize, localize2 } from '../../../../../../nls.js';
@@ -32,12 +32,19 @@ import { KeybindingWeight } from '../../../../../../platform/keybinding/common/k
3232
import { ICodeEditorService } from '../../../../../../editor/browser/services/codeEditorService.js';
3333
import { INSTRUCTIONS_LANGUAGE_ID } from '../../../common/promptSyntax/constants.js';
3434
import { CancellationToken } from '../../../../../../base/common/cancellation.js';
35+
import { IOpenerService } from '../../../../../../platform/opener/common/opener.js';
3536

3637
/**
3738
* Action ID for the `Attach Instruction` action.
3839
*/
3940
const ATTACH_INSTRUCTIONS_ACTION_ID = 'workbench.action.chat.attach.instructions';
4041

42+
/**
43+
* Action ID for the `Manage Instruction` action.
44+
*/
45+
const MANAGE_INSTRUCTIONS_ACTION_ID = 'workbench.action.chat.manage.instructions';
46+
47+
4148
/**
4249
* Options for the {@link AttachInstructionsAction} action.
4350
*/
@@ -93,7 +100,6 @@ class AttachInstructionsAction extends Action2 {
93100
options?: IAttachInstructionsActionOptions,
94101
): Promise<void> {
95102
const viewsService = accessor.get(IViewsService);
96-
const promptsService = accessor.get(IPromptsService);
97103
const commandService = accessor.get(ICommandService);
98104
const instaService = accessor.get(IInstantiationService);
99105

@@ -130,14 +136,12 @@ class AttachInstructionsAction extends Action2 {
130136
return;
131137
}
132138

133-
// find all prompt files in the user workspace
134-
const promptFiles = await promptsService.listPromptFiles(PromptsType.instructions, CancellationToken.None);
135139
const placeholder = localize(
136140
'commands.instructions.select-dialog.placeholder',
137141
'Select instructions files to attach',
138142
);
139143

140-
const result = await pickers.selectPromptFile({ promptFiles, resource, placeholder, type: PromptsType.instructions });
144+
const result = await pickers.selectPromptFile({ resource, placeholder, type: PromptsType.instructions });
141145

142146
if (result !== undefined) {
143147
const widget = await attachInstructionsFiles(
@@ -149,6 +153,48 @@ class AttachInstructionsAction extends Action2 {
149153
}
150154
}
151155

156+
class ManageInstructionsFilesAction extends Action2 {
157+
constructor() {
158+
super({
159+
id: MANAGE_INSTRUCTIONS_ACTION_ID,
160+
title: localize2('manage-instructions.capitalized.ellipses', "Manage Instructions Files..."),
161+
icon: Codicon.bookmark,
162+
f1: true,
163+
precondition: ContextKeyExpr.and(PromptsConfig.enabledCtx, ChatContextKeys.enabled),
164+
category: CHAT_CATEGORY,
165+
menu: {
166+
id: MenuId.ViewTitle,
167+
168+
when: ContextKeyExpr.equals('view', ChatViewId),
169+
order: 11,
170+
group: '1_open'
171+
},
172+
173+
});
174+
}
175+
176+
public override async run(
177+
accessor: ServicesAccessor,
178+
): Promise<void> {
179+
const openerService = accessor.get(IOpenerService);
180+
const instaService = accessor.get(IInstantiationService);
181+
182+
const pickers = instaService.createInstance(PromptFilePickers);
183+
184+
const placeholder = localize(
185+
'commands.prompt.manage-dialog.placeholder',
186+
'Select the instructions file to edit'
187+
);
188+
189+
const result = await pickers.selectPromptFile({ placeholder, type: PromptsType.instructions, optionEdit: false });
190+
if (result !== undefined) {
191+
await openerService.open(result.promptFile);
192+
}
193+
194+
}
195+
}
196+
197+
152198
function getFocusedChatWidget(accessor: ServicesAccessor): IChatWidget | undefined {
153199
const chatWidgetService = accessor.get(IChatWidgetService);
154200

@@ -182,6 +228,7 @@ const getActiveInstructionsFileUri = (accessor: ServicesAccessor): URI | undefin
182228
*/
183229
export const registerAttachPromptActions = () => {
184230
registerAction2(AttachInstructionsAction);
231+
registerAction2(ManageInstructionsFilesAction);
185232
};
186233

187234

src/vs/workbench/contrib/chat/browser/actions/promptActions/chatModeActions.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import { CHAT_CATEGORY } from '../chatActions.js';
77
import { Codicon } from '../../../../../../base/common/codicons.js';
88
import { ChatContextKeys } from '../../../common/chatContextKeys.js';
9-
import { IPromptsService } from '../../../common/promptSyntax/service/types.js';
109
import { localize, localize2 } from '../../../../../../nls.js';
1110
import { PromptsConfig } from '../../../../../../platform/prompts/common/config.js';
1211
import { PromptFilePickers } from './dialogs/askToSelectPrompt/promptFilePickers.js';
@@ -16,7 +15,6 @@ import { Action2, MenuId, registerAction2 } from '../../../../../../platform/act
1615
import { IInstantiationService } from '../../../../../../platform/instantiation/common/instantiation.js';
1716
import { PromptsType } from '../../../../../../platform/prompts/common/prompts.js';
1817
import { IOpenerService } from '../../../../../../platform/opener/common/opener.js';
19-
import { CancellationToken } from '../../../../../../base/common/cancellation.js';
2018

2119
/**
2220
* Action ID for the `Manage Custom Chat Mode` action.
@@ -27,7 +25,7 @@ class ManageModeAction extends Action2 {
2725
constructor() {
2826
super({
2927
id: MANAGE_CUSTOM_MODE_ACTION_ID,
30-
title: localize2('manage-mode.capitalized', "Manage Custom Chat Modes..."),
28+
title: localize2('manage-mode.capitalized', "Manage Chat Modes..."),
3129
shortTitle: localize('manage-mode', "Manage Modes..."),
3230
icon: Codicon.bookmark,
3331
f1: true,
@@ -45,30 +43,23 @@ class ManageModeAction extends Action2 {
4543
public override async run(
4644
accessor: ServicesAccessor,
4745
): Promise<void> {
48-
const promptsService = accessor.get(IPromptsService);
4946
const openerService = accessor.get(IOpenerService);
5047
const instaService = accessor.get(IInstantiationService);
5148

5249
const pickers = instaService.createInstance(PromptFilePickers);
5350

54-
// find all prompt files in the user workspace
55-
const promptFiles = await promptsService.listPromptFiles(PromptsType.mode, CancellationToken.None);
5651
const placeholder = localize(
5752
'commands.mode.select-dialog.placeholder',
5853
'Select the custom chat mode to edit'
5954
);
6055

61-
const result = await pickers.selectPromptFile({ promptFiles, placeholder, type: PromptsType.mode, optionEdit: false });
62-
63-
if (result === undefined) {
64-
return;
56+
const result = await pickers.selectPromptFile({ placeholder, type: PromptsType.mode, optionEdit: false });
57+
if (result !== undefined) {
58+
await openerService.open(result.promptFile);
6559
}
66-
openerService.open(result.promptFile);
6760
}
6861
}
6962

70-
71-
7263
/**
7364
* Helper to register all the `Run Current Prompt` actions.
7465
*/

src/vs/workbench/contrib/chat/browser/actions/promptActions/chatRunPromptAction.ts

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { IChatWidget } from '../../chat.js';
6+
import { ChatViewId, IChatWidget } from '../../chat.js';
77
import { CHAT_CATEGORY } from '../chatActions.js';
88
import { URI } from '../../../../../../base/common/uri.js';
99
import { OS } from '../../../../../../base/common/platform.js';
@@ -14,7 +14,6 @@ import { ThemeIcon } from '../../../../../../base/common/themables.js';
1414
import { ResourceContextKey } from '../../../../../common/contextkeys.js';
1515
import { KeyCode, KeyMod } from '../../../../../../base/common/keyCodes.js';
1616
import { PROMPT_LANGUAGE_ID } from '../../../common/promptSyntax/constants.js';
17-
import { IPromptsService } from '../../../common/promptSyntax/service/types.js';
1817
import { ILocalizedString, localize, localize2 } from '../../../../../../nls.js';
1918
import { UILabelProvider } from '../../../../../../base/common/keybindingLabels.js';
2019
import { ICommandAction } from '../../../../../../platform/action/common/action.js';
@@ -31,7 +30,7 @@ import { KeybindingWeight } from '../../../../../../platform/keybinding/common/k
3130
import { Action2, MenuId, registerAction2 } from '../../../../../../platform/actions/common/actions.js';
3231
import { IInstantiationService } from '../../../../../../platform/instantiation/common/instantiation.js';
3332
import { PromptsType } from '../../../../../../platform/prompts/common/prompts.js';
34-
import { CancellationToken } from '../../../../../../base/common/cancellation.js';
33+
import { IOpenerService } from '../../../../../../platform/opener/common/opener.js';
3534

3635
/**
3736
* Condition for the `Run Current Prompt` action.
@@ -57,6 +56,11 @@ const RUN_CURRENT_PROMPT_ACTION_ID = 'workbench.action.chat.run.prompt.current';
5756
*/
5857
const RUN_SELECTED_PROMPT_ACTION_ID = 'workbench.action.chat.run.prompt';
5958

59+
/**
60+
* Action ID for the `Manage Prompt Files...` action.
61+
*/
62+
const MANAGE_SELECTED_PROMPT_ACTION_ID = 'workbench.action.chat.manage.prompts';
63+
6064
/**
6165
* Constructor options for the `Run Prompt` base action.
6266
*/
@@ -203,21 +207,18 @@ class RunSelectedPromptAction extends Action2 {
203207
accessor: ServicesAccessor,
204208
): Promise<void> {
205209
const viewsService = accessor.get(IViewsService);
206-
const promptsService = accessor.get(IPromptsService);
207210
const commandService = accessor.get(ICommandService);
208211
const instaService = accessor.get(IInstantiationService);
209212

210213
const pickers = instaService.createInstance(PromptFilePickers);
211214

212-
// find all prompt files in the user workspace
213-
const promptFiles = await promptsService.listPromptFiles(PromptsType.prompt, CancellationToken.None);
214215
const placeholder = localize(
215216
'commands.prompt.select-dialog.placeholder',
216217
'Select the prompt file to run (hold {0}-key to use in new chat)',
217218
UILabelProvider.modifierLabels[OS].ctrlKey
218219
);
219220

220-
const result = await pickers.selectPromptFile({ promptFiles, placeholder, type: PromptsType.prompt });
221+
const result = await pickers.selectPromptFile({ placeholder, type: PromptsType.prompt });
221222

222223
if (result === undefined) {
223224
return;
@@ -237,6 +238,45 @@ class RunSelectedPromptAction extends Action2 {
237238
}
238239
}
239240

241+
class ManagePromptFilesAction extends Action2 {
242+
constructor() {
243+
super({
244+
id: MANAGE_SELECTED_PROMPT_ACTION_ID,
245+
title: localize2('manage-prompts.capitalized.ellipses', "Manage Prompt Files..."),
246+
icon: Codicon.bookmark,
247+
f1: true,
248+
precondition: ContextKeyExpr.and(PromptsConfig.enabledCtx, ChatContextKeys.enabled),
249+
category: CHAT_CATEGORY,
250+
menu: {
251+
id: MenuId.ViewTitle,
252+
when: ContextKeyExpr.equals('view', ChatViewId),
253+
order: 10,
254+
group: '1_open'
255+
},
256+
257+
});
258+
}
259+
260+
public override async run(
261+
accessor: ServicesAccessor,
262+
): Promise<void> {
263+
const openerService = accessor.get(IOpenerService);
264+
const instaService = accessor.get(IInstantiationService);
265+
266+
const pickers = instaService.createInstance(PromptFilePickers);
267+
268+
const placeholder = localize(
269+
'commands.prompt.manage-dialog.placeholder',
270+
'Select the prompt file to open'
271+
);
272+
273+
const result = await pickers.selectPromptFile({ placeholder, type: PromptsType.prompt, optionEdit: false });
274+
if (result !== undefined) {
275+
await openerService.open(result.promptFile);
276+
}
277+
}
278+
}
279+
240280

241281
/**
242282
* Gets `URI` of a prompt file open in an active editor instance, if any.
@@ -305,4 +345,5 @@ export const registerRunPromptActions = () => {
305345
registerAction2(RunCurrentPromptInNewChatAction);
306346
registerAction2(RunCurrentPromptAction);
307347
registerAction2(RunSelectedPromptAction);
348+
registerAction2(ManagePromptFilesAction);
308349
};

0 commit comments

Comments
 (0)