asdf
Squash the current repository state back into one baseline commit while preserving the README reframing and repository contents. Constraint: User explicitly requested a single squashed commit with subject "asdf" Confidence: high Scope-risk: broad Reversibility: clean Directive: This commit intentionally rewrites published history; coordinate before future force-pushes Tested: git status clean; local history rewritten to one commit; force-pushed main to origin and instructkr Not-tested: Fresh clone verification after push
This commit is contained in:
commit
d2542c9a62
74
src/services/awaySummary.ts
Normal file
74
src/services/awaySummary.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { APIUserAbortError } from '@anthropic-ai/sdk'
|
||||
import { getEmptyToolPermissionContext } from '../Tool.js'
|
||||
import type { Message } from '../types/message.js'
|
||||
import { logForDebugging } from '../utils/debug.js'
|
||||
import {
|
||||
createUserMessage,
|
||||
getAssistantMessageText,
|
||||
} from '../utils/messages.js'
|
||||
import { getSmallFastModel } from '../utils/model/model.js'
|
||||
import { asSystemPrompt } from '../utils/systemPromptType.js'
|
||||
import { queryModelWithoutStreaming } from './api/claude.js'
|
||||
import { getSessionMemoryContent } from './SessionMemory/sessionMemoryUtils.js'
|
||||
|
||||
// Recap only needs recent context — truncate to avoid "prompt too long" on
|
||||
// large sessions. 30 messages ≈ ~15 exchanges, plenty for "where we left off."
|
||||
const RECENT_MESSAGE_WINDOW = 30
|
||||
|
||||
function buildAwaySummaryPrompt(memory: string | null): string {
|
||||
const memoryBlock = memory
|
||||
? `Session memory (broader context):\n${memory}\n\n`
|
||||
: ''
|
||||
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.`
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a short session recap for the "while you were away" card.
|
||||
* Returns null on abort, empty transcript, or error.
|
||||
*/
|
||||
export async function generateAwaySummary(
|
||||
messages: readonly Message[],
|
||||
signal: AbortSignal,
|
||||
): Promise<string | null> {
|
||||
if (messages.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
const memory = await getSessionMemoryContent()
|
||||
const recent = messages.slice(-RECENT_MESSAGE_WINDOW)
|
||||
recent.push(createUserMessage({ content: buildAwaySummaryPrompt(memory) }))
|
||||
const response = await queryModelWithoutStreaming({
|
||||
messages: recent,
|
||||
systemPrompt: asSystemPrompt([]),
|
||||
thinkingConfig: { type: 'disabled' },
|
||||
tools: [],
|
||||
signal,
|
||||
options: {
|
||||
getToolPermissionContext: async () => getEmptyToolPermissionContext(),
|
||||
model: getSmallFastModel(),
|
||||
toolChoice: undefined,
|
||||
isNonInteractiveSession: false,
|
||||
hasAppendSystemPrompt: false,
|
||||
agents: [],
|
||||
querySource: 'away_summary',
|
||||
mcpTools: [],
|
||||
skipCacheWrite: true,
|
||||
},
|
||||
})
|
||||
|
||||
if (response.isApiErrorMessage) {
|
||||
logForDebugging(
|
||||
`[awaySummary] API error: ${getAssistantMessageText(response)}`,
|
||||
)
|
||||
return null
|
||||
}
|
||||
return getAssistantMessageText(response)
|
||||
} catch (err) {
|
||||
if (err instanceof APIUserAbortError || signal.aborted) {
|
||||
return null
|
||||
}
|
||||
logForDebugging(`[awaySummary] generation failed: ${err}`)
|
||||
return null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user