Update github copilot npm (#4274)

* Update github copilot extension

* Update tool calls

* Updates
This commit is contained in:
Don Jayamanne
2026-03-08 17:10:16 +11:00
committed by GitHub
parent e575034fa6
commit 24c0c3dbce
5 changed files with 137 additions and 108 deletions

View File

@@ -13,7 +13,7 @@
"@anthropic-ai/claude-agent-sdk": "^0.2.63",
"@anthropic-ai/sdk": "^0.78.0",
"@github/blackbird-external-ingest-utils": "^0.3.0",
"@github/copilot": "^0.0.421",
"@github/copilot": "^1.0.2",
"@google/genai": "^1.22.0",
"@humanwhocodes/gitignore-to-minimatch": "1.0.2",
"@microsoft/tiktokenizer": "^1.0.10",
@@ -3182,26 +3182,26 @@
"license": "MIT"
},
"node_modules/@github/copilot": {
"version": "0.0.421",
"resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-0.0.421.tgz",
"integrity": "sha512-nDUt9f5al7IgBOTc7AwLpqvaX61VsRDYDQ9D5iR0QQzHo4pgDcyOXIjXUQUKsJwObXHfh6qR+Jm1vnlbw5cacg==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.2.tgz",
"integrity": "sha512-716SIZMYftldVcJay2uZOzsa9ROGGb2Mh2HnxbDxoisFsWNNgZlQXlV7A+PYoGsnAo2Zk/8e1i5SPTscGf2oww==",
"license": "SEE LICENSE IN LICENSE.md",
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
"@github/copilot-darwin-arm64": "0.0.421",
"@github/copilot-darwin-x64": "0.0.421",
"@github/copilot-linux-arm64": "0.0.421",
"@github/copilot-linux-x64": "0.0.421",
"@github/copilot-win32-arm64": "0.0.421",
"@github/copilot-win32-x64": "0.0.421"
"@github/copilot-darwin-arm64": "1.0.2",
"@github/copilot-darwin-x64": "1.0.2",
"@github/copilot-linux-arm64": "1.0.2",
"@github/copilot-linux-x64": "1.0.2",
"@github/copilot-win32-arm64": "1.0.2",
"@github/copilot-win32-x64": "1.0.2"
}
},
"node_modules/@github/copilot-darwin-arm64": {
"version": "0.0.421",
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-0.0.421.tgz",
"integrity": "sha512-S4plFsxH7W8X1gEkGNcfyKykIji4mNv8BP/GpPs2Ad84qWoJpZzfZsjrjF0BQ8mvFObWp6Ft2SZOnJzFZW1Ftw==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.2.tgz",
"integrity": "sha512-dYoeaTidsphRXyMjvAgpjEbBV41ipICnXURrLFEiATcjC4IY6x2BqPOocrExBYW/Tz2VZvDw51iIZaf6GXrTmw==",
"cpu": [
"arm64"
],
@@ -3215,9 +3215,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
"version": "0.0.421",
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-0.0.421.tgz",
"integrity": "sha512-h+Dbfq8ByAielLYIeJbjkN/9Abs6AKHFi+XuuzEy4YA9jOA42uKMFsWYwaoYH8ZLK9Y+4wagYI9UewVPnyIWPA==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.2.tgz",
"integrity": "sha512-8+Z9dYigEfXf0wHl9c2tgFn8Cr6v4RAY8xTgHMI9mZInjQyxVeBXCxbE2VgzUtDUD3a705Ka2d8ZOz05aYtGsg==",
"cpu": [
"x64"
],
@@ -3231,9 +3231,9 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
"version": "0.0.421",
"resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-0.0.421.tgz",
"integrity": "sha512-cxlqDRR/wKfbdzd456N2h7sZOZY069wU2ycSYSmo7cC75U5DyhMGYAZwyAhvQ7UKmS5gJC/wgSgye0njuK22Xg==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.2.tgz",
"integrity": "sha512-ik0Y5aTXOFRPLFrNjZJdtfzkozYqYeJjVXGBAH3Pp1nFZRu/pxJnrnQ1HrqO/LEgQVbJzAjQmWEfMbXdQIxE4Q==",
"cpu": [
"arm64"
],
@@ -3247,9 +3247,9 @@
}
},
"node_modules/@github/copilot-linux-x64": {
"version": "0.0.421",
"resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-0.0.421.tgz",
"integrity": "sha512-7np5b6EEemJ3U3jnl92buJ88nlpqOAIrLaJxx3pJGrP9SVFMBD/6EAlfIQ5m5QTfs+/vIuTKWBrq1wpFVZZUcQ==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.2.tgz",
"integrity": "sha512-mHSPZjH4nU9rwbfwLxYJ7CQ90jK/Qu1v2CmvBCUPfmuGdVwrpGPHB5FrB+f+b0NEXjmemDWstk2zG53F7ppHfw==",
"cpu": [
"x64"
],
@@ -3263,9 +3263,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
"version": "0.0.421",
"resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-0.0.421.tgz",
"integrity": "sha512-T6qCqOnijD5pmC0ytVsahX3bpDnXtLTgo9xFGo/BGaPEvX02ePkzcRZkfkOclkzc8QlkVji6KqZYB+qMZTliwg==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.2.tgz",
"integrity": "sha512-tLW2CY/vg0fYLp8EuiFhWIHBVzbFCDDpohxT/F/XyMAdTVSZLnopCcxQHv2BOu0CVGrYjlf7YOIwPfAKYml1FA==",
"cpu": [
"arm64"
],
@@ -3279,9 +3279,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
"version": "0.0.421",
"resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-0.0.421.tgz",
"integrity": "sha512-KDfy3wsRQFIcOQDdd5Mblvh+DWRq+UGbTQ34wyW36ws1BsdWkV++gk9bTkeJRsPbQ51wsJ0V/jRKEZv4uK5dTA==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.2.tgz",
"integrity": "sha512-cFlc3xMkKKFRIYR00EEJ2XlYAemeh5EZHsGA8Ir2G0AH+DOevJbomdP1yyCC5gaK/7IyPkHX3sGie5sER2yPvQ==",
"cpu": [
"x64"
],

View File

@@ -6062,7 +6062,7 @@
"@anthropic-ai/claude-agent-sdk": "^0.2.63",
"@anthropic-ai/sdk": "^0.78.0",
"@github/blackbird-external-ingest-utils": "^0.3.0",
"@github/copilot": "^0.0.421",
"@github/copilot": "^1.0.2",
"@google/genai": "^1.22.0",
"@humanwhocodes/gitignore-to-minimatch": "1.0.2",
"@microsoft/tiktokenizer": "^1.0.10",

View File

@@ -38,6 +38,7 @@ interface ViewTool {
arguments: {
path: string;
view_range?: [number, number];
forceReadLargeFiles?: boolean;
};
}
@@ -50,13 +51,6 @@ interface EditTool {
};
}
interface UndoEditTool {
toolName: 'undo_edit';
arguments: {
path: string;
};
}
interface StrReplaceTool {
toolName: 'str_replace';
arguments: {
@@ -121,13 +115,13 @@ interface GrepTool {
arguments: {
pattern: string;
path?: string;
output_mode: 'content' | 'files_with_matches' | 'count';
output_mode?: 'content' | 'files_with_matches' | 'count';
glob?: string;
type?: string;
'-i'?: boolean;
'-A'?: boolean;
'-B'?: boolean;
'-C'?: boolean;
'-A'?: number;
'-B'?: number;
'-C'?: number;
'-n'?: boolean;
head_limit?: number;
multiline?: boolean;
@@ -187,26 +181,10 @@ type WebSearchTool = {
};
};
type SearchTool = {
toolName: 'search';
type SearchCodeSubagentTool = {
toolName: 'search_code_subagent';
arguments: {
question: string;
reason: string;
searchCommand: string;
};
};
type SearchBashTool = {
toolName: 'search_bash';
arguments: {
command: string;
};
};
type SemanticCodeSearchTool = {
toolName: 'semantic_code_search';
arguments: {
question: string;
query: string;
};
};
@@ -230,7 +208,7 @@ type ShowFileTool = {
toolName: 'show_file';
arguments: {
path: string;
view_range?: [number, number];
view_range?: number[];
diff?: boolean;
};
};
@@ -258,10 +236,18 @@ type TaskCompleteTool = {
type AskUserTool = {
toolName: 'ask_user';
arguments: {
arguments:
| {
question: string;
choices?: string[];
allow_freeform?: boolean;
}
| {
message: string;
requestedSchema: {
properties: Record<string, unknown>;
required?: string[];
};
};
};
@@ -331,10 +317,19 @@ type LspTool = {
};
};
type CreatePullRequestTool = {
toolName: 'create_pull_request';
arguments: {
title: string;
description?: string;
draft?: boolean;
};
};
type DependencyCheckerTool = {
toolName: 'gh-advisory-database';
arguments: {
dependencies: { version: string; name: string }[];
dependencies: { version: string; name: string; ecosystem: string }[];
};
};
@@ -345,6 +340,7 @@ type StoreMemoryTool = {
fact: string;
citations: string;
reason: string;
category: string;
};
};
@@ -354,24 +350,24 @@ type ParallelValidationTool = {
};
type StringReplaceArgumentTypes = CreateTool | ViewTool | StrReplaceTool | EditTool | InsertTool | UndoEditTool;
type StringReplaceArgumentTypes = CreateTool | ViewTool | StrReplaceTool | EditTool | InsertTool;
type ToStringReplaceEditorArguments<T extends StringReplaceArgumentTypes> = {
command: T['toolName'];
} & T['arguments'];
type StringReplaceEditorTool = {
toolName: 'str_replace_editor';
arguments: ToStringReplaceEditorArguments<CreateTool> | ToStringReplaceEditorArguments<ViewTool> | ToStringReplaceEditorArguments<EditTool> | ToStringReplaceEditorArguments<StrReplaceTool> |
ToStringReplaceEditorArguments<UndoEditTool> | ToStringReplaceEditorArguments<InsertTool>;
ToStringReplaceEditorArguments<InsertTool>;
};
export type ToolInfo = StringReplaceEditorTool | EditTool | CreateTool | ViewTool | UndoEditTool | InsertTool |
export type ToolInfo = StringReplaceEditorTool | EditTool | CreateTool | ViewTool | InsertTool |
ShellTool | WriteShellTool | ReadShellTool | StopShellTool | ListShellTool |
GrepTool | GLobTool |
ReportIntentTool | ThinkTool | ReportProgressTool |
SearchTool | SearchBashTool | SemanticCodeSearchTool |
SearchCodeSubagentTool |
ReplyToCommentTool | CodeReviewTool | WebFetchTool | UpdateTodoTool | WebSearchTool |
ShowFileTool | FetchCopilotCliDocumentationTool | ProposeWorkTool | TaskCompleteTool |
AskUserTool | SkillTool | TaskTool | ListAgentsTool | ReadAgentTool |
ExitPlanModeTool | SqlTool | LspTool | DependencyCheckerTool | StoreMemoryTool | ParallelValidationTool;
ExitPlanModeTool | SqlTool | LspTool | CreatePullRequestTool | DependencyCheckerTool | StoreMemoryTool | ParallelValidationTool;
export type ToolCall = ToolInfo & {
toolCallId: string;
@@ -420,7 +416,7 @@ export function getAffectedUrisForEditTool(data: { toolName: string; arguments?:
return [URI.file(toolCall.arguments.path)];
}
if ((toolCall.toolName === 'create' || toolCall.toolName === 'edit' || toolCall.toolName === 'undo_edit') && typeof toolCall.arguments.path === 'string') {
if ((toolCall.toolName === 'create' || toolCall.toolName === 'edit') && typeof toolCall.arguments.path === 'string') {
return [URI.file(toolCall.arguments.path)];
}
@@ -812,6 +808,13 @@ export function createCopilotCLIToolInvocation(data: {
}
return undefined;
}
if (toolCall.toolName === 'show_file') {
// Currently there's no good way to render this to the user.
// Its a way to draw users attention to a file/code block.
// Generally models render the codeblock in the response, but here we have a tool call.
// Its a WIP, no clear way to render in CLI either, hence decided to hide in VS Code.
return undefined;
}
const [friendlyToolName, formatter] = ToolFriendlyNameAndHandlers[toolCall.toolName];
const invocation = new ChatToolInvocationPart(friendlyToolName ?? toolCall.toolName ?? 'unknown', toolCall.toolCallId ?? '', false as unknown as string);
@@ -827,14 +830,12 @@ type PostInvocationFormatter = (invocation: ChatToolInvocationPart, toolCall: To
type ToolCallFor<T extends ToolCall['toolName']> = Extract<ToolCall, { toolName: T }>;
type ToolCallResult = ToolExecutionCompleteEvent['data'];
const ToolFriendlyNameAndHandlers: { [K in ToolCall['toolName']]: [title: string, pre: (invocation: ChatToolInvocationPart, toolCall: ToolCallFor<K>, editId?: string, workingDirectory?: URI) => void, post: (invocation: ChatToolInvocationPart, toolCall: ToolCallFor<K>, result: ToolCallResult, workingDirectory?: URI) => void] } = {
'str_replace_editor': [l10n.t('Edit File'), formatStrReplaceEditorInvocation, genericToolInvocationCompleted],
'edit': [l10n.t('Edit File'), formatEditToolInvocation, genericToolInvocationCompleted],
'str_replace': [l10n.t('Edit File'), formatEditToolInvocation, genericToolInvocationCompleted],
'create': [l10n.t('Create File'), formatCreateToolInvocation, genericToolInvocationCompleted],
'insert': [l10n.t('Edit File'), formatInsertToolInvocation, genericToolInvocationCompleted],
'undo_edit': [l10n.t('Edit File'), formatUndoEdit, genericToolInvocationCompleted],
'view': [l10n.t('Read'), formatViewToolInvocation, genericToolInvocationCompleted],
'bash': [l10n.t('Run Shell Command'), formatShellInvocation, formatShellInvocationCompleted],
'powershell': [l10n.t('Run Shell Command'), formatShellInvocation, formatShellInvocationCompleted],
@@ -844,12 +845,10 @@ const ToolFriendlyNameAndHandlers: { [K in ToolCall['toolName']]: [title: string
'read_powershell': [l10n.t('Read Terminal'), emptyInvocation, genericToolInvocationCompleted],
'stop_bash': [l10n.t('Stop Terminal Session'), emptyInvocation, genericToolInvocationCompleted],
'stop_powershell': [l10n.t('Stop Terminal Session'), emptyInvocation, genericToolInvocationCompleted],
'search': [l10n.t('Search'), formatSearchToolInvocation, genericToolInvocationCompleted],
'grep': [l10n.t('Search'), formatSearchToolInvocation, formatSearchToolInvocationCompleted],
'rg': [l10n.t('Search'), formatSearchToolInvocation, formatSearchToolInvocationCompleted],
'glob': [l10n.t('Search'), formatSearchToolInvocation, formatSearchToolInvocationCompleted],
'search_bash': [l10n.t('Search'), formatSearchToolInvocation, genericToolInvocationCompleted],
'semantic_code_search': [l10n.t('Search'), formatSearchToolInvocation, genericToolInvocationCompleted],
'search_code_subagent': [l10n.t('Search Code'), formatSearchToolInvocation, genericToolInvocationCompleted],
'reply_to_comment': [l10n.t('Reply to Comment'), formatReplyToCommentInvocation, genericToolInvocationCompleted],
'code_review': [l10n.t('Code Review'), formatCodeReviewInvocation, genericToolInvocationCompleted],
'report_intent': [l10n.t('Report Intent'), emptyInvocation, genericToolInvocationCompleted],
@@ -870,6 +869,7 @@ const ToolFriendlyNameAndHandlers: { [K in ToolCall['toolName']]: [title: string
'exit_plan_mode': [l10n.t('Exit Plan Mode'), formatExitPlanModeInvocation, genericToolInvocationCompleted],
'sql': [l10n.t('Execute SQL'), formatSqlInvocation, genericToolInvocationCompleted],
'lsp': [l10n.t('Language Server'), formatLspInvocation, genericToolInvocationCompleted],
'create_pull_request': [l10n.t('Create Pull Request'), formatCreatePullRequestInvocation, genericToolInvocationCompleted],
'gh-advisory-database': [l10n.t('Check Dependencies'), emptyInvocation, genericToolInvocationCompleted],
'store_memory': [l10n.t('Store Memory'), formatStoreMemoryInvocation, genericToolInvocationCompleted],
'list_bash': [l10n.t('List Shell Sessions'), emptyInvocation, genericToolInvocationCompleted],
@@ -893,7 +893,7 @@ function formatViewToolInvocation(invocation: ChatToolInvocationPart, toolCall:
if (!args.path) {
return;
} else if (args.view_range && args.view_range[1] >= args.view_range[0] && args.view_range[0] >= 0) {
} else if (args.view_range && args.view_range.length === 2 && args.view_range[1] >= args.view_range[0] && args.view_range[0] >= 0) {
const [start, end] = args.view_range;
const location = new Location(Uri.file(args.path), new Range(start === 0 ? start : start - 1, 0, end, 0));
const display = formatUriForFileWidget(location);
@@ -930,9 +930,6 @@ function formatStrReplaceEditorInvocation(invocation: ChatToolInvocationPart, to
case 'create':
formatCreateToolInvocation(invocation, { toolName: 'create', arguments: args } as CreateTool);
break;
case 'undo_edit':
formatUndoEdit(invocation, { toolName: 'undo_edit', arguments: args } as UndoEditTool);
break;
default:
invocation.invocationMessage = new MarkdownString(l10n.t("Modified {0}", display));
}
@@ -945,14 +942,6 @@ function formatInsertToolInvocation(invocation: ChatToolInvocationPart, toolCall
}
}
function formatUndoEdit(invocation: ChatToolInvocationPart, toolCall: UndoEditTool): void {
const args = toolCall.arguments;
if (args.path) {
invocation.invocationMessage = new MarkdownString(l10n.t("Undoing edit in {0}", formatUriForFileWidget(Uri.file(args.path))));
invocation.pastTenseMessage = new MarkdownString(l10n.t("Undid edit in {0}", formatUriForFileWidget(Uri.file(args.path))));
}
}
function formatEditToolInvocation(invocation: ChatToolInvocationPart, toolCall: EditTool, editId?: string): void {
const args = toolCall.arguments;
const display = args.path ? formatUriForFileWidget(Uri.file(args.path)) : '';
@@ -1054,14 +1043,8 @@ function formatShellInvocationCompleted(invocation: ChatToolInvocationPart, tool
};
invocation.toolSpecificData = toolSpecificData;
}
function formatSearchToolInvocation(invocation: ChatToolInvocationPart, toolCall: SearchTool | GLobTool | GrepTool | SearchBashTool | SemanticCodeSearchTool): void {
if (toolCall.toolName === 'search') {
invocation.invocationMessage = `Criteria: ${toolCall.arguments.question} \nReason: ${toolCall.arguments.reason}`;
} else if (toolCall.toolName === 'semantic_code_search') {
invocation.invocationMessage = `Criteria: ${toolCall.arguments.question}`;
} else if (toolCall.toolName === 'search_bash') {
invocation.invocationMessage = `Command: \`${toolCall.arguments.command}\``;
} else if (toolCall.toolName === 'glob') {
function formatSearchToolInvocation(invocation: ChatToolInvocationPart, toolCall: SearchCodeSubagentTool | GLobTool | GrepTool): void {
if (toolCall.toolName === 'glob') {
const searchInPath = toolCall.arguments.path ? ` in \`${toolCall.arguments.path}\`` : '';
invocation.invocationMessage = `Search for files matching \`${toolCall.arguments.pattern}\`${searchInPath}`;
invocation.pastTenseMessage = `Searched for files matching \`${toolCall.arguments.pattern}\`${searchInPath}`;
@@ -1069,17 +1052,14 @@ function formatSearchToolInvocation(invocation: ChatToolInvocationPart, toolCall
const searchInPath = toolCall.arguments.path ? ` in \`${toolCall.arguments.path}\`` : '';
invocation.invocationMessage = `Search for files matching \`${toolCall.arguments.pattern}\`${searchInPath}`;
invocation.pastTenseMessage = `Searched for files matching \`${toolCall.arguments.pattern}\`${searchInPath}`;
} else if (toolCall.toolName === 'search_code_subagent') {
invocation.invocationMessage = `Criteria: ${toolCall.arguments.query}`;
invocation.pastTenseMessage = `Searched code for: ${toolCall.arguments.query}`;
}
}
function formatSearchToolInvocationCompleted(invocation: ChatToolInvocationPart, toolCall: SearchTool | GLobTool | GrepTool | SearchBashTool | SemanticCodeSearchTool, result: ToolCallResult, workingDirectory?: URI): void {
if (toolCall.toolName === 'search') {
// invocation.invocationMessage = `Criteria: ${toolCall.arguments.question} \nReason: ${toolCall.arguments.reason}`;
} else if (toolCall.toolName === 'semantic_code_search') {
// invocation.invocationMessage = `Criteria: ${toolCall.arguments.question}`;
} else if (toolCall.toolName === 'search_bash') {
// invocation.invocationMessage = `Command: \`${toolCall.arguments.command}\``;
} else if (toolCall.toolName === 'glob' || toolCall.toolName === 'grep' || toolCall.toolName === 'rg') {
function formatSearchToolInvocationCompleted(invocation: ChatToolInvocationPart, toolCall: SearchCodeSubagentTool | GLobTool | GrepTool, result: ToolCallResult, workingDirectory?: URI): void {
if (toolCall.toolName === 'glob' || toolCall.toolName === 'grep' || toolCall.toolName === 'rg') {
const messagesIndicatingNoMatches = ['Pattern matched but no output generated', 'Pattern matched but no files found', 'No matches found', 'no files matched the pattern'].map(msg => msg.toLowerCase());
let searchPath = toolCall.arguments.path ? Uri.file(toolCall.arguments.path) : workingDirectory;
@@ -1130,10 +1110,14 @@ function formatShowFileInvocation(invocation: ChatToolInvocationPart, toolCall:
if (args.diff) {
invocation.invocationMessage = new MarkdownString(l10n.t("Showing diff of {0}", display));
invocation.pastTenseMessage = new MarkdownString(l10n.t("Showed diff of {0}", display));
} else if (args.view_range && args.view_range.length === 2) {
} else if (args.view_range && args.view_range.length >= 2) {
const [start, end] = args.view_range;
invocation.invocationMessage = new MarkdownString(l10n.t("Showing {0}, lines {1} to {2}", display, start, end));
invocation.pastTenseMessage = new MarkdownString(l10n.t("Showed {0}, lines {1} to {2}", display, start, end));
} else if (args.view_range && args.view_range.length === 1) {
const [line] = args.view_range;
invocation.invocationMessage = new MarkdownString(l10n.t("Showing {0}, line {1}", display, line));
invocation.pastTenseMessage = new MarkdownString(l10n.t("Showed {0}, line {1}", display, line));
} else {
invocation.invocationMessage = new MarkdownString(l10n.t("Showing {0}", display));
invocation.pastTenseMessage = new MarkdownString(l10n.t("Showed {0}", display));
@@ -1151,7 +1135,14 @@ function formatTaskCompleteInvocation(invocation: ChatToolInvocationPart, toolCa
}
function formatAskUserInvocation(invocation: ChatToolInvocationPart, toolCall: AskUserTool): void {
invocation.invocationMessage = toolCall.arguments.question || l10n.t('Asking user a question');
if ('question' in toolCall.arguments) {
invocation.invocationMessage = toolCall.arguments.question || l10n.t('Asking user a question');
invocation.pastTenseMessage = toolCall.arguments.question || l10n.t('Asked user a question');
return;
}
invocation.invocationMessage = toolCall.arguments.message || l10n.t('Asking user for input');
invocation.pastTenseMessage = toolCall.arguments.message || l10n.t('Asked user for input');
}
function formatSkillInvocation(invocation: ChatToolInvocationPart, toolCall: SkillTool): void {
@@ -1190,6 +1181,14 @@ function formatLspInvocation(invocation: ChatToolInvocationPart, toolCall: LspTo
}
}
function formatCreatePullRequestInvocation(invocation: ChatToolInvocationPart, toolCall: CreatePullRequestTool): void {
invocation.invocationMessage = toolCall.arguments.title || l10n.t('Creating pull request');
invocation.pastTenseMessage = toolCall.arguments.title || l10n.t('Created pull request');
if (toolCall.arguments.description) {
invocation.originMessage = toolCall.arguments.description;
}
}
function formatStoreMemoryInvocation(invocation: ChatToolInvocationPart, toolCall: StoreMemoryTool): void {
invocation.invocationMessage = l10n.t("Storing memory: {0}", toolCall.arguments.subject);
invocation.pastTenseMessage = l10n.t("Stored memory: {0}", toolCall.arguments.subject);

View File

@@ -244,17 +244,17 @@ describe('CopilotCLITools', () => {
const msg = getInvocationMessageText(part as ChatToolInvocationPart);
expect(msg).toMatch(/Creat/);
});
it('formats show_file invocation with path', () => {
it.skip('formats show_file invocation with path', () => {
const part = createCopilotCLIToolInvocation({ toolName: 'show_file', toolCallId: 'sf1', arguments: { path: '/tmp/file.ts' } });
expect(part).toBeInstanceOf(ChatToolInvocationPart);
expect(getInvocationMessageText(part as ChatToolInvocationPart)).toMatch(/Showing.*file\.ts/);
});
it('formats show_file invocation with diff mode', () => {
it.skip('formats show_file invocation with diff mode', () => {
const part = createCopilotCLIToolInvocation({ toolName: 'show_file', toolCallId: 'sf2', arguments: { path: '/tmp/file.ts', diff: true } });
expect(part).toBeInstanceOf(ChatToolInvocationPart);
expect(getInvocationMessageText(part as ChatToolInvocationPart)).toMatch(/diff/i);
});
it('formats show_file invocation with view_range', () => {
it.skip('formats show_file invocation with view_range', () => {
const part = createCopilotCLIToolInvocation({ toolName: 'show_file', toolCallId: 'sf3', arguments: { path: '/tmp/file.ts', view_range: [10, 20] } });
expect(part).toBeInstanceOf(ChatToolInvocationPart);
const msg = getInvocationMessageText(part as ChatToolInvocationPart);
@@ -281,6 +281,23 @@ describe('CopilotCLITools', () => {
expect(part).toBeInstanceOf(ChatToolInvocationPart);
expect(getInvocationMessageText(part as ChatToolInvocationPart)).toContain('Which DB?');
});
it('formats ask_user invocation with structured message', () => {
const part = createCopilotCLIToolInvocation({
toolName: 'ask_user',
toolCallId: 'au2',
arguments: {
message: 'Pick a deployment target',
requestedSchema: {
properties: {
target: { type: 'string', enum: ['staging', 'prod'] }
},
required: ['target']
}
}
});
expect(part).toBeInstanceOf(ChatToolInvocationPart);
expect(getInvocationMessageText(part as ChatToolInvocationPart)).toContain('Pick a deployment target');
});
it('formats skill invocation', () => {
const part = createCopilotCLIToolInvocation({ toolName: 'skill', toolCallId: 'sk1', arguments: { skill: 'pdf' } });
expect(part).toBeInstanceOf(ChatToolInvocationPart);
@@ -318,8 +335,19 @@ describe('CopilotCLITools', () => {
expect(part).toBeInstanceOf(ChatToolInvocationPart);
expect(getInvocationMessageText(part as ChatToolInvocationPart)).toContain('workspaceSymbol');
});
it('formats create_pull_request invocation', () => {
const part = createCopilotCLIToolInvocation({ toolName: 'create_pull_request', toolCallId: 'pr1', arguments: { title: 'Fix auth flow', description: 'Summary of changes', draft: false } });
expect(part).toBeInstanceOf(ChatToolInvocationPart);
expect(getInvocationMessageText(part as ChatToolInvocationPart)).toContain('Fix auth flow');
expect((part as ChatToolInvocationPart).originMessage).toContain('Summary of changes');
});
it('formats search_code_subagent invocation', () => {
const part = createCopilotCLIToolInvocation({ toolName: 'search_code_subagent', toolCallId: 'sc1', arguments: { query: 'find auth middleware' } });
expect(part).toBeInstanceOf(ChatToolInvocationPart);
expect(getInvocationMessageText(part as ChatToolInvocationPart)).toContain('find auth middleware');
});
it('formats store_memory invocation', () => {
const part = createCopilotCLIToolInvocation({ toolName: 'store_memory', toolCallId: 'sm1', arguments: { subject: 'naming', fact: 'Use camelCase', citations: 'src/foo.ts:1', reason: 'consistency' } });
const part = createCopilotCLIToolInvocation({ toolName: 'store_memory', toolCallId: 'sm1', arguments: { subject: 'naming', fact: 'Use camelCase', citations: 'src/foo.ts:1', reason: 'consistency', category: 'general' } });
expect(part).toBeInstanceOf(ChatToolInvocationPart);
expect(getInvocationMessageText(part as ChatToolInvocationPart)).toContain('naming');
});
@@ -340,7 +368,7 @@ describe('CopilotCLITools', () => {
expect(part).toBeInstanceOf(ChatToolInvocationPart);
});
it('creates invocation for gh-advisory-database', () => {
const part = createCopilotCLIToolInvocation({ toolName: 'gh-advisory-database', toolCallId: 'gh1', arguments: { dependencies: [{ name: 'lodash', version: '4.17.0' }] } });
const part = createCopilotCLIToolInvocation({ toolName: 'gh-advisory-database', toolCallId: 'gh1', arguments: { dependencies: [{ name: 'lodash', version: '4.17.0', ecosystem: 'npm' }] } });
expect(part).toBeInstanceOf(ChatToolInvocationPart);
});
it('creates invocation for parallel_validation', () => {

View File

@@ -17,6 +17,7 @@ import { ChatDelegationSummaryService, IChatDelegationSummaryService } from '../
import { emptyWorkspaceInfo, IWorkspaceInfo } from '../../src/extension/chatSessions/common/workspaceInfo';
import { CopilotCLIAgents, CopilotCLIModels, CopilotCLISDK, CopilotCLISessionOptions, ICopilotCLIAgents, ICopilotCLIModels, ICopilotCLISDK } from '../../src/extension/chatSessions/copilotcli/node/copilotCli';
import { CopilotCLIImageSupport, ICopilotCLIImageSupport } from '../../src/extension/chatSessions/copilotcli/node/copilotCLIImageSupport';
import { CopilotCLISkills, ICopilotCLISkills } from '../../src/extension/chatSessions/copilotcli/node/copilotCLISkills';
import { CopilotCLIPromptResolver } from '../../src/extension/chatSessions/copilotcli/node/copilotcliPromptResolver';
import { ICopilotCLISession } from '../../src/extension/chatSessions/copilotcli/node/copilotcliSession';
import { CopilotCLISessionService, ICopilotCLISessionService } from '../../src/extension/chatSessions/copilotcli/node/copilotcliSessionService';
@@ -231,6 +232,7 @@ async function registerChatServices(testingServiceCollection: TestingServiceColl
let instaService = accessor.get(IInstantiationService);
const summarizer = instaService.createInstance(ChatSummarizerProvider);
const delegatingSummarizerProvider = instaService.createInstance(ChatDelegationSummaryService, summarizer);
testingServiceCollection.define(ICopilotCLISkills, new SyncDescriptor(CopilotCLISkills));
testingServiceCollection.define(ICopilotCLISessionService, new SyncDescriptor(TestCopilotCLISessionService));
testingServiceCollection.define(ITestSessionOptionsProvider, new SyncDescriptor(TestSessionOptionsProvider));
testingServiceCollection.define(ILanguageModelServer, new SyncDescriptor(TestLanguageModelServer));