source dump of claude code
at main 74 lines 2.7 kB view raw
1import { APIUserAbortError } from '@anthropic-ai/sdk' 2import { getEmptyToolPermissionContext } from '../Tool.js' 3import type { Message } from '../types/message.js' 4import { logForDebugging } from '../utils/debug.js' 5import { 6 createUserMessage, 7 getAssistantMessageText, 8} from '../utils/messages.js' 9import { getSmallFastModel } from '../utils/model/model.js' 10import { asSystemPrompt } from '../utils/systemPromptType.js' 11import { queryModelWithoutStreaming } from './api/claude.js' 12import { getSessionMemoryContent } from './SessionMemory/sessionMemoryUtils.js' 13 14// Recap only needs recent context — truncate to avoid "prompt too long" on 15// large sessions. 30 messages ≈ ~15 exchanges, plenty for "where we left off." 16const RECENT_MESSAGE_WINDOW = 30 17 18function buildAwaySummaryPrompt(memory: string | null): string { 19 const memoryBlock = memory 20 ? `Session memory (broader context):\n${memory}\n\n` 21 : '' 22 return `${memoryBlock}The user stepped away and is coming back. Write exactly 1-3 short sentences. Start by stating the high-level task — what they are building or debugging, not implementation details. Next: the concrete next step. Skip status reports and commit recaps.` 23} 24 25/** 26 * Generates a short session recap for the "while you were away" card. 27 * Returns null on abort, empty transcript, or error. 28 */ 29export async function generateAwaySummary( 30 messages: readonly Message[], 31 signal: AbortSignal, 32): Promise<string | null> { 33 if (messages.length === 0) { 34 return null 35 } 36 37 try { 38 const memory = await getSessionMemoryContent() 39 const recent = messages.slice(-RECENT_MESSAGE_WINDOW) 40 recent.push(createUserMessage({ content: buildAwaySummaryPrompt(memory) })) 41 const response = await queryModelWithoutStreaming({ 42 messages: recent, 43 systemPrompt: asSystemPrompt([]), 44 thinkingConfig: { type: 'disabled' }, 45 tools: [], 46 signal, 47 options: { 48 getToolPermissionContext: async () => getEmptyToolPermissionContext(), 49 model: getSmallFastModel(), 50 toolChoice: undefined, 51 isNonInteractiveSession: false, 52 hasAppendSystemPrompt: false, 53 agents: [], 54 querySource: 'away_summary', 55 mcpTools: [], 56 skipCacheWrite: true, 57 }, 58 }) 59 60 if (response.isApiErrorMessage) { 61 logForDebugging( 62 `[awaySummary] API error: ${getAssistantMessageText(response)}`, 63 ) 64 return null 65 } 66 return getAssistantMessageText(response) 67 } catch (err) { 68 if (err instanceof APIUserAbortError || signal.aborted) { 69 return null 70 } 71 logForDebugging(`[awaySummary] generation failed: ${err}`) 72 return null 73 } 74}