Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/prompts/node/panel/vscode.tsx
13405 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as l10n from '@vscode/l10n';
7
import { BasePromptElementProps, PromptElement, PromptPiece, PromptSizing, SystemMessage, TextChunk, UserMessage } from '@vscode/prompt-tsx';
8
import type * as vscode from 'vscode';
9
import { ChatFetchResponseType, ChatLocation } from '../../../../platform/chat/common/commonTypes';
10
import { EmbeddingType, IEmbeddingsComputer } from '../../../../platform/embeddings/common/embeddingsComputer';
11
import { CommandListItem, ICombinedEmbeddingIndex, SettingListItem, settingItemToContext } from '../../../../platform/embeddings/common/vscodeIndex';
12
import { IEndpointProvider } from '../../../../platform/endpoint/common/endpointProvider';
13
import { IEnvService } from '../../../../platform/env/common/envService';
14
import { ILogService } from '../../../../platform/log/common/logService';
15
import { IChatEndpoint } from '../../../../platform/networking/common/networking';
16
import { IReleaseNotesService } from '../../../../platform/releaseNotes/common/releaseNotesService';
17
import { reportProgressOnSlowPromise } from '../../../../util/common/progress';
18
import { sanitizeVSCodeVersion } from '../../../../util/common/vscodeVersion';
19
import { IInstantiationService } from '../../../../util/vs/platform/instantiation/common/instantiation';
20
import { ChatResponseProgressPart } from '../../../../vscodeTypes';
21
import { Turn } from '../../../prompt/common/conversation';
22
import { IBuildPromptContext } from '../../../prompt/common/intents';
23
import { ToolName } from '../../../tools/common/toolNames';
24
import { CopilotIdentityRules } from '../base/copilotIdentity';
25
import { InstructionMessage } from '../base/instructionMessage';
26
import { PromptRenderer } from '../base/promptRenderer';
27
import { ResponseTranslationRules } from '../base/responseTranslationRules';
28
import { SafetyRules } from '../base/safetyRules';
29
import { Tag } from '../base/tag';
30
import { ChatToolReferences, ChatVariablesAndQuery } from './chatVariables';
31
import { ConversationHistoryWithTools, HistoryWithInstructions } from './conversationHistory';
32
import { ChatToolCalls } from './toolCalling';
33
import { UnsafeCodeBlock } from './unsafeElements';
34
35
export interface VscodePromptProps extends BasePromptElementProps {
36
promptContext: IBuildPromptContext;
37
endpoint: IChatEndpoint;
38
}
39
40
export interface VscodePromptState {
41
settings: SettingListItem[];
42
commands: CommandListItem[];
43
query: string;
44
releaseNotes?: { version: string; notes: string }[];
45
currentVersion?: string;
46
}
47
48
export class VscodePrompt extends PromptElement<VscodePromptProps, VscodePromptState> {
49
50
constructor(props: VscodePromptProps,
51
@ILogService private readonly logService: ILogService,
52
@IEmbeddingsComputer private readonly embeddingsComputer: IEmbeddingsComputer,
53
@IEndpointProvider private readonly endPointProvider: IEndpointProvider,
54
@ICombinedEmbeddingIndex private readonly combinedEmbeddingIndex: ICombinedEmbeddingIndex,
55
@IEnvService private readonly envService: IEnvService,
56
@IInstantiationService private readonly instantiationService: IInstantiationService,
57
@IReleaseNotesService private readonly releaseNotesService: IReleaseNotesService,
58
) {
59
super(props);
60
}
61
62
override async prepare(sizing: PromptSizing, progress: vscode.Progress<vscode.ChatResponseProgressPart> | undefined, token: vscode.CancellationToken): Promise<VscodePromptState> {
63
if (!this.props.promptContext.query) {
64
return { settings: [], commands: [], query: '' };
65
}
66
67
progress?.report(new ChatResponseProgressPart(l10n.t('Refining question to improve search accuracy.')));
68
let userQuery: string = this.props.promptContext.query;
69
70
const endpoint = await this.endPointProvider.getChatEndpoint('copilot-fast');
71
const renderer = PromptRenderer.create(this.instantiationService, endpoint, VscodeMetaPrompt, this.props.promptContext);
72
const { messages } = await renderer.render();
73
if (token.isCancellationRequested) {
74
return { settings: [], commands: [], query: userQuery };
75
}
76
77
this.logService.debug('[VSCode Prompt] Asking the model to update the user question.');
78
79
const fetchResult = await endpoint.makeChatRequest(
80
'vscodePrompt',
81
messages,
82
async (_) => void 0,
83
token,
84
ChatLocation.Panel,
85
undefined,
86
{
87
temperature: 0,
88
},
89
);
90
91
if (token.isCancellationRequested) {
92
return { settings: [], commands: [], query: userQuery };
93
}
94
95
let fetchReleaseNotes = false;
96
let shouldIncludeDocsSearch = false;
97
let extensionSearch = false;
98
let vscodeApiSearch = false;
99
if (fetchResult.type === ChatFetchResponseType.Success) {
100
userQuery = parseMetaPromptResponse(this.props.promptContext.query, fetchResult.value);
101
shouldIncludeDocsSearch = fetchResult.value.includes('Other Question');
102
fetchReleaseNotes = fetchResult.value.includes('release_notes');
103
extensionSearch = fetchResult.value.includes('vscode_extensions');
104
vscodeApiSearch = fetchResult.value.includes('vscode_api');
105
} else {
106
this.logService.error(`[VSCode Prompt] Failed to refine the question: ${fetchResult.requestId}`);
107
}
108
109
const currentSanitized = sanitizeVSCodeVersion(this.envService.getEditorInfo().version); // major.minor
110
if (fetchReleaseNotes) {
111
// Determine which versions to fetch based on meta response
112
const rnMatch = fetchResult.type === ChatFetchResponseType.Success ? fetchResult.value.match(/release_notes(?:@(?<spec>[A-Za-z0-9._-]+))?/i) : undefined;
113
const spec = rnMatch?.groups?.['spec']?.toLowerCase();
114
115
let versionsToFetch: string[];
116
if (spec === 'last3') {
117
versionsToFetch = getLastNMinorVersions(currentSanitized, 3);
118
} else {
119
versionsToFetch = [currentSanitized];
120
}
121
122
const notes = await Promise.all(versionsToFetch.map(async (ver) => {
123
const text = await this.releaseNotesService.fetchReleaseNotesForVersion(ver);
124
return text ? { version: ver, notes: text } : undefined;
125
}));
126
127
const filtered = notes.filter((n): n is { version: string; notes: string } => !!n);
128
return { settings: [], commands: [], releaseNotes: filtered, query: this.props.promptContext.query, currentVersion: currentSanitized };
129
}
130
131
if (extensionSearch || vscodeApiSearch) {
132
return { settings: [], commands: [], query: this.props.promptContext.query };
133
}
134
135
if (token.isCancellationRequested) {
136
return { settings: [], commands: [], query: userQuery };
137
}
138
139
const embeddingResult = await this.embeddingsComputer.computeEmbeddings(EmbeddingType.text3small_512, [userQuery], {}, undefined);
140
if (token.isCancellationRequested) {
141
return { settings: [], commands: [], query: userQuery };
142
}
143
144
const nClosestValuesPromise = progress
145
? reportProgressOnSlowPromise(progress, new ChatResponseProgressPart(l10n.t("Searching command and setting index....")), this.combinedEmbeddingIndex.nClosestValues(embeddingResult.values[0], shouldIncludeDocsSearch ? 5 : 25), 500)
146
: this.combinedEmbeddingIndex.nClosestValues(embeddingResult.values[0], shouldIncludeDocsSearch ? 5 : 25);
147
148
const results = await Promise.allSettled([
149
nClosestValuesPromise,
150
]);
151
152
const embeddingResults = results[0].status === 'fulfilled' ? results[0].value : { commands: [], settings: [] };
153
154
return { settings: embeddingResults.settings, commands: embeddingResults.commands, query: userQuery, currentVersion: currentSanitized };
155
}
156
157
override render(state: VscodePromptState) {
158
const operatingSystem = this.envService.OS;
159
return (
160
<>
161
<SystemMessage priority={1000}>
162
You are a Visual Studio Code assistant. Your job is to assist users in using Visual Studio Code by providing knowledge to accomplish their task. This knowledge should focus on settings, commands, keybindings but also includes documentation. <br />
163
{state.query.length < 1 && <>
164
If the user does not include a question, respond with: I am your Visual Studio Code assistant. I can help you with settings, commands, keybindings, extensions, and documentation. Ask me anything about using or configuring Visual Studio Code.<br />
165
</>}
166
<CopilotIdentityRules />
167
<SafetyRules />
168
<InstructionMessage>
169
Additional Rules<br />
170
If a command or setting references another command or setting, you must respond with both the original and the referenced commands or settings.<br />
171
Prefer a setting over a command if the user's request can be achieved by a setting change.<br />
172
If answering with a keybinding, please still include the command bound to the keybinding.<br />
173
If a keybinding contains a backtick you must escape it. For example the keybinding Ctrl + backtick would be written as ``ctrl + ` ``<br />
174
If you believe the context given to you is incorrect or not relevant you may ignore it.<br />
175
Always respond with a numbered list of steps to be taken to achieve the desired outcome if multiple steps are necessary.<br />
176
If an extension might help the user, you may suggest a search query for the extension marketplace. You must also include the command **Search marketplace** (`workbench.extensions.search`) with args set to the suggested query in the commands section at the end of your response. The query can also contain the tags "@popular", "@recommended", or "@featured" to filter the results.<br />
177
The user is working on a {operatingSystem} machine. Please respond with system specific commands if applicable.<br />
178
If a command or setting is not a valid answer, but it still relates to Visual Studio Code, please still respond.<br />
179
If the question is about release notes, you must also include the command **Show release notes** (`update.showCurrentReleaseNotes`) in the commands section at the end of your response.<br />
180
If the response includes a command, only reference the command description in the description. Do not include the actual command in the description.<br />
181
All responses for settings and commands code blocks must strictly adhere to the template shown below:<br />
182
<Tag name='responseTemplate'>
183
<UnsafeCodeBlock code={`
184
{
185
"type": "array",
186
"items": {
187
"type": "object",
188
"properties": {
189
"type": {
190
"type": "string",
191
"enum": ["command", "setting"]
192
},
193
"details": {
194
"type": "object",
195
"properties": {
196
"key": { "type": "string" },
197
"value": { "type": "string" }
198
},
199
"required": ["key"]
200
}
201
},
202
"required": ["type", "details"],
203
"additionalProperties": false
204
}
205
}
206
`} languageId='json'></UnsafeCodeBlock>
207
<br />
208
where the `type` is either `setting`, `command`.<br />
209
- `setting` is used for responding with a setting to set.<br />
210
- `command` is used for responding with a command to execute<br />
211
where the `details` is an optional object that contains the setting/command objects.<br />
212
- `key` is the setting | command value to use .<br />
213
- `value` is the setting value in case of a setting.<br />
214
- `value` is the optional arguments to the command in case of a command.<br />
215
</Tag>
216
<Tag name='examples'>
217
Below you will find a set of examples of what you should respond with. Please follow these examples as closely as possible.<br />
218
<Tag name='singleSettingExample'>
219
Question: How do I disable telemetry?<br />
220
Response:<br />
221
Use the **telemetry.telemetryLevel** setting to disable telemetry.<br />
222
<UnsafeCodeBlock code={`
223
[
224
{
225
"type": "setting",
226
"details": {
227
"key": "telemetry.telemetryLevel",
228
"value": "off"
229
}
230
}
231
]
232
`} languageId='json'></UnsafeCodeBlock>
233
</Tag>
234
<Tag name='singleCommandExample'>
235
Question: How do I open a specific walkthrough?<br />
236
Use the **Welcome: Open Walkthrough...** command to open walkthroughs.<br />
237
Response:<br />
238
<UnsafeCodeBlock code={`
239
[
240
{
241
"type": "command",
242
"details": {
243
"key": "workbench.action.openWalkthrough",
244
}
245
}
246
]
247
`} languageId='json'></UnsafeCodeBlock>
248
</Tag>
249
<Tag name='multipleSettingsExample'>
250
If you are referencing multiple settings, first describe each setting and then include all settings in a single JSON markdown code block, as shown in the template below:<br />
251
Question: How can I change the font size in all areas of Visual Studio Code, including the editor, terminal?<br />
252
Response:<br />
253
The **editor.fontsize** setting adjusts the font size within the editor.<br />
254
The **terminal.integrated.fontSize** setting changes the font size in the integrated terminal.<br />
255
This **window.zoomLevel** setting controls the zoom level of the entire Visual Studio Code interface.<br />
256
<UnsafeCodeBlock code={`
257
[
258
{
259
"type": "setting",
260
"details": {
261
"key": "editor.fontSize",
262
"value": "18"
263
}
264
},
265
{
266
"type": "setting",
267
"details": {
268
"key": "terminal.integrated.fontSize",
269
"value": "14"
270
}
271
},
272
{
273
"type": "setting",
274
"details": {
275
"key": "window.zoomLevel",
276
"value": "1"
277
}
278
}
279
]
280
`} languageId='json'></UnsafeCodeBlock>
281
</Tag>
282
<Tag name='multipleCommandsExample'>
283
If you are referencing multiple commands, do not combine all the commands into the same JSON markdown code block.<br />
284
Instead, describe each command and include the JSON markdown code block in a numbered list, as shown in the template below:<br />
285
Question: How can I setup a python virtual environment in Visual Studio Code?<br />
286
Response:<br />
287
Use the **Python: Create Environment** command to create a new python environment.<br />
288
<UnsafeCodeBlock code={`
289
[
290
{
291
"type": "command",
292
"details": {
293
"key": "python.createEnvironment"
294
}
295
}
296
]
297
`} languageId='json'></UnsafeCodeBlock>
298
Select the environment type (Venv or Conda) from the list.<br />
299
If creating a Venv environment, select the interpreter to use as a base for the new virtual environment.<br />
300
Wait for the environment creation process to complete. A notification will show the progress.<br />
301
Ensure your new environment is selected by using the **Python: Select Interpreter** command.<br />
302
<UnsafeCodeBlock code={`
303
[
304
{
305
"type": "command",
306
"details": {
307
"key": "python.setInterpreter"
308
}
309
}
310
]
311
`} languageId='json'></UnsafeCodeBlock>
312
</Tag>
313
<Tag name='noSuchCommandExample'>
314
Question: How do I move the terminal to a new window?<br />
315
Response:<br />
316
There is no such command.<br />
317
</Tag>
318
<Tag name='invalidQuestionExample'>
319
Question: How do I bake a potato?<br />
320
Response:<br />
321
Sorry this question isn't related to Visual Studio Code.<br />
322
</Tag>
323
<Tag name='marketplaceSearchExample'>
324
Question: How do I add PHP support?<br />
325
Response:<br />
326
You can use the **Search marketplace** command to search for extensions that add PHP support.<br />
327
<UnsafeCodeBlock code={`
328
[
329
{
330
"type": "command",
331
"details": {
332
"key": "workbench.extensions.search",
333
"value": "php"
334
}
335
}
336
]
337
`} languageId='json'></UnsafeCodeBlock>
338
<br />
339
</Tag>
340
</Tag>
341
<Tag name='extensionSearchResponseRules'>
342
If you referene any extensions, you must respond with with the identifiers as a comma seperated string inside ```vscode-extensions code block. <br />
343
Do not describe the extension. Simply return the response in the format shown above.<br />
344
<Tag name='extensionResponseExample'>
345
Question: What are some popular python extensions?<br />
346
Response:<br />
347
Here are some popular python extensions.<br />
348
<UnsafeCodeBlock code={`
349
ms-python.python,ms-python.vscode-pylance
350
`} languageId='vscode-extensions'></UnsafeCodeBlock>
351
</Tag>
352
</Tag>
353
<ResponseTranslationRules />
354
</InstructionMessage>
355
</SystemMessage>
356
<ConversationHistoryWithTools flexGrow={1} priority={700} promptContext={this.props.promptContext} />
357
<UserMessage flexGrow={1} priority={800}>
358
Use the examples above to help you formulate your response and follow the examples as closely as possible.
359
Below is a list of information we found which might be relevant to the question. For view related commands "Toggle" often means Show or Hide. A setting may reference another setting, that will appear as \`#setting.id#\`, you must return the referenced setting as well. You may use this context to help you formulate your response, but are not required to.<br />
360
{state.commands.length > 0 && <><Tag name='command'>
361
Here are some possible commands:<br />
362
{state.commands.map(c => <TextChunk>- {c.label} ("{c.key}") (Keybinding: "{c.keybinding}")</TextChunk>)}
363
</Tag>
364
</>}
365
{state.settings.length > 0 && <><Tag name='settings'>
366
Here are some possible settings:<br />
367
{state.settings.map(c => <TextChunk>{settingItemToContext(c)}</TextChunk>)}
368
</Tag>
369
</>}
370
{state.currentVersion && <><Tag name='currentVSCodeVersion'>
371
Current VS Code version (major.minor): {state.currentVersion}
372
</Tag><br /></>}
373
{state.releaseNotes && state.releaseNotes.length > 0 && <><Tag name='releaseNotes'>
374
Below are release notes which might be relevant to the question. <br />
375
{state.releaseNotes.map(rn => <><TextChunk>Version {rn.version}:</TextChunk><br /><TextChunk>{rn.notes}</TextChunk></>)}
376
</Tag>
377
</>}
378
<Tag name='vscodeAPIToolUseInstructions'>
379
Always call the tool {ToolName.VSCodeAPI} to get documented references and examples when before responding to questions about VS Code Extension Development.<br />
380
</Tag>
381
<Tag name='searchExtensionToolUseInstructions'>
382
Always call the tool 'vscode_searchExtensions_internal' to first search for extensions in the VS Code Marketplace before responding about extensions.<br />
383
</Tag>
384
<Tag name='vscodeCmdToolUseInstructions'>
385
Call the tool {ToolName.RunVscodeCmd} to run commands in Visual Studio Code, only use as part of a new workspace creation process. <br />
386
You must use the command name as the `name` field and the command ID as the `commandId` field in the tool call input with any arguments for the command in a `map` array.<br />
387
For example, to run the command `workbench.action.openWith`, you would use the following input:<br />
388
<UnsafeCodeBlock code={`{
389
"name": "workbench.action.openWith",
390
"commandId": "workbench.action.openWith",
391
"args": ["file:///path/to/file.txt", "default"]
392
}
393
`}></UnsafeCodeBlock>
394
</Tag>
395
</UserMessage>
396
<ChatToolReferences priority={850} flexGrow={2} promptContext={{ ...this.props.promptContext, query: state.query }} embeddedInsideUserMessage={false} />
397
<ChatToolCalls priority={899} flexGrow={2} promptContext={this.props.promptContext} toolCallRounds={this.props.promptContext.toolCallRounds} toolCallResults={this.props.promptContext.toolCallResults} />
398
<ChatVariablesAndQuery flexGrow={2} priority={900} chatVariables={this.props.promptContext.chatVariables} query={this.props.promptContext.query} embeddedInsideUserMessage={false} />
399
</>);
400
}
401
}
402
403
interface VscodeMetaPromptProps extends BasePromptElementProps {
404
history?: readonly Turn[];
405
query: string;
406
}
407
408
class VscodeMetaPrompt extends PromptElement<VscodeMetaPromptProps> {
409
410
override render(state: void, sizing: PromptSizing): PromptPiece<any, any> | undefined {
411
return <>
412
<SystemMessage priority={1000}>
413
You are a Visual Studio Code assistant who helps the user create well-formed and unambiguous queries about their Visual Studio Code development environment.<br />
414
Specifically, you help users rewrite questions about how to use Visual Studio Code's Commands and Settings.
415
</SystemMessage>
416
<HistoryWithInstructions historyPriority={500} passPriority history={this.props.history || []}>
417
<InstructionMessage priority={1000}>
418
Evaluate the question to determine the user's intent. <br />
419
Determine if the user's question is about the editor, terminal, activity bar, side bar, status bar, panel or other parts of Visual Studio Code's workbench and include those keyword in the rewrite.<br />
420
Determine if the user is asking about Visual Studio Code's Commands and/or Settings and explicitly include those keywords during the rewrite. <br />
421
If the question does not clearly indicate whether it pertains to a command or setting, categorize it as an ‘Other Question’ <br />
422
If the user is asking about Visual Studio Code Release Notes, respond using this exact protocol and do not rephrase the question: <br />
423
- Respond with only one of the following: `release_notes@latest` or `release_notes@last3`.<br />
424
- If the user does not specify a timeframe, respond with: `release_notes@latest`.<br />
425
- If the request is vague about a timeframe (e.g., "recent changes"), respond with: `release_notes@last3` to consider the last three versions (major.minor).<br />
426
- If the user asks to find or locate a specific change/feature in the release notes, respond with: `release_notes@last3` to search across the last three versions (major.minor).<br />
427
If the user is asking about Extensions available in Visual Studio Code, simply respond with "vscode_extensions"<br />
428
If the user is asking about Visual Studio Code API or Visual Studio Code Extension Development, simply respond with "vscode_api"<br />
429
Remove any references to "What" or "How" and instead rewrite the question as a description of the command or setting that the user is trying to find. <br />
430
Respond in Markdown. Under a `# Question` header, output a rephrased version of the user's question that resolves all pronouns and ambiguous words like 'this' to the specific nouns they stand for.<br />
431
If it is not clear what the user is asking for or if the question appears to be unrelated to Visual Studio Code, do not try to rephrase the question and simply return the original question. <br />
432
DO NOT ask the user for additional information or clarification.<br />
433
DO NOT answer the user's question directly.<br />
434
<br />
435
# Additional Rules<br />
436
<br />
437
2. If the question contains pronouns such as 'it' or 'that', try to understand what the pronoun refers to by looking at the rest of the question and the conversation history.<br />
438
3. If the question contains an ambiguous word such as 'this', try to understand what 'this' refers to by looking at the rest of the question and the conversation history.<br />
439
4. After a `# Question` header, output a precise version of the question that resolves all pronouns and ambiguous words like 'this' to the specific nouns they stand for. Be sure to preserve the exact meaning of the question.<br />
440
<br />
441
Examples<br />
442
<br />
443
User: opne cmmand palete<br />
444
<br />
445
Assistant:<br />
446
# Question<br />
447
Command to open command palette<br />
448
<br />
449
<br />
450
User: How do I change change font size in the editor?<br />
451
<br />
452
Assistant:<br />
453
# Question<br />
454
Command or setting to change the font size in the editor<br />
455
<br />
456
User: What is the setting to move editor and pin it<br />
457
Assistant: <br />
458
# Question<br />
459
Settings to move and pin editor<br />
460
<br />
461
User: latest released features<br />
462
<br />
463
Assistant:<br />
464
release_notes@latest<br />
465
<br />
466
User: What are the recent changes?<br />
467
<br />
468
Assistant:<br />
469
release_notes@last3<br />
470
<br />
471
User: set up python<br />
472
<br />
473
Assistant:<br />
474
# Other Question<br />
475
Set up python development in Visual Studio Code<br />
476
<br />
477
User: Show me popular extensions<br />
478
<br />
479
Assistant:<br />
480
vscode_extensions<br />
481
<br />
482
User: How do I contribute a command to my extension?<br />
483
<br />
484
Assistant:<br />
485
vscode_api<br />
486
<br />
487
<ResponseTranslationRules />
488
</InstructionMessage>
489
</HistoryWithInstructions>
490
<UserMessage priority={700}>{this.props.query}</UserMessage>
491
</>;
492
}
493
}
494
495
function parseMetaPromptResponse(originalQuestion: string, response: string): string {
496
const match = response.match(/#+\s*(Question|Other Question)\n(?<question>.+)/si);
497
if (!match?.groups) {
498
return originalQuestion.trim();
499
}
500
return match.groups['question'].trim();
501
}
502
503
function getLastNMinorVersions(current: string, n: number): string[] {
504
const m = /^(\d+)\.(\d+)$/.exec(current);
505
if (!m) {
506
return [current];
507
}
508
const major = parseInt(m[1], 10);
509
let minor = parseInt(m[2], 10);
510
const out: string[] = [];
511
for (let i = 0; i < n && minor >= 0; i++, minor--) {
512
out.push(`${major}.${minor}`);
513
}
514
return out;
515
}
516
517