Path: blob/main/extensions/copilot/src/extension/intents/node/notebookEditorIntent.ts
13399 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 type * as vscode from 'vscode';6import { ChatLocation } from '../../../platform/chat/common/commonTypes';7import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';8import { IEndpointProvider } from '../../../platform/endpoint/common/endpointProvider';9import { IAutomodeService } from '../../../platform/endpoint/node/automodeService';10import { IEnvService } from '../../../platform/env/common/envService';11import { ILogService } from '../../../platform/log/common/logService';12import { IEditLogService } from '../../../platform/multiFileEdit/common/editLogService';13import { IChatEndpoint } from '../../../platform/networking/common/networking';14import { IAlternativeNotebookContentService } from '../../../platform/notebook/common/alternativeContent';15import { getCellId } from '../../../platform/notebook/common/helpers';16import { INotebookService } from '../../../platform/notebook/common/notebookService';17import { IOTelService } from '../../../platform/otel/common/otelService';18import { ISessionTranscriptService } from '../../../platform/chat/common/sessionTranscriptService';19import { IPromptPathRepresentationService } from '../../../platform/prompts/common/promptPathRepresentationService';20import { ITabsAndEditorsService } from '../../../platform/tabs/common/tabsAndEditorsService';21import { IExperimentationService } from '../../../platform/telemetry/common/nullExperimentationService';22import { ITelemetryService } from '../../../platform/telemetry/common/telemetry';23import { IWorkspaceService } from '../../../platform/workspace/common/workspaceService';24import { generateUuid } from '../../../util/vs/base/common/uuid';25import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';26import { ICommandService } from '../../commands/node/commandService';27import { Intent } from '../../common/constants';28import { ChatVariablesCollection } from '../../prompt/common/chatVariablesCollection';29import { IBuildPromptContext, InternalToolReference } from '../../prompt/common/intents';30import { getRequestedToolCallIterationLimit } from '../../prompt/common/specialRequestTypes';31import { IDefaultIntentRequestHandlerOptions } from '../../prompt/node/defaultIntentRequestHandler';32import { IBuildPromptResult, IIntent } from '../../prompt/node/intents';33import { ICodeMapperService } from '../../prompts/node/codeMapper/codeMapperService';34import { NotebookInlinePrompt } from '../../prompts/node/panel/notebookInlinePrompt';35import { getToolName, ToolName } from '../../tools/common/toolNames';36import { IToolsService } from '../../tools/common/toolsService';37import { getAgentMaxRequests } from '../common/agentConfig';38import { EditCodeIntent, EditCodeIntentOptions } from './editCodeIntent';39import { EditCode2IntentInvocation } from './editCodeIntent2';4041const getTools = (instaService: IInstantiationService, request: vscode.ChatRequest): Promise<vscode.LanguageModelToolInformation[]> =>42instaService.invokeFunction(async accessor => {43const toolsService = accessor.get<IToolsService>(IToolsService);44const endpointProvider = accessor.get<IEndpointProvider>(IEndpointProvider);45const model = await endpointProvider.getChatEndpoint(request);46const lookForTools = new Set<string>([ToolName.EditFile]);4748lookForTools.add(ToolName.EditNotebook);49lookForTools.add(ToolName.GetNotebookSummary);50lookForTools.add(ToolName.RunNotebookCell);51lookForTools.add(ToolName.ReadCellOutput);5253return toolsService.getEnabledTools(request, model, tool => lookForTools.has(tool.name) || tool.tags.includes('notebooks'));54});5556export class NotebookEditorIntent extends EditCodeIntent {5758static override readonly ID = Intent.notebookEditor;5960override readonly id = NotebookEditorIntent.ID;6162override readonly locations = [ChatLocation.Notebook];6364constructor(65@IInstantiationService instantiationService: IInstantiationService,66@IEndpointProvider endpointProvider: IEndpointProvider,67@IConfigurationService configurationService: IConfigurationService,68@IExperimentationService expService: IExperimentationService,69@ICodeMapperService codeMapperService: ICodeMapperService,70@IWorkspaceService workspaceService: IWorkspaceService,71) {72super(instantiationService, endpointProvider, configurationService, expService, codeMapperService, workspaceService, { processCodeblocks: false, intentInvocation: NotebookEditorIntentInvocation });73}7475protected override getIntentHandlerOptions(request: vscode.ChatRequest): IDefaultIntentRequestHandlerOptions | undefined {76return {77maxToolCallIterations: getRequestedToolCallIterationLimit(request) ?? this.instantiationService.invokeFunction(getAgentMaxRequests),78temperature: this.configurationService.getConfig(ConfigKey.Advanced.AgentTemperature) ?? 0,79overrideRequestLocation: ChatLocation.Notebook,80};81}82}8384export class NotebookEditorIntentInvocation extends EditCode2IntentInvocation {8586constructor(87intent: IIntent,88location: ChatLocation,89endpoint: IChatEndpoint,90request: vscode.ChatRequest,91intentOptions: EditCodeIntentOptions,92@ITabsAndEditorsService private readonly tabsAndEditorsService: ITabsAndEditorsService,93@IAlternativeNotebookContentService private readonly alternativeNotebookContentService: IAlternativeNotebookContentService,94@IInstantiationService instantiationService: IInstantiationService,95@ICodeMapperService codeMapperService: ICodeMapperService,96@IEnvService envService: IEnvService,97@IPromptPathRepresentationService promptPathRepresentationService: IPromptPathRepresentationService,98@IEndpointProvider endpointProvider: IEndpointProvider,99@IWorkspaceService workspaceService: IWorkspaceService,100@IToolsService toolsService: IToolsService,101@IConfigurationService configurationService: IConfigurationService,102@IEditLogService editLogService: IEditLogService,103@ICommandService commandService: ICommandService,104@ITelemetryService telemetryService: ITelemetryService,105@INotebookService notebookService: INotebookService,106@ILogService logService: ILogService,107@IExperimentationService expService: IExperimentationService,108@IAutomodeService automodeService: IAutomodeService,109@IOTelService otelService: IOTelService,110@ISessionTranscriptService sessionTranscriptService: ISessionTranscriptService,111) {112super(intent, location, endpoint, request, intentOptions, instantiationService, codeMapperService, envService, promptPathRepresentationService, endpointProvider, workspaceService, toolsService, configurationService, editLogService, commandService, telemetryService, notebookService, logService, expService, automodeService, otelService, sessionTranscriptService);113}114115protected override prompt = NotebookInlinePrompt;116117public override async getAvailableTools(): Promise<vscode.LanguageModelToolInformation[]> {118return getTools(this.instantiationService, this.request);119}120121public override buildPrompt(promptContext: IBuildPromptContext, progress: vscode.Progress<vscode.ChatResponseReferencePart | vscode.ChatResponseProgressPart>, token: vscode.CancellationToken): Promise<IBuildPromptResult> {122const variables = this.createReferencesForActiveEditor() ?? promptContext.chatVariables;123124const { query, commandToolReferences } = this.processSlashCommand(promptContext.query);125126return super.buildPrompt({127...promptContext,128chatVariables: variables,129query,130tools: promptContext.tools && {131...promptContext.tools,132toolReferences: this.stableToolReferences.filter((r) => r.name !== ToolName.Codebase).concat(commandToolReferences),133},134}, progress, token);135}136137private createReferencesForActiveEditor(): ChatVariablesCollection | undefined {138139const editor = this.tabsAndEditorsService.activeNotebookEditor;140141if (editor) {142const cell = editor.notebook.cellAt(editor.selection.start);143const format = this.alternativeNotebookContentService.getFormat(this.endpoint);144const altDocument = this.alternativeNotebookContentService.create(format).getAlternativeDocument(editor.notebook);145146const textEditor = this.tabsAndEditorsService.activeTextEditor;147148let selectedText = '';149150if (textEditor) {151const cellText = textEditor.document.getText();152const lines = cellText.split('\n');153const startLine = Math.max(0, textEditor.selection.start.line - 1);154const endLine = Math.min(lines.length - 1, textEditor.selection.end.line + 1);155selectedText = lines.slice(startLine, endLine + 1).join('\n');156}157158const refsForActiveEditor: vscode.ChatPromptReference[] = [159{160id: editor.notebook.uri.toString(),161name: 'Active notebook editor: ' + editor.notebook.uri.toString(),162value: altDocument.getText()163}164];165166// Add selected text as a separate reference if we have any167if (selectedText.trim()) {168const cellID = getCellId(cell);169refsForActiveEditor.push({170id: `${editor.notebook.uri.toString()}#selection`,171name: `Selected text in cell ${cellID} active notebook editor`,172value: selectedText173});174}175176return new ChatVariablesCollection([...this.request.references, ...refsForActiveEditor]);177}178}179180private processSlashCommand(query: string): { query: string; commandToolReferences: InternalToolReference[] } {181const commandToolReferences: InternalToolReference[] = [];182const command = this.request.command && this.commandService.getCommand(this.request.command, this.location);183if (command) {184if (command.toolEquivalent) {185commandToolReferences.push({186id: `${this.request.command}->${generateUuid()}`,187name: getToolName(command.toolEquivalent)188});189}190query = query ? `${command.details}.\n${query}` : command.details;191}192193return { query, commandToolReferences };194}195}196197198