/** * Tool Use Summary Generator * * Generates human-readable summaries of completed tool batches using Haiku. * Used by the SDK to provide high-level progress updates to clients. */ import { E_TOOL_USE_SUMMARY_GENERATION_FAILED } from '../../constants/errorIds.js' import { toError } from '../../utils/errors.js' import { logError } from '../../utils/log.js' import { jsonStringify } from '../../utils/slowOperations.js' import { asSystemPrompt } from '../../utils/systemPromptType.js' import { queryHaiku } from '../api/claude.js' const TOOL_USE_SUMMARY_SYSTEM_PROMPT = `Write a short summary label describing what these tool calls accomplished. It appears as a single-line row in a mobile app and truncates around 30 characters, so think git-commit-subject, not sentence. Keep the verb in past tense and the most distinctive noun. Drop articles, connectors, and long location context first. Examples: - Searched in auth/ - Fixed NPE in UserService - Created signup endpoint - Read config.json - Ran failing tests` type ToolInfo = { name: string input: unknown output: unknown } export type GenerateToolUseSummaryParams = { tools: ToolInfo[] signal: AbortSignal isNonInteractiveSession: boolean lastAssistantText?: string } /** * Generates a human-readable summary of completed tools. * * @param params - Parameters including tools executed and their results * @returns A brief summary string, or null if generation fails */ export async function generateToolUseSummary({ tools, signal, isNonInteractiveSession, lastAssistantText, }: GenerateToolUseSummaryParams): Promise { if (tools.length === 0) { return null } try { // Build a concise representation of what tools did const toolSummaries = tools .map(tool => { const inputStr = truncateJson(tool.input, 300) const outputStr = truncateJson(tool.output, 300) return `Tool: ${tool.name}\nInput: ${inputStr}\nOutput: ${outputStr}` }) .join('\n\n') const contextPrefix = lastAssistantText ? `User's intent (from assistant's last message): ${lastAssistantText.slice(0, 200)}\n\n` : '' const response = await queryHaiku({ systemPrompt: asSystemPrompt([TOOL_USE_SUMMARY_SYSTEM_PROMPT]), userPrompt: `${contextPrefix}Tools completed:\n\n${toolSummaries}\n\nLabel:`, signal, options: { querySource: 'tool_use_summary_generation', enablePromptCaching: true, agents: [], isNonInteractiveSession, hasAppendSystemPrompt: false, mcpTools: [], }, }) const summary = response.message.content .filter(block => block.type === 'text') .map(block => (block.type === 'text' ? block.text : '')) .join('') .trim() return summary || null } catch (error) { // Log but don't fail - summaries are non-critical const err = toError(error) err.cause = { errorId: E_TOOL_USE_SUMMARY_GENERATION_FAILED } logError(err) return null } } /** * Truncates a JSON value to a maximum length for the prompt. */ function truncateJson(value: unknown, maxLength: number): string { try { const str = jsonStringify(value) if (str.length <= maxLength) { return str } return str.slice(0, maxLength - 3) + '...' } catch { return '[unable to serialize]' } }