From 6f5f379438f2307f2b3b53d0ce8db0a14d20d515 Mon Sep 17 00:00:00 2001 From: Rob Bos Date: Mon, 30 Mar 2026 22:17:20 +0200 Subject: [PATCH] Fix null safety in response array loops and OpenCode method reference - Fix TypeError: getOpenCodeSessionData was called on tokenTracker directly instead of tokenTracker.openCode where the method actually lives; this caused 'tokenTracker.getOpenCodeSessionData is not a function' warnings during backend sync for every OpenCode session file. - Fix TypeError: Cannot read properties of undefined (reading 'value') in getModelUsageFromSession: response arrays reconstructed from VS Code delta-based JSONL can contain null/undefined entries; use optional chaining (responseItem?.value) instead of bare property access. - Fix TypeError: Cannot read properties of undefined (reading 'kind') in analyzeSessionUsage and trackEnhancedMetrics: add an explicit 'if (!responseItem) continue' guard at the top of every loop that iterates over request.response or event.v arrays, covering both the delta-path and JSON-path code branches. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- vscode-extension/src/extension.ts | 2 +- vscode-extension/src/usageAnalysis.ts | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/vscode-extension/src/extension.ts b/vscode-extension/src/extension.ts index a4d6ff4..d79ce66 100644 --- a/vscode-extension/src/extension.ts +++ b/vscode-extension/src/extension.ts @@ -7041,7 +7041,7 @@ export function activate(context: vscode.ExtensionContext) { isOpenCodeSession: (sessionFile: string) => (tokenTracker as any).openCode.isOpenCodeSessionFile(sessionFile), getOpenCodeSessionData: (sessionFile: string) => - (tokenTracker as any).getOpenCodeSessionData(sessionFile), + (tokenTracker as any).openCode.getOpenCodeSessionData(sessionFile), }); const backendHandler = new BackendCommandHandler({ diff --git a/vscode-extension/src/usageAnalysis.ts b/vscode-extension/src/usageAnalysis.ts index 2efea00..259b8f2 100644 --- a/vscode-extension/src/usageAnalysis.ts +++ b/vscode-extension/src/usageAnalysis.ts @@ -811,6 +811,7 @@ export async function trackEnhancedMetrics(deps: Pick // Track edit scope and apply usage if (request.response && Array.isArray(request.response)) { for (const resp of request.response) { + if (!resp) { continue; } if (resp.kind === 'textEditGroup' && resp.uri) { const filePath = resp.uri.path || JSON.stringify(resp.uri); editedFiles.add(filePath); @@ -866,6 +867,7 @@ export async function trackEnhancedMetrics(deps: Pick // Track edit scope and apply usage if (request.response && Array.isArray(request.response)) { for (const resp of request.response) { + if (!resp) { continue; } if (resp.kind === 'textEditGroup' && resp.uri) { const filePath = resp.uri.path || JSON.stringify(resp.uri); editedFiles.add(filePath); @@ -1258,6 +1260,7 @@ export async function analyzeSessionUsage(deps: UsageAnalysisDeps, sessionFile: // Extract tool calls and MCP tools from request.response array if (request.response && Array.isArray(request.response)) { for (const responseItem of request.response) { + if (!responseItem) { continue; } if (responseItem.kind === 'toolInvocationSerialized' || responseItem.kind === 'prepareToolInvocation') { const toolName = responseItem.toolId || responseItem.toolName || responseItem.invocationMessage?.toolName || responseItem.toolSpecificData?.kind || 'unknown'; @@ -1365,6 +1368,7 @@ export async function analyzeSessionUsage(deps: UsageAnalysisDeps, sessionFile: // Extract tool calls from request.response array (when full request is added) if (request.response && Array.isArray(request.response)) { for (const responseItem of request.response) { + if (!responseItem) { continue; } if (responseItem.kind === 'toolInvocationSerialized' || responseItem.kind === 'prepareToolInvocation') { analysis.toolCalls.total++; const toolName = responseItem.toolId || responseItem.toolName || responseItem.invocationMessage?.toolName || responseItem.toolSpecificData?.kind || 'unknown'; @@ -1378,6 +1382,7 @@ export async function analyzeSessionUsage(deps: UsageAnalysisDeps, sessionFile: // Handle VS Code incremental format - tool invocations in responses if (event.kind === 2 && event.k?.includes('response') && Array.isArray(event.v)) { for (const responseItem of event.v) { + if (!responseItem) { continue; } if (responseItem.kind === 'toolInvocationSerialized') { analysis.toolCalls.total++; const toolName = responseItem.toolId || responseItem.toolName || responseItem.invocationMessage?.toolName || responseItem.toolSpecificData?.kind || 'unknown'; @@ -1485,6 +1490,7 @@ export async function analyzeSessionUsage(deps: UsageAnalysisDeps, sessionFile: // Analyze response for tool calls and MCP tools if (request.response && Array.isArray(request.response)) { for (const responseItem of request.response) { + if (!responseItem) { continue; } // Detect tool invocations if (responseItem.kind === 'toolInvocationSerialized' || responseItem.kind === 'prepareToolInvocation') { @@ -1698,7 +1704,7 @@ export async function getModelUsageFromSession(deps: Pick