edits: set hasError on tool results from editing tools (#2022)

Refs https://github.com/microsoft/vscode/issues/275056
This commit is contained in:
Connor Peet
2025-11-14 14:42:01 -08:00
committed by GitHub
parent 9dfc3993af
commit 125097f3f6
3 changed files with 15 additions and 6 deletions
@@ -28,7 +28,7 @@ import { ResourceMap, ResourceSet } from '../../../util/vs/base/common/map';
import { isDefined } from '../../../util/vs/base/common/types';
import { URI } from '../../../util/vs/base/common/uri';
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
import { ChatRequestEditorData, ChatResponseTextEditPart, EndOfLine, Position as ExtPosition, LanguageModelPromptTsxPart, LanguageModelToolResult, TextEdit } from '../../../vscodeTypes';
import { ChatRequestEditorData, ChatResponseTextEditPart, EndOfLine, ExtendedLanguageModelToolResult, Position as ExtPosition, LanguageModelPromptTsxPart, LanguageModelToolResult, TextEdit } from '../../../vscodeTypes';
import { IBuildPromptContext } from '../../prompt/common/intents';
import { renderPromptElementJSON } from '../../prompts/node/base/promptRenderer';
import { CellOrNotebookEdit, processFullRewriteNotebookEdits } from '../../prompts/node/codeMapper/codeMapper';
@@ -39,7 +39,7 @@ import { IToolsService } from '../common/toolsService';
import { ActionType } from './applyPatch/parser';
import { CorrectedEditResult, healReplaceStringParams } from './editFileHealing';
import { EditFileResult, IEditedFile } from './editFileToolResult';
import { EditError, NoChangeError, NoMatchError, applyEdit, canExistingFileBeEdited, createEditConfirmation, formatDiffAsUnified, logEditToolResult, openDocumentAndSnapshot } from './editFileToolUtils';
import { applyEdit, canExistingFileBeEdited, createEditConfirmation, EditError, formatDiffAsUnified, logEditToolResult, NoChangeError, NoMatchError, openDocumentAndSnapshot } from './editFileToolUtils';
import { sendEditNotebookTelemetry } from './editNotebookTool';
import { assertFileNotContentExcluded, resolveToolInputPath } from './toolUtils';
@@ -308,7 +308,7 @@ export abstract class AbstractReplaceStringTool<T extends { explanation: string
const isInlineChat = this._promptContext.request?.location2 instanceof ChatRequestEditorData;
return new LanguageModelToolResult([
const result = new ExtendedLanguageModelToolResult([
new LanguageModelPromptTsxPart(
await renderPromptElementJSON(
this.instantiationService,
@@ -324,6 +324,9 @@ export abstract class AbstractReplaceStringTool<T extends { explanation: string
),
)
]);
result.hasError = fileResults.some(f => f.error);
return result;
}
private async generateEdit(uri: URI, document: TextDocumentSnapshot | NotebookDocumentSnapshot, options: vscode.LanguageModelToolInvocationOptions<T> | vscode.LanguageModelToolInvocationPrepareOptions<T>, input: IAbstractReplaceStringInput, didHealRef: { healed?: IAbstractReplaceStringInput }, token: vscode.CancellationToken) {
@@ -31,7 +31,7 @@ import { ResourceMap, ResourceSet } from '../../../util/vs/base/common/map';
import { isDefined } from '../../../util/vs/base/common/types';
import { URI } from '../../../util/vs/base/common/uri';
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
import { ChatRequestEditorData, ChatResponseTextEditPart, LanguageModelPromptTsxPart, LanguageModelTextPart, LanguageModelToolResult, Position, Range, WorkspaceEdit } from '../../../vscodeTypes';
import { ChatRequestEditorData, ChatResponseTextEditPart, ExtendedLanguageModelToolResult, LanguageModelPromptTsxPart, LanguageModelTextPart, LanguageModelToolResult, Position, Range, WorkspaceEdit } from '../../../vscodeTypes';
import { IBuildPromptContext } from '../../prompt/common/intents';
import { ApplyPatchFormatInstructions } from '../../prompts/node/agent/defaultAgentInstructions';
import { PromptRenderer, renderPromptElementJSON } from '../../prompts/node/base/promptRenderer';
@@ -417,7 +417,7 @@ export class ApplyPatchTool implements ICopilotTool<IApplyPatchToolParams> {
const isInlineChat = this._promptContext.request?.location2 instanceof ChatRequestEditorData;
const isNotebook = editEntires.length === 1 ? handledNotebookUris.size === 1 : undefined;
this.sendApplyPatchTelemetry('success', options, undefined, !!healed, isNotebook);
return new LanguageModelToolResult([
const result = new ExtendedLanguageModelToolResult([
new LanguageModelPromptTsxPart(
await renderPromptElementJSON(
this.instantiationService,
@@ -431,13 +431,17 @@ export class ApplyPatchTool implements ICopilotTool<IApplyPatchToolParams> {
),
)
]);
result.hasError = files.some(f => f.error);
return result;
} catch (error) {
const isNotebook = Object.values(docText).length === 1 ? (!!mapFindFirst(Object.values(docText), v => v.notebookUri)) : undefined;
// TODO parser.ts could annotate DiffError with a telemetry detail if we want
this.sendApplyPatchTelemetry('error', options, undefined, false, isNotebook, error);
return new LanguageModelToolResult([
const result = new ExtendedLanguageModelToolResult([
new LanguageModelTextPart('Applying patch failed with error: ' + error.message),
]);
result.hasError = true;
return result;
}
}
@@ -248,6 +248,8 @@ declare module 'vscode' {
toolResultMessage?: string | MarkdownString;
toolResultDetails?: Array<Uri | Location>;
toolMetadata?: unknown;
/** Whether there was an error calling the tool. The tool may still have partially succeeded. */
hasError?: boolean;
}
// #region Chat participant detection