source dump of claude code
at main 112 lines 3.4 kB view raw
1/** 2 * Tool Use Summary Generator 3 * 4 * Generates human-readable summaries of completed tool batches using Haiku. 5 * Used by the SDK to provide high-level progress updates to clients. 6 */ 7 8import { E_TOOL_USE_SUMMARY_GENERATION_FAILED } from '../../constants/errorIds.js' 9import { toError } from '../../utils/errors.js' 10import { logError } from '../../utils/log.js' 11import { jsonStringify } from '../../utils/slowOperations.js' 12import { asSystemPrompt } from '../../utils/systemPromptType.js' 13import { queryHaiku } from '../api/claude.js' 14 15const 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. 16 17Keep the verb in past tense and the most distinctive noun. Drop articles, connectors, and long location context first. 18 19Examples: 20- Searched in auth/ 21- Fixed NPE in UserService 22- Created signup endpoint 23- Read config.json 24- Ran failing tests` 25 26type ToolInfo = { 27 name: string 28 input: unknown 29 output: unknown 30} 31 32export type GenerateToolUseSummaryParams = { 33 tools: ToolInfo[] 34 signal: AbortSignal 35 isNonInteractiveSession: boolean 36 lastAssistantText?: string 37} 38 39/** 40 * Generates a human-readable summary of completed tools. 41 * 42 * @param params - Parameters including tools executed and their results 43 * @returns A brief summary string, or null if generation fails 44 */ 45export async function generateToolUseSummary({ 46 tools, 47 signal, 48 isNonInteractiveSession, 49 lastAssistantText, 50}: GenerateToolUseSummaryParams): Promise<string | null> { 51 if (tools.length === 0) { 52 return null 53 } 54 55 try { 56 // Build a concise representation of what tools did 57 const toolSummaries = tools 58 .map(tool => { 59 const inputStr = truncateJson(tool.input, 300) 60 const outputStr = truncateJson(tool.output, 300) 61 return `Tool: ${tool.name}\nInput: ${inputStr}\nOutput: ${outputStr}` 62 }) 63 .join('\n\n') 64 65 const contextPrefix = lastAssistantText 66 ? `User's intent (from assistant's last message): ${lastAssistantText.slice(0, 200)}\n\n` 67 : '' 68 69 const response = await queryHaiku({ 70 systemPrompt: asSystemPrompt([TOOL_USE_SUMMARY_SYSTEM_PROMPT]), 71 userPrompt: `${contextPrefix}Tools completed:\n\n${toolSummaries}\n\nLabel:`, 72 signal, 73 options: { 74 querySource: 'tool_use_summary_generation', 75 enablePromptCaching: true, 76 agents: [], 77 isNonInteractiveSession, 78 hasAppendSystemPrompt: false, 79 mcpTools: [], 80 }, 81 }) 82 83 const summary = response.message.content 84 .filter(block => block.type === 'text') 85 .map(block => (block.type === 'text' ? block.text : '')) 86 .join('') 87 .trim() 88 89 return summary || null 90 } catch (error) { 91 // Log but don't fail - summaries are non-critical 92 const err = toError(error) 93 err.cause = { errorId: E_TOOL_USE_SUMMARY_GENERATION_FAILED } 94 logError(err) 95 return null 96 } 97} 98 99/** 100 * Truncates a JSON value to a maximum length for the prompt. 101 */ 102function truncateJson(value: unknown, maxLength: number): string { 103 try { 104 const str = jsonStringify(value) 105 if (str.length <= maxLength) { 106 return str 107 } 108 return str.slice(0, maxLength - 3) + '...' 109 } catch { 110 return '[unable to serialize]' 111 } 112}