diff --git a/vscode-extension/package.json b/vscode-extension/package.json index bd692418..062fc95d 100644 --- a/vscode-extension/package.json +++ b/vscode-extension/package.json @@ -270,6 +270,14 @@ "type": "string", "default": "", "description": "Screenshot/demo mode: when set to a folder path, overrides all session file scanning and returns only .json/.jsonl files from this directory. Leave empty for normal operation." + }, + "copilotTokenTracker.suppressedUnknownTools": { + "type": "array", + "items": { + "type": "string" + }, + "default": [], + "description": "List of tool names to suppress from the 'Unknown Tools Found' section in the Usage Analysis dashboard. Useful for tools you are testing that don't yet have friendly display names." } } } diff --git a/vscode-extension/src/extension.ts b/vscode-extension/src/extension.ts index 88d4e6f1..f32dfaaf 100644 --- a/vscode-extension/src/extension.ts +++ b/vscode-extension/src/extension.ts @@ -3837,6 +3837,19 @@ class CopilotTokenTracker implements vscode.Disposable { vscode.commands.executeCommand('workbench.action.chat.open', { query: message.prompt, isNewChat: true }) ); break; + case 'suppressUnknownTool': { + const toolName = message.toolName as string; + if (toolName) { + const config = vscode.workspace.getConfiguration('copilotTokenTracker'); + const current = config.get('suppressedUnknownTools', []); + if (!current.includes(toolName)) { + await config.update('suppressedUnknownTools', [...current, toolName], vscode.ConfigurationTarget.Global); + this.log(`🔇 Suppressed unknown tool: ${toolName}`); + } + await this.dispatch('refresh:analysis', () => this.refreshAnalysisPanel()); + } + break; + } } }); @@ -7068,6 +7081,10 @@ ${hashtag}`; `[Usage Analysis] Test format 1234567.89: ${new Intl.NumberFormat(detectedLocale).format(1234567.89)}`, ); + const suppressedUnknownTools = vscode.workspace + .getConfiguration('copilotTokenTracker') + .get('suppressedUnknownTools', []); + const initialData = JSON.stringify({ today: stats.today, last30Days: stats.last30Days, @@ -7078,6 +7095,7 @@ ${hashtag}`; lastUpdated: stats.lastUpdated.toISOString(), backendConfigured: this.isBackendConfigured(), currentWorkspacePaths: vscode.workspace.workspaceFolders?.map(f => f.uri.fsPath) ?? [], + suppressedUnknownTools, }).replace(/ diff --git a/vscode-extension/src/webview/usage/main.ts b/vscode-extension/src/webview/usage/main.ts index ce711690..3a81170e 100644 --- a/vscode-extension/src/webview/usage/main.ts +++ b/vscode-extension/src/webview/usage/main.ts @@ -47,6 +47,7 @@ type UsageAnalysisStats = { missedPotential?: MissedPotentialWorkspace[]; backendConfigured?: boolean; currentWorkspacePaths?: string[]; + suppressedUnknownTools?: string[]; }; declare function acquireVsCodeApi(): { @@ -159,9 +160,11 @@ function getUnknownMcpTools(stats: UsageAnalysisStats): string[] { Object.entries(stats.today.toolCalls.byTool).forEach(([tool]) => allTools.add(tool)); Object.entries(stats.last30Days.toolCalls.byTool).forEach(([tool]) => allTools.add(tool)); Object.entries(stats.month.toolCalls.byTool).forEach(([tool]) => allTools.add(tool)); + + const suppressed = new Set(stats.suppressedUnknownTools ?? []); - // Filter to only unknown tools (where lookupToolName returns the same value) - return Array.from(allTools).filter(tool => lookupToolName(tool) === tool).sort(); + // Filter to only unknown tools (where lookupToolName returns the same value) and not suppressed + return Array.from(allTools).filter(tool => lookupToolName(tool) === tool && !suppressed.has(tool)).sort(); } function createMcpToolIssueUrl(unknownTools: string[]): string { @@ -948,7 +951,8 @@ function renderLayout(stats: UsageAnalysisStats): void { if (last30Count > todayCount) { countParts.push(`${last30Count} in the last 30d`); } if (monthCount > last30Count) { countParts.push(`${monthCount} this month`); } const countHtml = countParts.length > 0 ? ` (${countParts.join(' | ')})` : ''; - return `${escapeHtml(tool)}${countHtml}`; + const suppressBtn = ``; + return `${escapeHtml(tool)}${countHtml}${suppressBtn}`; }).join(' '); return `
@@ -1702,6 +1706,15 @@ async function bootstrap(): Promise { console.log('[Usage Analysis] Test format 1234567.89 with received locale:', new Intl.NumberFormat(initialData.locale).format(1234567.89)); setFormatLocale(initialData.locale); renderLayout(initialData); + + // Event delegation for suppress-tool buttons (rendered dynamically in the tools section) + document.addEventListener('click', (event) => { + const target = event.target as HTMLElement; + const toolName = target.getAttribute('data-suppress-tool'); + if (toolName) { + vscode.postMessage({ command: 'suppressUnknownTool', toolName }); + } + }); } void bootstrap();