Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/chat/browser/promptSyntax/saveToPromptAction.ts
3296 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 { localize2 } from '../../../../../nls.js';
7
import { Action2, registerAction2 } from '../../../../../platform/actions/common/actions.js';
8
9
import { ContextKeyExpr } from '../../../../../platform/contextkey/common/contextkey.js';
10
import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
11
import { ILogService } from '../../../../../platform/log/common/log.js';
12
import { PromptsConfig } from '../../common/promptSyntax/config/config.js';
13
import { IEditorService } from '../../../../services/editor/common/editorService.js';
14
import { ChatContextKeys } from '../../common/chatContextKeys.js';
15
import { chatSubcommandLeader, IParsedChatRequest } from '../../common/chatParserTypes.js';
16
import { PROMPT_LANGUAGE_ID } from '../../common/promptSyntax/promptTypes.js';
17
import { CHAT_CATEGORY } from '../actions/chatActions.js';
18
import { IChatWidget } from '../chat.js';
19
import { ChatModeKind } from '../../common/constants.js';
20
import { PromptFileRewriter } from './promptFileRewriter.js';
21
import { ILanguageModelChatMetadata } from '../../common/languageModels.js';
22
import { URI } from '../../../../../base/common/uri.js';
23
import { Schemas } from '../../../../../base/common/network.js';
24
25
/**
26
* Action ID for the `Save Prompt` action.
27
*/
28
export const SAVE_TO_PROMPT_ACTION_ID = 'workbench.action.chat.save-to-prompt';
29
30
/**
31
* Name of the in-chat slash command associated with this action.
32
*/
33
export const SAVE_TO_PROMPT_SLASH_COMMAND_NAME = 'save';
34
35
/**
36
* Options for the {@link SaveToPromptAction} action.
37
*/
38
interface ISaveToPromptActionOptions {
39
/**
40
* Chat widget reference to save session of.
41
*/
42
readonly chat: IChatWidget;
43
}
44
45
/**
46
* Class that defines the `Save Prompt` action.
47
*/
48
class SaveToPromptAction extends Action2 {
49
constructor() {
50
super({
51
id: SAVE_TO_PROMPT_ACTION_ID,
52
title: localize2(
53
'workbench.actions.save-to-prompt.label',
54
"Save chat session to a prompt file",
55
),
56
f1: false,
57
precondition: ContextKeyExpr.and(PromptsConfig.enabledCtx, ChatContextKeys.enabled),
58
category: CHAT_CATEGORY,
59
});
60
}
61
62
public async run(
63
accessor: ServicesAccessor,
64
options: ISaveToPromptActionOptions,
65
): Promise<void> {
66
const logService = accessor.get(ILogService);
67
const editorService = accessor.get(IEditorService);
68
const rewriter = accessor.get(IInstantiationService).createInstance(PromptFileRewriter);
69
70
const logPrefix = 'save to prompt';
71
const chatWidget = options.chat;
72
const mode = chatWidget.input.currentModeObs.get();
73
const model = chatWidget.input.selectedLanguageModel;
74
75
const output = [];
76
output.push('---');
77
output.push(`description: New prompt created from chat session`);
78
output.push(`mode: ${mode.kind}`);
79
if (mode.kind === ChatModeKind.Agent) {
80
const toolAndToolsetMap = chatWidget.input.selectedToolsModel.entriesMap.get();
81
output.push(`tools: ${rewriter.getNewValueString(toolAndToolsetMap)}`);
82
}
83
if (model) {
84
output.push(`model: ${ILanguageModelChatMetadata.asQualifiedName(model.metadata)}`);
85
}
86
output.push('---');
87
88
const viewModel = chatWidget.viewModel;
89
if (viewModel) {
90
91
for (const request of viewModel.model.getRequests()) {
92
const { message, response: responseModel } = request;
93
94
if (isSaveToPromptSlashCommand(message)) {
95
continue;
96
}
97
98
if (responseModel === undefined) {
99
logService.warn(`[${logPrefix}]: skipping request '${request.id}' with no response`);
100
continue;
101
}
102
103
const { response } = responseModel;
104
105
output.push(`<user>`);
106
output.push(request.message.text);
107
output.push(`</user>`);
108
output.push();
109
output.push(`<assistant>`);
110
output.push(response.getMarkdown());
111
output.push(`</assistant>`);
112
output.push();
113
}
114
const promptText = output.join('\n');
115
116
const untitledPath = 'new.prompt.md';
117
const untitledResource = URI.from({ scheme: Schemas.untitled, path: untitledPath });
118
119
const editor = await editorService.openEditor({
120
resource: untitledResource,
121
contents: promptText,
122
languageId: PROMPT_LANGUAGE_ID,
123
});
124
125
editor?.focus();
126
}
127
}
128
}
129
130
/**
131
* Check if provided message belongs to the `save to prompt` slash
132
* command itself that was run in the chat to invoke this action.
133
*/
134
function isSaveToPromptSlashCommand(message: IParsedChatRequest): boolean {
135
const { parts } = message;
136
if (parts.length < 1) {
137
return false;
138
}
139
140
const firstPart = parts[0];
141
if (firstPart.kind !== 'slash') {
142
return false;
143
}
144
145
if (firstPart.text !== `${chatSubcommandLeader}${SAVE_TO_PROMPT_SLASH_COMMAND_NAME}`) {
146
return false;
147
}
148
149
return true;
150
}
151
152
/**
153
* Helper to register all the `Save Prompt` actions.
154
*/
155
export function registerSaveToPromptActions(): void {
156
registerAction2(SaveToPromptAction);
157
}
158
159