mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-21 03:36:14 +01:00
In the agents window, each chat session has its own working directory that may differ from the current workspace folders (which change when switching between sessions). This caused tools to search the wrong folder, show spurious 'Allow reading external files?' prompts, and render incorrect workspace_info in the system prompt. Core plumbing: - Add workingDirectory to IToolInvocationContext, IToolInvocationPreparationContext, ILanguageModelToolConfirmationRef, and IChatAgentRequest - Enrich tool invocation context from model.workingDirectory in invokeTool() - Include workingDirectory in toolInvocationToken built in extHostTypeConverters - Pass workingDirectory through LanguageModelToolInvocationOptions and LanguageModelToolInvocationPrepareOptions (proposed API) - Revive workingDirectory URI in extHostLanguageModelTools Tool fixes (when workingDirectory is set, use it exclusively): - chatExternalPathConfirmation: auto-approve paths within workingDirectory - isFileExternalAndNeedsConfirmation / isDirExternalAndNeedsConfirmation / assertFileOkForTool: treat workingDirectory as workspace-internal - createEditConfirmation: use workingDirectory for edit trust checks - All edit tools (create_file, replace_string, multi_replace, apply_patch, insert_edit, edit_notebook, create_directory): pass workingDirectory - resolveToolUri: resolve relative paths against workingDirectory - inputGlobToPattern: scope unscoped globs to workingDirectory - file_search / grep_search: scope searches to workingDirectory - semantic_search: prefer workingDirectory for cwd - run_in_terminal: prefer workingDirectory for terminal cwd - fetchPageTool: check workingDirectory for file URI trust - readFileTool / listDirTool / viewImageTool: pass workingDirectory Prompt fixes: - WorkspaceFoldersHint: show workingDirectory instead of workspace folders - AgentMultirootWorkspaceStructure: generate file tree from workingDirectory
72 lines
3.0 KiB
TypeScript
72 lines
3.0 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import * as l10n from '@vscode/l10n';
|
|
import type * as vscode from 'vscode';
|
|
import { IFileSystemService } from '../../../platform/filesystem/common/fileSystemService';
|
|
import { IPromptPathRepresentationService } from '../../../platform/prompts/common/promptPathRepresentationService';
|
|
import { createFencedCodeBlock } from '../../../util/common/markdown';
|
|
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
|
|
import { LanguageModelTextPart, LanguageModelToolResult, MarkdownString } from '../../../vscodeTypes';
|
|
import { ToolName } from '../common/toolNames';
|
|
import { ICopilotTool, ToolRegistry } from '../common/toolsRegistry';
|
|
import { formatUriForFileWidget } from '../common/toolUtils';
|
|
import { createEditConfirmation } from './editFileToolUtils';
|
|
import { resolveToolInputPath } from './toolUtils';
|
|
|
|
export interface ICreateDirectoryParams {
|
|
dirPath: string;
|
|
}
|
|
|
|
export class CreateDirectoryTool implements ICopilotTool<ICreateDirectoryParams> {
|
|
public static toolName = ToolName.CreateDirectory;
|
|
|
|
constructor(
|
|
@IPromptPathRepresentationService private readonly promptPathRepresentationService: IPromptPathRepresentationService,
|
|
@IFileSystemService private readonly fileSystemService: IFileSystemService,
|
|
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
|
) { }
|
|
|
|
async invoke(options: vscode.LanguageModelToolInvocationOptions<ICreateDirectoryParams>, token: vscode.CancellationToken) {
|
|
const uri = this.promptPathRepresentationService.resolveFilePath(options.input.dirPath);
|
|
if (!uri) {
|
|
throw new Error(`Invalid directory path`);
|
|
}
|
|
|
|
await this.fileSystemService.createDirectory(uri);
|
|
|
|
return new LanguageModelToolResult([
|
|
new LanguageModelTextPart(
|
|
`Created directory at ${this.promptPathRepresentationService.getFilePath(uri)}`,
|
|
)
|
|
]);
|
|
}
|
|
|
|
async prepareInvocation(options: vscode.LanguageModelToolInvocationPrepareOptions<ICreateDirectoryParams>, token: vscode.CancellationToken): Promise<vscode.PreparedToolInvocation> {
|
|
const uri = resolveToolInputPath(options.input.dirPath, this.promptPathRepresentationService);
|
|
|
|
const confirmation = await this.instantiationService.invokeFunction(
|
|
createEditConfirmation,
|
|
[uri],
|
|
undefined,
|
|
async () => {
|
|
return 'Creating the directory:\n\n' + createFencedCodeBlock('plaintext', uri.fsPath);
|
|
},
|
|
options.forceConfirmationReason,
|
|
undefined,
|
|
options.workingDirectory,
|
|
);
|
|
|
|
return {
|
|
...confirmation,
|
|
presentation: undefined,
|
|
invocationMessage: new MarkdownString(l10n.t`Creating ${formatUriForFileWidget(uri)}`),
|
|
pastTenseMessage: new MarkdownString(l10n.t`Created ${formatUriForFileWidget(uri)}`)
|
|
};
|
|
}
|
|
}
|
|
|
|
ToolRegistry.registerTool(CreateDirectoryTool);
|