Path: blob/main/src/vs/workbench/contrib/chat/browser/promptSyntax/promptFileRewriter.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { CancellationToken } from '../../../../../base/common/cancellation.js';6import { URI } from '../../../../../base/common/uri.js';7import { ICodeEditorService } from '../../../../../editor/browser/services/codeEditorService.js';8import { EditOperation } from '../../../../../editor/common/core/editOperation.js';9import { Range } from '../../../../../editor/common/core/range.js';10import { ITextModel } from '../../../../../editor/common/model.js';11import { IToolAndToolSetEnablementMap, IToolData, ToolSet } from '../../common/languageModelToolsService.js';12import { IPromptsService } from '../../common/promptSyntax/service/promptsService.js';1314export class PromptFileRewriter {15constructor(16@ICodeEditorService private readonly _codeEditorService: ICodeEditorService,17@IPromptsService private readonly _promptsService: IPromptsService18) {19}2021public async openAndRewriteTools(uri: URI, newTools: IToolAndToolSetEnablementMap | undefined, token: CancellationToken): Promise<void> {22const editor = await this._codeEditorService.openCodeEditor({ resource: uri }, this._codeEditorService.getFocusedCodeEditor());23if (!editor || !editor.hasModel()) {24return;25}26const model = editor.getModel();2728const parser = this._promptsService.getSyntaxParserFor(model);29await parser.start(token).settled();30const { header } = parser;31if (header === undefined) {32return undefined;33}3435const completed = await header.settled;36if (!completed || token.isCancellationRequested) {37return;38}3940if (('tools' in header.metadataUtility) === false) {41return undefined;42}43const { tools } = header.metadataUtility;44if (tools === undefined) {45return undefined;46}47editor.setSelection(tools.range);48this.rewriteTools(model, newTools, tools.range);49}505152public rewriteTools(model: ITextModel, newTools: IToolAndToolSetEnablementMap | undefined, range: Range): void {53const newString = newTools === undefined ? '' : `tools: ${this.getNewValueString(newTools)}`;54model.pushStackElement();55model.pushEditOperations(null, [EditOperation.replaceMove(range, newString)], () => null);56model.pushStackElement();57}5859public getNewValueString(tools: IToolAndToolSetEnablementMap): string {60const newToolNames: string[] = [];61const toolsCoveredBySets = new Set<IToolData>();62for (const [item, picked] of tools) {63if (picked && item instanceof ToolSet) {64for (const tool of item.getTools()) {65toolsCoveredBySets.add(tool);66}67}68}69for (const [item, picked] of tools) {70if (picked) {71if (item instanceof ToolSet) {72newToolNames.push(item.referenceName);73} else if (!toolsCoveredBySets.has(item)) {74newToolNames.push(item.toolReferenceName ?? item.displayName);75}76}77}78return `[${newToolNames.map(s => `'${s}'`).join(', ')}]`;79}80}8182838485