From 6ba92cb9d8ce01230f75007cabfc812653751d22 Mon Sep 17 00:00:00 2001 From: Colin McDonnell Date: Fri, 21 Nov 2025 14:51:13 -0800 Subject: [PATCH] standardize tool call logging --- agents/claude.ts | 30 ++++-------------------------- agents/codex.ts | 15 ++++++++++++--- agents/cursor.ts | 8 +++----- utils/cli.ts | 40 +++++++++++++++------------------------- 4 files changed, 34 insertions(+), 59 deletions(-) diff --git a/agents/claude.ts b/agents/claude.ts index 7aff563..59d7079 100644 --- a/agents/claude.ts +++ b/agents/claude.ts @@ -62,37 +62,15 @@ const messageHandlers: SDKMessageHandlers = { if (content.type === "text" && content.text?.trim()) { log.box(content.text.trim(), { title: "Claude" }); } else if (content.type === "tool_use") { - log.info(`→ ${content.name}`); - // Track bash tool IDs if (content.name === "bash" && content.id) { bashToolIds.add(content.id); } - if (content.input) { - const input = content.input as any; - if (input.description) log.info(` └─ ${input.description}`); - if (input.command) log.info(` └─ command: ${input.command}`); - if (input.file_path) log.info(` └─ file: ${input.file_path}`); - if (input.content) { - const preview = - input.content.length > 100 - ? `${input.content.substring(0, 100)}...` - : input.content; - log.info(` └─ content: ${preview}`); - } - if (input.query) log.info(` └─ query: ${input.query}`); - if (input.pattern) log.info(` └─ pattern: ${input.pattern}`); - if (input.url) log.info(` └─ url: ${input.url}`); - if (input.edits && Array.isArray(input.edits)) { - log.info(` └─ edits: ${input.edits.length} changes`); - input.edits.forEach((edit: any, index: number) => { - if (edit.file_path) log.info(` ${index + 1}. ${edit.file_path}`); - }); - } - if (input.task) log.info(` └─ task: ${input.task}`); - if (input.bash_command) log.info(` └─ bash_command: ${input.bash_command}`); - } + log.toolCall({ + toolName: content.name, + input: content.input, + }); } } } diff --git a/agents/codex.ts b/agents/codex.ts index eaaa20c..413e56d 100644 --- a/agents/codex.ts +++ b/agents/codex.ts @@ -53,7 +53,7 @@ export const codex = agent({ let finalOutput = ""; for await (const event of streamedTurn.events) { const handler = messageHandlers[event.type]; - console.log(event as never); + log.debug(JSON.stringify(event, null, 2)); if (handler) { handler(event as never); } @@ -116,12 +116,21 @@ const messageHandlers: { "item.started": (event) => { const item = event.item; if (item.type === "command_execution") { - log.info(`→ ${item.command}`); commandExecutionIds.add(item.id); + log.toolCall({ + toolName: item.command, + input: (item as any).args || {}, + }); } else if (item.type === "agent_message") { // Will be handled on completion } else if (item.type === "mcp_tool_call") { - log.info(`→ ${item.tool} (${item.server})`); + log.toolCall({ + toolName: item.tool, + input: { + server: item.server, + ...((item as any).args || {}), + }, + }); } // Reasoning items are handled on completion for better readability }, diff --git a/agents/cursor.ts b/agents/cursor.ts index 158e7d2..0f26913 100644 --- a/agents/cursor.ts +++ b/agents/cursor.ts @@ -2,7 +2,7 @@ import { spawn } from "node:child_process"; import { mkdirSync, writeFileSync } from "node:fs"; import { homedir } from "node:os"; import { join } from "node:path"; -import { formatToolCallLog, log } from "../utils/cli.ts"; +import { log } from "../utils/cli.ts"; import { addInstructions } from "./instructions.ts"; import { agent, type ConfigureMcpServersParams, installFromCurl } from "./shared.ts"; @@ -105,17 +105,15 @@ const messageHandlers = { const builtinToolCall = (event.tool_call as any)?.builtinToolCall; if (mcpToolCall?.args?.toolName && mcpToolCall?.args?.args) { - const formatted = formatToolCallLog({ + log.toolCall({ toolName: mcpToolCall.args.toolName, input: mcpToolCall.args.args, }); - log.info(formatted); } else if (builtinToolCall?.args?.name && builtinToolCall?.args?.args) { - const formatted = formatToolCallLog({ + log.toolCall({ toolName: builtinToolCall.args.name, input: builtinToolCall.args.args, }); - log.info(formatted); } } else if (event.subtype === "completed") { const isError = event.tool_call?.mcpToolCall?.result?.success?.isError; diff --git a/utils/cli.ts b/utils/cli.ts index 5eb39da..072ba71 100644 --- a/utils/cli.ts +++ b/utils/cli.ts @@ -308,10 +308,24 @@ export const log = { */ endGroup, + /** + * Log tool call information to console with formatted output + */ + toolCall: ({ toolName, input }: { toolName: string; input: unknown }): void => { + let output = `→ ${toolName}\n`; + + const inputFormatted = formatJsonValue(input); + if (inputFormatted !== "{}") { + output += formatIndentedField("input", inputFormatted); + } + + log.info(output.trimEnd()); + }, + /** * Log MCP tool call information to mcpLog.txt in the temp directory */ - toolCall: ({ + toolCallToFile: ({ toolName, request, result, @@ -420,30 +434,6 @@ function formatToolCall({ return logEntry; } -/** - * Format a tool call log entry with tool name and input - */ -export function formatToolCallLog({ - toolName, - input, - result: _result, -}: { - toolName: string; - input: unknown; - result?: unknown; -}): string { - let output = `→ ${toolName}\n`; - - const inputFormatted = formatJsonValue(input); - if (inputFormatted !== "{}") { - output += formatIndentedField("input", inputFormatted); - } - - // result parameter added for future use but not implemented yet - - return output.trimEnd(); -} - /** * Finds a CLI executable path by checking if it's installed globally * @param name The name of the CLI executable to find