From 218eb81c7afefbc1a4621e6dab72bf8ee4548225 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Tue, 18 Nov 2025 23:10:45 +0000 Subject: [PATCH 1/4] feat: add toolProtocol property to PostHog tool usage telemetry --- packages/telemetry/src/TelemetryService.ts | 4 ++-- src/core/assistant-message/presentAssistantMessage.ts | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/telemetry/src/TelemetryService.ts b/packages/telemetry/src/TelemetryService.ts index 5ea4cef936f..67fb13cee48 100644 --- a/packages/telemetry/src/TelemetryService.ts +++ b/packages/telemetry/src/TelemetryService.ts @@ -98,8 +98,8 @@ export class TelemetryService { this.captureEvent(TelemetryEventName.MODE_SWITCH, { taskId, newMode }) } - public captureToolUsage(taskId: string, tool: string): void { - this.captureEvent(TelemetryEventName.TOOL_USED, { taskId, tool }) + public captureToolUsage(taskId: string, tool: string, toolProtocol?: string): void { + this.captureEvent(TelemetryEventName.TOOL_USED, { taskId, tool, toolProtocol }) } public captureCheckpointCreated(taskId: string): void { diff --git a/src/core/assistant-message/presentAssistantMessage.ts b/src/core/assistant-message/presentAssistantMessage.ts index d4389c22e89..71c1da4f6fd 100644 --- a/src/core/assistant-message/presentAssistantMessage.ts +++ b/src/core/assistant-message/presentAssistantMessage.ts @@ -430,7 +430,10 @@ export async function presentAssistantMessage(cline: Task) { if (!block.partial) { cline.recordToolUsage(block.name) - TelemetryService.instance.captureToolUsage(cline.taskId, block.name) + // Determine protocol: native if tool has an ID, otherwise XML + const toolCallId = (block as any).id + const toolProtocol = toolCallId ? "native" : "xml" + TelemetryService.instance.captureToolUsage(cline.taskId, block.name, toolProtocol) } // Validate tool use before execution. From 97fab750fbc49a5e2048faa4e77d6699d76c2fa8 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Wed, 19 Nov 2025 01:16:11 +0000 Subject: [PATCH 2/4] refactor: eliminate duplicate toolProtocol detection logic and make parameter required - Extract toolProtocol variable once at protocol detection point (line 288) - Remove duplicate detection logic at telemetry capture point (line 434) - Make toolProtocol parameter required (not optional) in TelemetryService.captureToolUsage() - Ensures consistent protocol detection and required telemetry data --- packages/telemetry/src/TelemetryService.ts | 2 +- src/core/assistant-message/presentAssistantMessage.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/telemetry/src/TelemetryService.ts b/packages/telemetry/src/TelemetryService.ts index 67fb13cee48..8f4fbe09741 100644 --- a/packages/telemetry/src/TelemetryService.ts +++ b/packages/telemetry/src/TelemetryService.ts @@ -98,7 +98,7 @@ export class TelemetryService { this.captureEvent(TelemetryEventName.MODE_SWITCH, { taskId, newMode }) } - public captureToolUsage(taskId: string, tool: string, toolProtocol?: string): void { + public captureToolUsage(taskId: string, tool: string, toolProtocol: string): void { this.captureEvent(TelemetryEventName.TOOL_USED, { taskId, tool, toolProtocol }) } diff --git a/src/core/assistant-message/presentAssistantMessage.ts b/src/core/assistant-message/presentAssistantMessage.ts index 71c1da4f6fd..ac1f36f0556 100644 --- a/src/core/assistant-message/presentAssistantMessage.ts +++ b/src/core/assistant-message/presentAssistantMessage.ts @@ -285,6 +285,7 @@ export async function presentAssistantMessage(cline: Task) { // XML protocol tool calls NEVER have an ID (parsed from XML text). const toolCallId = (block as any).id const isNative = !!toolCallId + const toolProtocol = toolCallId ? "native" : "xml" const pushToolResult = (content: ToolResponse) => { if (isNative && toolCallId) { @@ -430,9 +431,6 @@ export async function presentAssistantMessage(cline: Task) { if (!block.partial) { cline.recordToolUsage(block.name) - // Determine protocol: native if tool has an ID, otherwise XML - const toolCallId = (block as any).id - const toolProtocol = toolCallId ? "native" : "xml" TelemetryService.instance.captureToolUsage(cline.taskId, block.name, toolProtocol) } From c2c2faaf63a2a417d9e34e52f811a9eb98b540e7 Mon Sep 17 00:00:00 2001 From: Matt Rubens Date: Tue, 18 Nov 2025 20:17:53 -0500 Subject: [PATCH 3/4] Update src/core/assistant-message/presentAssistantMessage.ts --- src/core/assistant-message/presentAssistantMessage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/assistant-message/presentAssistantMessage.ts b/src/core/assistant-message/presentAssistantMessage.ts index ac1f36f0556..79d0e0571c7 100644 --- a/src/core/assistant-message/presentAssistantMessage.ts +++ b/src/core/assistant-message/presentAssistantMessage.ts @@ -285,7 +285,7 @@ export async function presentAssistantMessage(cline: Task) { // XML protocol tool calls NEVER have an ID (parsed from XML text). const toolCallId = (block as any).id const isNative = !!toolCallId - const toolProtocol = toolCallId ? "native" : "xml" + const toolProtocol = isNative ? "native" : "xml" const pushToolResult = (content: ToolResponse) => { if (isNative && toolCallId) { From dcb4229cdc4e484cbbe731690ab323e5a9bf7afa Mon Sep 17 00:00:00 2001 From: daniel-lxs Date: Tue, 18 Nov 2025 20:22:55 -0500 Subject: [PATCH 4/4] fix: make protocol check more explicit --- src/core/assistant-message/presentAssistantMessage.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/core/assistant-message/presentAssistantMessage.ts b/src/core/assistant-message/presentAssistantMessage.ts index 79d0e0571c7..07193ab3cc7 100644 --- a/src/core/assistant-message/presentAssistantMessage.ts +++ b/src/core/assistant-message/presentAssistantMessage.ts @@ -13,7 +13,7 @@ import { fetchInstructionsTool } from "../tools/FetchInstructionsTool" import { listFilesTool } from "../tools/ListFilesTool" import { readFileTool } from "../tools/ReadFileTool" import { getSimpleReadFileToolDescription, simpleReadFileTool } from "../tools/simpleReadFileTool" -import { shouldUseSingleFileRead } from "@roo-code/types" +import { shouldUseSingleFileRead, TOOL_PROTOCOL } from "@roo-code/types" import { writeToFileTool } from "../tools/WriteToFileTool" import { applyDiffTool } from "../tools/MultiApplyDiffTool" import { insertContentTool } from "../tools/InsertContentTool" @@ -284,11 +284,10 @@ export async function presentAssistantMessage(cline: Task) { // Native protocol tool calls ALWAYS have an ID (set when parsed from tool_call chunks). // XML protocol tool calls NEVER have an ID (parsed from XML text). const toolCallId = (block as any).id - const isNative = !!toolCallId - const toolProtocol = isNative ? "native" : "xml" + const toolProtocol = toolCallId ? TOOL_PROTOCOL.NATIVE : TOOL_PROTOCOL.XML const pushToolResult = (content: ToolResponse) => { - if (isNative && toolCallId) { + if (toolProtocol === TOOL_PROTOCOL.NATIVE) { // For native protocol, only allow ONE tool_result per tool call if (hasToolResult) { console.warn( @@ -515,7 +514,7 @@ export async function presentAssistantMessage(cline: Task) { // Check if this tool call came from native protocol by checking for ID // Native calls always have IDs, XML calls never do - if (isNative) { + if (toolProtocol === TOOL_PROTOCOL.NATIVE) { await applyDiffToolClass.handle(cline, block as ToolUse<"apply_diff">, { askApproval, handleError,