init claude-code
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 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<string | null> {
|
||||
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]'
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user