diff --git a/package.json b/package.json index ca25ed5eb..53745d7ef 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,9 @@ { "name": "claude-code-best", - "version": "1.0.3", + "version": "2026.4.3-restored", + "private": true, "description": "Reverse-engineered Anthropic Claude Code CLI — interactive AI coding assistant in the terminal", + "license": "SEE LICENSE IN LICENSE.md", "type": "module", "author": "claude-code-best ", "repository": { @@ -39,6 +41,7 @@ "scripts": { "build": "bun run build.ts", "dev": "bun run scripts/dev.ts", + "dev-debug": "FEATURE_BUDDY=1 bun run scripts/dev.ts --debug", "dev:inspect": "bun run scripts/dev-debug.ts", "prepublishOnly": "bun run build", "lint": "biome lint src/", diff --git a/src/services/api/claude.ts b/src/services/api/claude.ts index fd4f25110..8cd0cbdb2 100644 --- a/src/services/api/claude.ts +++ b/src/services/api/claude.ts @@ -1784,6 +1784,27 @@ async function* queryModel( const params = paramsFromContext(context) captureAPIRequest(params, options.querySource) // Capture for bug reports + // Log the full API request to debug log file + logForDebugging(`[API_REQUEST] model=${params.model} max_tokens=${params.max_tokens}`) + // Set CLAUDE_CODE_LOG_FULL_PROMPT=1 to log full system prompt and messages + if (isEnvTruthy(process.env.CLAUDE_CODE_LOG_FULL_PROMPT)) { + logForDebugging(`[API_REQUEST_SYSTEM_FULL] ${jsonStringify(params.system)}`) + logForDebugging(`[API_REQUEST_MESSAGES_FULL] ${jsonStringify(params.messages)}`) + } else { + logForDebugging(`[API_REQUEST_SYSTEM] ${jsonStringify(params.system).slice(0, 5000)}...`) + logForDebugging(`[API_REQUEST_MESSAGES] count=${params.messages.length}`) + } + logForDebugging(`[API_REQUEST_TOOLS] count=${params.tools?.length ?? 0}`) + if (params.tools && params.tools.length > 0) { + for (const tool of params.tools) { + if ('name' in tool) { + logForDebugging(`[API_REQUEST_TOOL] name=${tool.name}`) + } else if ('type' in tool) { + logForDebugging(`[API_REQUEST_TOOL] type=${tool.type}`) + } + } + } + maxOutputTokens = params.max_tokens // Fire immediately before the fetch is dispatched. .withResponse() below @@ -1986,12 +2007,14 @@ async function* queryModel( ...part.content_block, input: '', } + logForDebugging(`[TOOL_USE] name=${part.content_block.name} id=${part.content_block.id}`) break case 'server_tool_use': contentBlocks[part.index] = { ...part.content_block, input: '' as unknown as { [key: string]: unknown }, } + logForDebugging(`[MCP_TOOL_USE] name=${part.content_block.name} id=${part.content_block.id}`) if ((part.content_block.name as string) === 'advisor') { isAdvisorInProgress = true logForDebugging(`[AdvisorTool] Advisor tool called`) @@ -2234,6 +2257,11 @@ async function* queryModel( lastMsg.message.stop_reason = stopReason } + // Log the API response summary + logForDebugging(`[API_RESPONSE] stop_reason=${stopReason} usage=${jsonStringify(usage)}`) + logForDebugging(`[API_RESPONSE_MESSAGES] count=${newMessages.length}`) + logForDebugging(`[API_RESPONSE_CONTENT] ${jsonStringify(newMessages)}`) + // Update cost const costUSDForPart = calculateUSDCost(resolvedModel, usage as unknown as BetaUsage) costUSD += addToTotalSessionCost( diff --git a/src/tools/AgentTool/AgentTool.tsx b/src/tools/AgentTool/AgentTool.tsx index 709f31e66..53387f174 100644 --- a/src/tools/AgentTool/AgentTool.tsx +++ b/src/tools/AgentTool/AgentTool.tsx @@ -251,6 +251,19 @@ export const AgentTool = buildTool({ const startTime = Date.now(); const model = isCoordinatorMode() ? undefined : modelParam; + // Log Agent tool invocation details + logForDebugging(`[AGENT_TOOL] Invoking Agent with parameters:`); + logForDebugging(`[AGENT_TOOL] description: ${description}`); + logForDebugging(`[AGENT_TOOL] subagent_type: ${subagent_type ?? '(auto-select)'}`); + logForDebugging(`[AGENT_TOOL] model: ${model ?? '(default)'}`); + logForDebugging(`[AGENT_TOOL] run_in_background: ${run_in_background ?? false}`); + logForDebugging(`[AGENT_TOOL] prompt length: ${prompt.length} chars`); + if (name) logForDebugging(`[AGENT_TOOL] name: ${name}`); + if (team_name) logForDebugging(`[AGENT_TOOL] team_name: ${team_name}`); + if (spawnMode) logForDebugging(`[AGENT_TOOL] mode: ${spawnMode}`); + if (isolation) logForDebugging(`[AGENT_TOOL] isolation: ${isolation}`); + if (cwd) logForDebugging(`[AGENT_TOOL] cwd: ${cwd}`); + // Get app state for permission mode and agent filtering const appState = toolUseContext.getAppState(); const permissionMode = appState.toolPermissionContext.mode; @@ -299,6 +312,12 @@ export const AgentTool = buildTool({ invokingRequestId: assistantMessage?.requestId as string | undefined }, toolUseContext); + // Log teammate spawn + logForDebugging(`[AGENT_TOOL] Teammate spawned: ${name}`); + logForDebugging(`[AGENT_TOOL] team_name: ${teamName}`); + logForDebugging(`[AGENT_TOOL] agent_type: ${subagent_type ?? '(default)'}`); + logForDebugging(`[AGENT_TOOL] model: ${model ?? agentDef?.model ?? '(default)'}`); + // Type assertion uses TeammateSpawnedOutput (defined above) instead of any. // This type is excluded from the exported outputSchema for dead code elimination. // Cast through unknown because TeammateSpawnedOutput is intentionally @@ -355,6 +374,16 @@ export const AgentTool = buildTool({ selectedAgent = found; } + // Log selected agent definition details + logForDebugging(`[AGENT_TOOL] Selected agent: ${selectedAgent.agentType}`); + logForDebugging(`[AGENT_TOOL] source: ${selectedAgent.source}`); + if (selectedAgent.model) logForDebugging(`[AGENT_TOOL] agent model: ${selectedAgent.model}`); + if (selectedAgent.permissionMode) logForDebugging(`[AGENT_TOOL] permissionMode: ${selectedAgent.permissionMode}`); + if (selectedAgent.maxTurns) logForDebugging(`[AGENT_TOOL] maxTurns: ${selectedAgent.maxTurns}`); + if (selectedAgent.background) logForDebugging(`[AGENT_TOOL] background: ${selectedAgent.background}`); + if (selectedAgent.effort !== undefined) logForDebugging(`[AGENT_TOOL] effort: ${selectedAgent.effort}`); + if (selectedAgent.requiredMcpServers?.length) logForDebugging(`[AGENT_TOOL] requiredMcpServers: ${selectedAgent.requiredMcpServers.join(', ')}`); + // Same lifecycle constraint as the run_in_background guard above, but for // agent definitions that force background via `background: true`. Checked // here because selectedAgent is only now resolved. @@ -466,6 +495,12 @@ export const AgentTool = buildTool({ logEvent('tengu_agent_tool_remote_launched', { agent_type: selectedAgent.agentType as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS }); + + // Log remote agent launch + logForDebugging(`[AGENT_TOOL] Remote agent launched: ${selectedAgent.agentType}`); + logForDebugging(`[AGENT_TOOL] taskId: ${taskId}`); + logForDebugging(`[AGENT_TOOL] sessionUrl: ${getRemoteTaskSessionUrl(sessionId)}`); + const remoteResult: RemoteLaunchedOutput = { status: 'remote_launched', taskId, @@ -751,6 +786,12 @@ export const AgentTool = buildTool({ getWorktreeResult: cleanupWorktreeIfNeeded }))); const canReadOutputFile = toolUseContext.options.tools.some(t => toolMatchesName(t, FILE_READ_TOOL_NAME) || toolMatchesName(t, BASH_TOOL_NAME)); + + // Log async agent launch + logForDebugging(`[AGENT_TOOL] Async agent launched: ${selectedAgent.agentType}`); + logForDebugging(`[AGENT_TOOL] agentId: ${agentBackgroundTask.agentId}`); + logForDebugging(`[AGENT_TOOL] outputFile: ${getTaskOutputPath(agentBackgroundTask.agentId)}`); + return { data: { isAsync: true as const, @@ -1233,6 +1274,16 @@ export const AgentTool = buildTool({ logForDebugging(`Sync agent recovering from error with ${agentMessages.length} messages`); } const agentResult = finalizeAgentTool(agentMessages, syncAgentId, metadata); + + // Log Agent completion with usage statistics + const duration = Date.now() - startTime; + logForDebugging(`[AGENT_TOOL] Agent completed: ${selectedAgent.agentType}`); + logForDebugging(`[AGENT_TOOL] agentId: ${syncAgentId}`); + logForDebugging(`[AGENT_TOOL] totalTokens: ${agentResult.totalTokens}`); + logForDebugging(`[AGENT_TOOL] totalToolUseCount: ${agentResult.totalToolUseCount}`); + logForDebugging(`[AGENT_TOOL] duration_ms: ${duration}`); + logForDebugging(`[AGENT_TOOL] content items: ${agentResult.content.length}`); + if (feature('TRANSCRIPT_CLASSIFIER')) { const currentAppState = toolUseContext.getAppState(); const handoffWarning = await classifyHandoffIfNeeded({