feat: add tool metadata registry with human-readable labels

Add a builtin tool label registry mapping all ~30 official SDK tool IDs
to human-readable display names. Update listApprovalToolDefinitions to
resolve labels from the registry instead of showing raw tool IDs like
read_bash or fetch_copilot_cli_documentation. Expand the fallback
runtime tool catalog from 6 to 23 non-internal standard tools.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
David Kaya
2026-03-26 19:27:36 +01:00
co-authored by Copilot
parent a1a044e7ca
commit 912677fba0
2 changed files with 111 additions and 9 deletions
+74 -7
View File
@@ -89,15 +89,82 @@ const lspApprovalOperations = [
{ suffix: 'references', label: 'References' },
] as const;
// Human-readable labels for built-in runtime tools.
// Both bash and powershell variants are included for forward compatibility.
const builtinToolLabels: ReadonlyMap<string, string> = new Map([
// Shell tools
['bash', 'Execute shell commands'],
['powershell', 'Execute shell commands'],
['read_bash', 'Read shell output'],
['read_powershell', 'Read shell output'],
['write_bash', 'Write shell input'],
['write_powershell', 'Write shell input'],
['stop_bash', 'Stop shell session'],
['stop_powershell', 'Stop shell session'],
['list_bash', 'List shell sessions'],
['list_powershell', 'List shell sessions'],
// File tools
['view', 'View files'],
['create', 'Create files'],
['edit', 'Edit files'],
['apply_patch', 'Apply patch'],
// Search tools
['grep', 'Search file contents'],
['rg', 'Search file contents'],
['glob', 'Find files by pattern'],
// Agent tools
['task', 'Run sub-agent'],
['read_agent', 'Read agent results'],
['list_agents', 'List agents'],
// Web tools
['web_fetch', 'Fetch web content'],
['web_search', 'Search the web'],
// Other tools
['skill', 'Invoke skill'],
['show_file', 'Show file'],
['fetch_copilot_cli_documentation', 'Fetch CLI docs'],
['update_todo', 'Update checklist'],
['store_memory', 'Store memory'],
['sql', 'Query session data'],
['lsp', 'Language server'],
]);
export function resolveToolLabel(toolId: string): string {
return builtinToolLabels.get(toolId) ?? toolId;
}
// Fallback runtime tools used before sidecar capabilities are loaded or when the
// CLI cannot report its built-in tool catalog dynamically.
const fallbackRuntimeApprovalTools: ReadonlyArray<RuntimeToolDefinition> = [
{ id: 'glob', label: 'glob', description: 'Match files by glob pattern.' },
{ id: 'lsp', label: 'lsp', description: 'Query configured language servers.' },
{ id: 'rg', label: 'rg', description: 'Search file contents with ripgrep.' },
{ id: 'view', label: 'view', description: 'Read files and list directories.' },
{ id: 'web_fetch', label: 'web_fetch', description: 'Fetch content from a URL.' },
{ id: 'web_search', label: 'web_search', description: 'Search the web for current information.' },
// Shell tools (bash variants — SDK reports these on all platforms)
{ id: 'bash', label: 'Execute shell commands' },
{ id: 'read_bash', label: 'Read shell output' },
{ id: 'write_bash', label: 'Write shell input' },
{ id: 'stop_bash', label: 'Stop shell session' },
{ id: 'list_bash', label: 'List shell sessions' },
// File tools
{ id: 'view', label: 'View files' },
{ id: 'create', label: 'Create files' },
{ id: 'edit', label: 'Edit files' },
{ id: 'apply_patch', label: 'Apply patch' },
// Search tools
{ id: 'grep', label: 'Search file contents' },
{ id: 'glob', label: 'Find files by pattern' },
// Agent tools
{ id: 'task', label: 'Run sub-agent' },
{ id: 'read_agent', label: 'Read agent results' },
{ id: 'list_agents', label: 'List agents' },
// Web tools
{ id: 'web_fetch', label: 'Fetch web content' },
{ id: 'web_search', label: 'Search the web' },
// Other tools
{ id: 'skill', label: 'Invoke skill' },
{ id: 'show_file', label: 'Show file' },
{ id: 'fetch_copilot_cli_documentation', label: 'Fetch CLI docs' },
{ id: 'update_todo', label: 'Update checklist' },
{ id: 'store_memory', label: 'Store memory' },
{ id: 'sql', label: 'Query session data' },
{ id: 'lsp', label: 'Language server' },
];
export function createWorkspaceSettings(): WorkspaceSettings {
@@ -171,7 +238,7 @@ export function listApprovalToolDefinitions(
for (const tool of runtimeApprovalTools) {
registerApprovalTool(toolsById, {
id: tool.id,
label: tool.label,
label: resolveToolLabel(tool.id),
description: tool.description,
kind: 'builtin',
providerId: `builtin:${tool.id}`,
+37 -2
View File
@@ -4,6 +4,7 @@ import {
listApprovalToolDefinitions,
normalizeWorkspaceSettings,
resolveProjectToolingSettings,
resolveToolLabel,
resolveWorkspaceToolingSettings,
validateLspProfileDefinition,
validateMcpServerDefinition,
@@ -206,8 +207,7 @@ describe('tooling settings helpers', () => {
expect(tools).toContainEqual({
id: 'web_fetch',
label: 'web_fetch',
description: 'Fetch content from a URL.',
label: 'Fetch web content',
kind: 'builtin',
providerIds: ['builtin:web_fetch'],
providerNames: ['Built-in'],
@@ -251,6 +251,41 @@ describe('tooling settings helpers', () => {
expect(tools.some((tool) => tool.id === 'web_fetch')).toBe(false);
});
test('resolves human-readable labels from the tool metadata registry', () => {
expect(resolveToolLabel('bash')).toBe('Execute shell commands');
expect(resolveToolLabel('read_bash')).toBe('Read shell output');
expect(resolveToolLabel('web_fetch')).toBe('Fetch web content');
expect(resolveToolLabel('fetch_copilot_cli_documentation')).toBe('Fetch CLI docs');
expect(resolveToolLabel('glob')).toBe('Find files by pattern');
expect(resolveToolLabel('lsp')).toBe('Language server');
});
test('passes through unknown tool IDs as labels', () => {
expect(resolveToolLabel('my_custom_tool')).toBe('my_custom_tool');
expect(resolveToolLabel('')).toBe('');
});
test('fallback catalog includes all standard non-internal tools with friendly labels', () => {
const tools = listApprovalToolDefinitions({ mcpServers: [], lspProfiles: [] });
const builtinTools = tools.filter((t) => t.kind === 'builtin');
expect(builtinTools.length).toBeGreaterThanOrEqual(20);
expect(builtinTools.some((t) => t.id === 'bash')).toBe(true);
expect(builtinTools.some((t) => t.id === 'web_fetch')).toBe(true);
expect(builtinTools.some((t) => t.id === 'task')).toBe(true);
expect(builtinTools.some((t) => t.id === 'store_memory')).toBe(true);
// Labels should be human-readable, not raw IDs
const bashTool = builtinTools.find((t) => t.id === 'bash');
expect(bashTool?.label).toBe('Execute shell commands');
// Internal tools should not appear in the fallback
expect(builtinTools.some((t) => t.id === 'ask_user')).toBe(false);
expect(builtinTools.some((t) => t.id === 'report_intent')).toBe(false);
expect(builtinTools.some((t) => t.id === 'task_complete')).toBe(false);
expect(builtinTools.some((t) => t.id === 'exit_plan_mode')).toBe(false);
});
test('resolves workspace and project tooling with accepted discovered MCP servers', () => {
const workspaceTooling = resolveWorkspaceToolingSettings(normalizeWorkspaceSettings({
tooling: {