@averyyy/pi-agent-core 0.87.1-piclient.1 → 0.87.1-piclient.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,10 @@ export interface CompactionDetails extends Record<string, JsonValue> {
11
11
  readFiles: string[];
12
12
  /** Files modified in the compacted history. */
13
13
  modifiedFiles: string[];
14
+ cachePath: {
15
+ mode: "exact_prefix" | "chunked";
16
+ reason: string;
17
+ };
14
18
  }
15
19
  /** Generated compaction data ready to be persisted as a compaction entry. */
16
20
  export interface CompactResult<T = JsonValue> {
@@ -30,9 +34,10 @@ export interface LegacyCompactResult<T = unknown> extends CompactResult<T> {
30
34
  /** Entry id where retained history starts. */
31
35
  firstKeptEntryId: string;
32
36
  }
33
- export type SummaryRequest = (aiContext: AiContext, options: SimpleStreamOptions, context: Context) => Promise<AssistantMessage>;
34
- export declare function createSummaryRequestOptions(options: SimpleStreamOptions, context: Context): SimpleStreamOptions;
35
- export declare function completeSimpleWithRetries(models: Models, model: Model<Api>, aiContext: AiContext, options: SimpleStreamOptions, retry: RetryPolicy | undefined, callbacks: RetryCallbacks | undefined, context: Context): Promise<AssistantMessage>;
37
+ export type SummaryRequest = (aiContext: AiContext, options: SimpleStreamOptions, context: Context, preservePromptCache?: boolean) => Promise<AssistantMessage>;
38
+ export type CompactionCacheRequestOptions = Pick<SimpleStreamOptions, "cacheRetention" | "sessionId" | "transport" | "thinkingBudgets" | "maxRetryDelayMs" | "timeoutMs">;
39
+ export declare function createSummaryRequestOptions(options: SimpleStreamOptions, context: Context, preservePromptCache?: boolean): SimpleStreamOptions;
40
+ export declare function completeSimpleWithRetries(models: Models, model: Model<Api>, aiContext: AiContext, options: SimpleStreamOptions, retry: RetryPolicy | undefined, callbacks: RetryCallbacks | undefined, context: Context, preservePromptCache?: boolean): Promise<AssistantMessage>;
36
41
  /** Compaction thresholds and retention settings. */
37
42
  export interface CompactionSettings {
38
43
  /** Enable automatic compaction decisions. */
@@ -100,6 +105,8 @@ export declare function generateSummaryWithRequest(currentMessages: AgentMessage
100
105
  }, CompactionError>>;
101
106
  /** Prepared inputs for a compaction run. */
102
107
  export interface CompactionPreparation {
108
+ /** Canonical model-visible session prefix before the current cut point. */
109
+ cachePrefixMessages?: AgentMessage[];
103
110
  /** Messages summarized into the history summary. */
104
111
  messagesToSummarize: AgentMessage[];
105
112
  /** Prefix messages summarized separately when compaction splits a turn. */
@@ -136,9 +143,12 @@ export interface CompactGenerationOptions {
136
143
  model: Model<Api>;
137
144
  customInstructions?: string;
138
145
  thinkingLevel?: ThinkingLevel;
146
+ cacheContext?: AiContext;
147
+ cacheOptions?: CompactionCacheRequestOptions;
148
+ cacheFallbackReason?: string;
139
149
  }
140
150
  /** Generate compaction data through a caller-owned boundary for each provider request. */
141
151
  export declare function compactWithRequest(preparation: CompactionPreparation, options: CompactGenerationOptions, request: SummaryRequest, context: Context): Promise<Result<CompactResult, CompactionError>>;
142
152
  /** Compact a pi-client/pi-server session branch and preserve its retained entry id. */
143
- export declare function compactLegacy(preparation: LegacyCompactionPreparation, models: Models, model: Model<Api>, customInstructions?: string, signal?: AbortSignal, thinkingLevel?: ThinkingLevel, retry?: RetryPolicy, callbacks?: RetryCallbacks): Promise<Result<LegacyCompactResult, CompactionError>>;
153
+ export declare function compactLegacy(preparation: LegacyCompactionPreparation, models: Models, model: Model<Api>, customInstructions?: string, signal?: AbortSignal, thinkingLevel?: ThinkingLevel, retry?: RetryPolicy, callbacks?: RetryCallbacks, cacheContext?: AiContext, cacheOptions?: CompactionCacheRequestOptions, cacheFallbackReason?: string): Promise<Result<LegacyCompactResult, CompactionError>>;
144
154
  //# sourceMappingURL=compaction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/harness/compaction/compaction.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Context as AiContext,\n\ttype Api,\n\ttype AssistantMessage,\n\tcontentText,\n\tgetCurrentSystemMessage,\n\tisContextOverflow,\n\ttype Model,\n\ttype Models,\n\ttype RetryCallbacks,\n\ttype RetryPolicy,\n\tretryAssistantCall,\n\ttype SimpleStreamOptions,\n\ttype SystemMessage,\n\ttype Usage,\n\tuuidv7,\n} from \"@earendil-works/pi-ai\";\nimport type { AgentMessage, ThinkingLevel } from \"../../types.ts\";\nimport { BACKGROUND_CONTEXT, type Context, getTelemetryContext, withAbortSignal } from \"../context.ts\";\nimport {\n\tbuildLegacySessionProjection,\n\ttype LegacyCompactionEntry,\n\ttype LegacyProjectedSessionEntry,\n\tlegacyEntryToContextMessages,\n\ttype SessionTreeEntry,\n} from \"../legacy-session.ts\";\nimport { convertToLlm, createBranchSummaryMessage, createCompactionSummaryMessage } from \"../messages.ts\";\nimport { buildContextEntries, sessionEntryToContextMessages } from \"../session/context.ts\";\nimport type { CompactionEntry, Entry, JsonValue } from \"../session/types.ts\";\nimport { CompactionError, err, ok, type Result } from \"../types.ts\";\nimport { addUsage } from \"../utils/usage.ts\";\nimport {\n\tcomputeFileLists,\n\tcreateFileOps,\n\textractFileOpsFromMessage,\n\ttype FileOperations,\n\tformatFileOperations,\n\tserializeConversation,\n} from \"./utils.ts\";\n\n/** File-operation details stored on generated compaction entries. */\nexport interface CompactionDetails extends Record<string, JsonValue> {\n\t/** Files read in the compacted history. */\n\treadFiles: string[];\n\t/** Files modified in the compacted history. */\n\tmodifiedFiles: string[];\n}\nfunction safeJsonStringify(value: unknown): string {\n\ttry {\n\t\treturn JSON.stringify(value) ?? \"undefined\";\n\t} catch {\n\t\treturn \"[unserializable]\";\n\t}\n}\n\nfunction extractFileOperations(\n\tmessages: AgentMessage[],\n\tentries: Entry[],\n\tprevCompactionIndex: number,\n): FileOperations {\n\tconst fileOps = createFileOps();\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = entries[prevCompactionIndex] as CompactionEntry;\n\t\tif (\n\t\t\ttypeof prevCompaction.details === \"object\" &&\n\t\t\tprevCompaction.details !== null &&\n\t\t\t!Array.isArray(prevCompaction.details)\n\t\t) {\n\t\t\tif (Array.isArray(prevCompaction.details.readFiles)) {\n\t\t\t\tfor (const path of prevCompaction.details.readFiles) {\n\t\t\t\t\tif (typeof path === \"string\") fileOps.read.add(path);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Array.isArray(prevCompaction.details.modifiedFiles)) {\n\t\t\t\tfor (const path of prevCompaction.details.modifiedFiles) {\n\t\t\t\t\tif (typeof path === \"string\") fileOps.edited.add(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (const msg of messages) {\n\t\textractFileOpsFromMessage(msg, fileOps);\n\t}\n\n\treturn fileOps;\n}\nfunction getMessageFromEntry(entry: Entry): AgentMessage | undefined {\n\tif (entry.type === \"message\") {\n\t\treturn entry.message as AgentMessage;\n\t}\n\tif (entry.type === \"branch_summary\") {\n\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\t}\n\tif (entry.type === \"compaction\") {\n\t\treturn createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp);\n\t}\n\treturn undefined;\n}\n\nfunction getMessageFromEntryForCompaction(entry: Entry): AgentMessage | undefined {\n\tif (entry.type === \"compaction\") {\n\t\treturn undefined;\n\t}\n\treturn getMessageFromEntry(entry);\n}\n\nfunction extractLegacyFileOperations(\n\tmessages: AgentMessage[],\n\tentries: SessionTreeEntry[],\n\tprevCompactionIndex: number,\n): FileOperations {\n\tconst fileOps = createFileOps();\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = entries[prevCompactionIndex] as LegacyCompactionEntry;\n\t\tif (!prevCompaction.fromHook && prevCompaction.details) {\n\t\t\tconst details = prevCompaction.details as CompactionDetails;\n\t\t\tif (Array.isArray(details.readFiles)) {\n\t\t\t\tfor (const file of details.readFiles) fileOps.read.add(file);\n\t\t\t}\n\t\t\tif (Array.isArray(details.modifiedFiles)) {\n\t\t\t\tfor (const file of details.modifiedFiles) fileOps.edited.add(file);\n\t\t\t}\n\t\t}\n\t}\n\tfor (const message of messages) extractFileOpsFromMessage(message, fileOps);\n\treturn fileOps;\n}\n\n/** Generated compaction data ready to be persisted as a compaction entry. */\nexport interface CompactResult<T = JsonValue> {\n\t/** Summary text that replaces compacted history in future context. */\n\tsummary: string;\n\t/** Estimated context tokens before compaction. */\n\ttokensBefore: number;\n\t/** Usage from the LLM call(s) that generated this summary, if available. */\n\tusage?: Usage;\n\t/** Retained recent messages stored directly on the compaction entry. */\n\tretainedTail: AgentMessage[];\n\t/** Optional implementation-specific details stored with the compaction entry. */\n\tdetails?: T;\n}\n\n/** Compaction result used by the pi-client/pi-server session-tree protocol. */\nexport interface LegacyCompactResult<T = unknown> extends CompactResult<T> {\n\t/** Entry id where retained history starts. */\n\tfirstKeptEntryId: string;\n}\n\nexport type SummaryRequest = (\n\taiContext: AiContext,\n\toptions: SimpleStreamOptions,\n\tcontext: Context,\n) => Promise<AssistantMessage>;\n\nexport function createSummaryRequestOptions(options: SimpleStreamOptions, context: Context): SimpleStreamOptions {\n\treturn {\n\t\t...options,\n\t\tsignal: context.abortSignal,\n\t\ttelemetryContext: getTelemetryContext(context),\n\t\tcacheRetention: \"none\",\n\t\tsessionId: options.sessionId ?? uuidv7(),\n\t};\n}\n\nexport async function completeSimpleWithRetries(\n\tmodels: Models,\n\tmodel: Model<Api>,\n\taiContext: AiContext,\n\toptions: SimpleStreamOptions,\n\tretry: RetryPolicy | undefined,\n\tcallbacks: RetryCallbacks | undefined,\n\tcontext: Context,\n): Promise<AssistantMessage> {\n\t// Summaries are standalone requests, so isolate routing and avoid cache writes that cannot be reused.\n\tconst requestOptions = createSummaryRequestOptions(options, context);\n\treturn retryAssistantCall(\n\t\t() => models.completeSimple(model, aiContext, requestOptions),\n\t\tretry,\n\t\trequestOptions.signal,\n\t\tcallbacks,\n\t);\n}\n\n/** Compaction thresholds and retention settings. */\nexport interface CompactionSettings {\n\t/** Enable automatic compaction decisions. */\n\tenabled: boolean;\n\t/** Tokens reserved for summary prompt and output. */\n\treserveTokens: number;\n\t/** Approximate recent-context tokens to keep after compaction. */\n\tkeepRecentTokens: number;\n}\n\n/** Default compaction settings used by the harness. */\nexport const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tkeepRecentTokens: 20000,\n};\n\n/** Calculate total context tokens from provider usage. */\nexport function calculateContextTokens(usage: Usage): number {\n\treturn usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;\n}\nfunction getAssistantUsage(msg: AgentMessage): Usage | undefined {\n\tif (msg.role === \"assistant\" && \"usage\" in msg) {\n\t\tconst assistantMsg = msg as AssistantMessage;\n\t\tif (\n\t\t\tassistantMsg.stopReason !== \"aborted\" &&\n\t\t\tassistantMsg.stopReason !== \"error\" &&\n\t\t\tassistantMsg.usage &&\n\t\t\tcalculateContextTokens(assistantMsg.usage) > 0\n\t\t) {\n\t\t\treturn assistantMsg.usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Return usage from the last valid assistant message in session entries. */\nexport function getLastAssistantUsage(entries: Entry[]): Usage | undefined {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"message\") {\n\t\t\tconst usage = getAssistantUsage(entry.message as AgentMessage);\n\t\t\tif (usage) return usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Estimated context-token usage for a message list. */\nexport interface ContextUsageEstimate {\n\t/** Estimated total context tokens. */\n\ttokens: number;\n\t/** Tokens reported by the most recent assistant usage block. */\n\tusageTokens: number;\n\t/** Estimated tokens after the most recent assistant usage block. */\n\ttrailingTokens: number;\n\t/** Index of the message that provided usage, or null when none exists. */\n\tlastUsageIndex: number | null;\n}\n\nfunction getLastAssistantUsageInfo(messages: AgentMessage[]): { usage: Usage; index: number } | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst usage = getAssistantUsage(messages[i]);\n\t\tif (usage) return { usage, index: i };\n\t}\n\treturn undefined;\n}\n\n/** Estimate context tokens for messages using provider usage when available. */\nexport function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\n\tif (!usageInfo) {\n\t\tlet estimated = 0;\n\t\tfor (const message of messages) {\n\t\t\testimated += estimateTokens(message);\n\t\t}\n\t\treturn {\n\t\t\ttokens: estimated,\n\t\t\tusageTokens: 0,\n\t\t\ttrailingTokens: estimated,\n\t\t\tlastUsageIndex: null,\n\t\t};\n\t}\n\n\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\tlet trailingTokens = 0;\n\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\ttrailingTokens += estimateTokens(messages[i]);\n\t}\n\n\treturn {\n\t\ttokens: usageTokens + trailingTokens,\n\t\tusageTokens,\n\t\ttrailingTokens,\n\t\tlastUsageIndex: usageInfo.index,\n\t};\n}\n\n/** Return whether context usage exceeds the configured compaction threshold. */\nexport function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {\n\tif (!settings.enabled) return false;\n\treturn contextTokens > contextWindow - settings.reserveTokens;\n}\n\nconst ESTIMATED_IMAGE_CHARS = 4800;\n\nfunction estimateTextAndImageContentChars(content: string | Array<{ type: string; text?: string }>): number {\n\tif (typeof content === \"string\") {\n\t\treturn content.length;\n\t}\n\n\tlet chars = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"text\" && block.text) {\n\t\t\tchars += block.text.length;\n\t\t} else if (block.type === \"image\") {\n\t\t\tchars += ESTIMATED_IMAGE_CHARS;\n\t\t}\n\t}\n\treturn chars;\n}\n\n/** Estimate token count for one message using a conservative character heuristic. */\nexport function estimateTokens(message: AgentMessage): number {\n\tlet chars = 0;\n\n\tswitch (message.role) {\n\t\tcase \"system\": {\n\t\t\tconst system = message as SystemMessage;\n\t\t\tchars = estimateTextAndImageContentChars(system.content);\n\t\t\tif (system.sections) {\n\t\t\t\tfor (const section of Object.values(system.sections)) {\n\t\t\t\t\tif (section) chars += section.length;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (system.toolsAdded) chars += safeJsonStringify(system.toolsAdded).length;\n\t\t\tif (system.toolsRemoved) chars += safeJsonStringify(system.toolsRemoved).length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"user\": {\n\t\t\tchars = estimateTextAndImageContentChars(\n\t\t\t\t(message as { content: string | Array<{ type: string; text?: string }> }).content,\n\t\t\t);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"assistant\": {\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\tfor (const block of assistant.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tchars += block.text.length;\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tchars += block.thinking.length;\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tchars += block.name.length + safeJsonStringify(block.arguments).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"custom\":\n\t\tcase \"toolResult\": {\n\t\t\tchars = estimateTextAndImageContentChars(message.content);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"bashExecution\": {\n\t\t\tchars = message.command.length + message.output.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\": {\n\t\t\tchars = message.summary.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t}\n\n\treturn 0;\n}\nfunction findValidCutPoints(entries: Entry[], startIndex: number, endIndex: number): number[] {\n\tconst cutPoints: number[] = [];\n\tfor (let i = startIndex; i < endIndex; i++) {\n\t\tconst entry = entries[i];\n\t\tswitch (entry.type) {\n\t\t\tcase \"message\": {\n\t\t\t\tconst role = entry.message.role;\n\t\t\t\tswitch (role) {\n\t\t\t\t\tcase \"bashExecution\":\n\t\t\t\t\tcase \"custom\":\n\t\t\t\t\tcase \"branchSummary\":\n\t\t\t\t\tcase \"compactionSummary\":\n\t\t\t\t\tcase \"user\":\n\t\t\t\t\tcase \"assistant\":\n\t\t\t\t\t\tcutPoints.push(i);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"toolResult\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"compaction\":\n\t\t\tcase \"branch_summary\":\n\t\t\tcase \"custom\":\n\t\t\t\tbreak;\n\t\t}\n\t\tif (entry.type === \"branch_summary\") cutPoints.push(i);\n\t}\n\treturn cutPoints;\n}\n\n/** Find the user-visible message that starts the turn containing an entry. */\nexport function findTurnStartIndex(entries: Entry[], entryIndex: number, startIndex: number): number {\n\tfor (let i = entryIndex; i >= startIndex; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"branch_summary\") {\n\t\t\treturn i;\n\t\t}\n\t\tif (entry.type === \"message\") {\n\t\t\tconst role = entry.message.role;\n\t\t\tif (role === \"user\" || role === \"bashExecution\") {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t}\n\treturn -1;\n}\n\n/** Cut point selected for compaction. */\nexport interface CutPointResult {\n\t/** Index of the first entry retained after compaction. */\n\tfirstKeptEntryIndex: number;\n\t/** Index of the turn-start entry when the cut splits a turn, otherwise -1. */\n\tturnStartIndex: number;\n\t/** Whether the selected cut point splits an in-progress turn. */\n\tisSplitTurn: boolean;\n}\n\n/** Find the compaction cut point that keeps approximately the requested recent-token budget. */\nexport function findCutPoint(\n\tentries: Entry[],\n\tstartIndex: number,\n\tendIndex: number,\n\tkeepRecentTokens: number,\n): CutPointResult {\n\tconst cutPoints = findValidCutPoints(entries, startIndex, endIndex);\n\n\tif (cutPoints.length === 0) {\n\t\treturn { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };\n\t}\n\tlet accumulatedTokens = 0;\n\tlet cutIndex = cutPoints[0];\n\n\tfor (let i = endIndex - 1; i >= startIndex; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type !== \"message\") continue;\n\t\tconst messageTokens = estimateTokens(entry.message as AgentMessage);\n\t\taccumulatedTokens += messageTokens;\n\t\tif (accumulatedTokens >= keepRecentTokens) {\n\t\t\tfor (let c = 0; c < cutPoints.length; c++) {\n\t\t\t\tif (cutPoints[c] >= i) {\n\t\t\t\t\tcutIndex = cutPoints[c];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\twhile (cutIndex > startIndex) {\n\t\tconst prevEntry = entries[cutIndex - 1];\n\t\tif (prevEntry.type === \"compaction\") {\n\t\t\tbreak;\n\t\t}\n\t\tif (prevEntry.type === \"message\") {\n\t\t\tbreak;\n\t\t}\n\t\tcutIndex--;\n\t}\n\tconst cutEntry = entries[cutIndex];\n\tconst isUserMessage = cutEntry.type === \"message\" && cutEntry.message.role === \"user\";\n\tconst turnStartIndex = isUserMessage ? -1 : findTurnStartIndex(entries, cutIndex, startIndex);\n\n\treturn {\n\t\tfirstKeptEntryIndex: cutIndex,\n\t\tturnStartIndex,\n\t\tisSplitTurn: !isUserMessage && turnStartIndex !== -1,\n\t};\n}\n\nfunction isLegacyProjectionCutPointMessage(message: AgentMessage): boolean {\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"assistant\":\n\t\tcase \"bashExecution\":\n\t\tcase \"custom\":\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn true;\n\t\tcase \"toolResult\":\n\t\tcase \"system\":\n\t\t\treturn false;\n\t}\n}\n\nfunction isLegacyProjectionTurnStartMessage(message: AgentMessage): boolean {\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"bashExecution\":\n\t\tcase \"custom\":\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn true;\n\t\tcase \"assistant\":\n\t\tcase \"toolResult\":\n\t\tcase \"system\":\n\t\t\treturn false;\n\t}\n}\n\nfunction findLegacyProjectedValidCutPoints(\n\tentries: LegacyProjectedSessionEntry[],\n\tstartIndex: number,\n\tendIndex: number,\n): number[] {\n\tconst cutPoints: number[] = [];\n\tfor (let index = startIndex; index < endIndex; index++) {\n\t\tconst entry = entries[index];\n\t\tif (entry.sourceEntry.type !== \"compaction\" && entry.messages.some(isLegacyProjectionCutPointMessage)) {\n\t\t\tcutPoints.push(index);\n\t\t}\n\t}\n\treturn cutPoints;\n}\n\nfunction findLegacyProjectedTurnStartIndex(\n\tentries: LegacyProjectedSessionEntry[],\n\tentryIndex: number,\n\tstartIndex: number,\n): number {\n\tfor (let index = entryIndex; index >= startIndex; index--) {\n\t\tif (entries[index].messages.some(isLegacyProjectionTurnStartMessage)) return index;\n\t}\n\treturn -1;\n}\n\nfunction findLegacyProjectedCutPoint(\n\tentries: LegacyProjectedSessionEntry[],\n\tstartIndex: number,\n\tendIndex: number,\n\tkeepRecentTokens: number,\n): CutPointResult {\n\tconst cutPoints = findLegacyProjectedValidCutPoints(entries, startIndex, endIndex);\n\tif (cutPoints.length === 0) {\n\t\treturn { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };\n\t}\n\n\tlet accumulatedTokens = 0;\n\tlet exceededBudget = false;\n\tlet cutIndex = cutPoints[0];\n\tfor (let index = endIndex - 1; index >= startIndex; index--) {\n\t\tconst messageTokens = entries[index].messages.reduce((sum, message) => sum + estimateTokens(message), 0);\n\t\tif (messageTokens === 0) continue;\n\t\taccumulatedTokens += messageTokens;\n\t\tif (accumulatedTokens >= keepRecentTokens) {\n\t\t\texceededBudget = true;\n\t\t\tcutIndex = cutPoints.find((candidate) => candidate >= index) ?? cutPoints[cutPoints.length - 1];\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// A completed recovery attempt and its omission edits are context-invisible after\n\t// the last visible input. Advance past that closed suffix without skipping a\n\t// replacement edit for a visible input.\n\tconst suffix = entries.slice(cutIndex + 1, endIndex);\n\tconst isIntrinsicallyVisible = (entry: LegacyProjectedSessionEntry): boolean =>\n\t\tentry.sourceEntry.type !== \"context_edit\" && legacyEntryToContextMessages(entry.sourceEntry).length > 0;\n\tconst isOmitted = (entry: LegacyProjectedSessionEntry): boolean =>\n\t\tisIntrinsicallyVisible(entry) && entry.messages.length === 0;\n\tconst omittedSuffixIds = new Set(suffix.filter(isOmitted).map((entry) => entry.sourceEntry.id));\n\tconst hasExternalReplacement = suffix.some(\n\t\t(entry) =>\n\t\t\tentry.sourceEntry.type === \"context_edit\" &&\n\t\t\tentry.sourceEntry.replacement !== null &&\n\t\t\t!omittedSuffixIds.has(entry.sourceEntry.targetId),\n\t);\n\tconst isRecoveryOmissionSuffix =\n\t\texceededBudget &&\n\t\t!hasExternalReplacement &&\n\t\tsuffix.some(\n\t\t\t(entry) =>\n\t\t\t\tentry.sourceEntry.type === \"message\" && entry.sourceEntry.message.role === \"assistant\" && isOmitted(entry),\n\t\t) &&\n\t\tsuffix.every(\n\t\t\t(entry) => entry.sourceEntry.type !== \"compaction\" && (!isIntrinsicallyVisible(entry) || isOmitted(entry)),\n\t\t);\n\tif (isRecoveryOmissionSuffix) cutIndex++;\n\n\twhile (cutIndex > startIndex) {\n\t\tconst previousEntry = entries[cutIndex - 1];\n\t\tif (previousEntry.sourceEntry.type === \"compaction\" || previousEntry.messages.length > 0) break;\n\t\tcutIndex--;\n\t}\n\tconst startsTurn = entries[cutIndex].messages.some(isLegacyProjectionTurnStartMessage);\n\tconst turnStartIndex = startsTurn ? -1 : findLegacyProjectedTurnStartIndex(entries, cutIndex, startIndex);\n\treturn {\n\t\tfirstKeptEntryIndex: cutIndex,\n\t\tturnStartIndex,\n\t\tisSplitTurn: !startsTurn && turnStartIndex !== -1,\n\t};\n}\n\nexport const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;\n\nconst SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.\n\nUse this EXACT format:\n\n## Goal\n[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]\n\n## Constraints & Preferences\n- [Any constraints, preferences, or requirements mentioned by user]\n- [Or \"(none)\" if none were mentioned]\n\n## Progress\n### Done\n- [x] [Completed tasks/changes]\n\n### In Progress\n- [ ] [Current work]\n\n### Blocked\n- [Issues preventing progress, if any]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale]\n\n## Operational State\n- Modified files: [Exact paths, or \"(none)\"]\n- Read files: [Exact paths, or \"(none)\"]\n- Open failures: [Current unresolved failures/errors, or \"(none)\"]\n- Last command: [Most recent test/build/shell command and exit code, or \"(none)\"]\n- Last failing assertion/error: [Exact assertion, stack frame, or failing lines if available, or \"(none)\"]\n- Pending TODO: [Concrete remaining work, or \"(none)\"]\n\n## Next Steps\n1. [Ordered list of what should happen next]\n\n## Critical Context\n- [Any data, examples, or references needed to continue]\n- [Or \"(none)\" if not applicable]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\nconst UPDATE_SUMMARIZATION_PROMPT = `The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.\n\nUpdate the existing structured summary with new information. RULES:\n- PRESERVE all existing information from the previous summary\n- ADD new progress, decisions, and context from the new messages\n- UPDATE the Progress section: move items from \"In Progress\" to \"Done\" when completed\n- UPDATE \"Next Steps\" based on what was accomplished\n- PRESERVE exact file paths, function names, and error messages\n- If something is no longer relevant, you may remove it\n\nUse this EXACT format:\n\n## Goal\n[Preserve existing goals, add new ones if the task expanded]\n\n## Constraints & Preferences\n- [Preserve existing, add new ones discovered]\n\n## Progress\n### Done\n- [x] [Include previously done items AND newly completed items]\n\n### In Progress\n- [ ] [Current work - update based on progress]\n\n### Blocked\n- [Current blockers - remove if resolved]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale] (preserve all previous, add new)\n\n## Operational State\n- Modified files: [Preserve/update exact paths, or \"(none)\"]\n- Read files: [Preserve/update exact paths, or \"(none)\"]\n- Open failures: [Current unresolved failures/errors, or \"(none)\"]\n- Last command: [Most recent test/build/shell command and exit code, or \"(none)\"]\n- Last failing assertion/error: [Exact assertion, stack frame, or failing lines if available, or \"(none)\"]\n- Pending TODO: [Concrete remaining work, or \"(none)\"]\n\n## Next Steps\n1. [Update based on current state]\n\n## Critical Context\n- [Preserve important context, add new if needed]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\nfunction getSummaryMaxTokens(model: Model<any>, reserveTokens: number): number {\n\treturn Math.min(Math.floor(0.8 * reserveTokens), model.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY);\n}\n\nfunction estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction buildSummaryPrompt(conversationText: string, basePrompt: string, previousSummary: string | undefined): string {\n\tlet promptText = `<conversation>\\n${conversationText}\\n</conversation>\\n\\n`;\n\tif (previousSummary) {\n\t\tpromptText += `<previous-summary>\\n${previousSummary}\\n</previous-summary>\\n\\n`;\n\t}\n\treturn promptText + basePrompt;\n}\n\nfunction getSummaryInputBudget(\n\tmodel: Model<any>,\n\tmaxTokens: number,\n\tbasePrompt: string,\n\tpreviousSummary: string | undefined,\n): number {\n\tif (model.contextWindow <= 0) return Number.POSITIVE_INFINITY;\n\tconst overheadTokens = estimateTextTokens(buildSummaryPrompt(\"\", basePrompt, previousSummary));\n\treturn Math.max(1, Math.floor(model.contextWindow - maxTokens - overheadTokens));\n}\n\nfunction toSummarySegments(messages: AgentMessage[]): string[] {\n\treturn messages\n\t\t.map((message) => serializeConversation(convertToLlm([message])))\n\t\t.filter((segment) => segment.length > 0);\n}\n\nfunction takeSummaryChunk(segments: string[], tokenBudget: number): { chunk: string; remaining: string[] } {\n\tif (!Number.isFinite(tokenBudget)) return { chunk: segments.join(\"\\n\\n\"), remaining: [] };\n\n\tconst chunk: string[] = [];\n\tlet chunkTokens = 0;\n\n\tfor (let i = 0; i < segments.length; i++) {\n\t\tconst segment = segments[i];\n\t\tconst messageTokens = Math.max(1, estimateTextTokens(segment));\n\t\tif (chunk.length === 0 && messageTokens > tokenBudget) {\n\t\t\tconst chunkChars = Math.max(1, Math.floor(tokenBudget * 4));\n\t\t\tconst remainingSegment = segment.slice(chunkChars);\n\t\t\tconst remaining = remainingSegment ? [remainingSegment, ...segments.slice(i + 1)] : segments.slice(i + 1);\n\t\t\treturn { chunk: segment.slice(0, chunkChars), remaining };\n\t\t}\n\t\tif (chunk.length > 0 && chunkTokens + messageTokens > tokenBudget) {\n\t\t\treturn { chunk: chunk.join(\"\\n\\n\"), remaining: segments.slice(i) };\n\t\t}\n\t\tchunk.push(segment);\n\t\tchunkTokens += messageTokens;\n\t}\n\n\treturn { chunk: chunk.join(\"\\n\\n\"), remaining: [] };\n}\n\nasync function summarizeChunk(\n\tconversationText: string,\n\tmodel: Model<Api>,\n\tmaxTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tinitialPrompt: string,\n\tupdatePrompt: string,\n\tpreviousSummary: string | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst basePrompt = previousSummary ? updatePrompt : initialPrompt;\n\tconst promptText = buildSummaryPrompt(conversationText, basePrompt, previousSummary);\n\tconst summarizationMessages = [\n\t\t{\n\t\t\trole: \"user\" as const,\n\t\t\tcontent: [{ type: \"text\" as const, text: promptText }],\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t];\n\n\tconst completionOptions =\n\t\tmodel.reasoning && thinkingLevel && thinkingLevel !== \"off\"\n\t\t\t? { maxTokens, reasoning: thinkingLevel }\n\t\t\t: { maxTokens };\n\n\tconst response = await request(\n\t\t{ systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: summarizationMessages },\n\t\tcreateSummaryRequestOptions(completionOptions, context),\n\t\tcontext,\n\t);\n\n\tif (isContextOverflow(response, model.contextWindow) && conversationText.length > 1) {\n\t\tconst middle = Math.ceil(conversationText.length / 2);\n\t\tconst leftSummary = await summarizeChunk(\n\t\t\tconversationText.slice(0, middle),\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tpreviousSummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!leftSummary.ok) return leftSummary;\n\t\tconst rightSummary = await summarizeChunk(\n\t\t\tconversationText.slice(middle),\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tleftSummary.value.text,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!rightSummary.ok) return rightSummary;\n\t\treturn ok({\n\t\t\ttext: rightSummary.value.text,\n\t\t\tusage: addUsage(leftSummary.value.usage, rightSummary.value.usage),\n\t\t});\n\t}\n\tif (response.stopReason === \"aborted\") {\n\t\treturn err(new CompactionError(\"aborted\", response.errorMessage || \"Summarization aborted\"));\n\t}\n\tif (response.stopReason === \"error\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Summarization failed: ${response.errorMessage || \"Unknown error\"}`,\n\t\t\t),\n\t\t);\n\t}\n\tif (response.stopReason === \"length\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t\"Summarization failed: generation hit the token cap and the summary is incomplete\",\n\t\t\t),\n\t\t);\n\t}\n\tif (response.content.some((block) => block.type === \"toolCall\")) {\n\t\treturn err(new CompactionError(\"summarization_failed\", \"Summarization attempted to call a tool\"));\n\t}\n\n\treturn ok({ text: contentText(response.content), usage: response.usage });\n}\n\nasync function summarizeMessages(\n\tmessages: AgentMessage[],\n\tmodel: Model<Api>,\n\tmaxTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tinitialPrompt: string,\n\tupdatePrompt: string,\n\tpreviousSummary: string | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tlet remaining = toSummarySegments(messages);\n\tif (remaining.length === 0) {\n\t\treturn summarizeChunk(\n\t\t\t\"\",\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tpreviousSummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t}\n\tlet summary = previousSummary;\n\tlet summaryUsage: Usage | undefined;\n\twhile (remaining.length > 0) {\n\t\tconst basePrompt = summary ? updatePrompt : initialPrompt;\n\t\tconst next = takeSummaryChunk(remaining, getSummaryInputBudget(model, maxTokens, basePrompt, summary));\n\t\tconst chunkSummary = await summarizeChunk(\n\t\t\tnext.chunk,\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tsummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!chunkSummary.ok) return chunkSummary;\n\t\tsummary = chunkSummary.value.text;\n\t\tsummaryUsage = summaryUsage ? addUsage(summaryUsage, chunkSummary.value.usage) : chunkSummary.value.usage;\n\t\tremaining = next.remaining;\n\t}\n\tif (!summaryUsage) {\n\t\treturn err(new CompactionError(\"summarization_failed\", \"Summarization returned no usage data\"));\n\t}\n\treturn ok({ text: summary ?? \"\", usage: summaryUsage });\n}\n\n/** Generate or update a conversation summary for compaction. */\nexport async function generateSummary(\n\tcurrentMessages: AgentMessage[],\n\tmodels: Models,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions?: string,\n\tpreviousSummary?: string,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcontext: Context = BACKGROUND_CONTEXT,\n): Promise<Result<string, CompactionError>> {\n\tconst result = await generateSummaryWithUsage(\n\t\tcurrentMessages,\n\t\tmodels,\n\t\tmodel,\n\t\treserveTokens,\n\t\tcustomInstructions,\n\t\tpreviousSummary,\n\t\tthinkingLevel,\n\t\tretry,\n\t\tcallbacks,\n\t\tcontext,\n\t);\n\treturn result.ok ? ok(result.value.text) : err(result.error);\n}\n\n/** Generate or update a conversation summary and return its provider usage. */\nexport function generateSummaryWithUsage(\n\tcurrentMessages: AgentMessage[],\n\tmodels: Models,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions?: string,\n\tpreviousSummary?: string,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcontext: Context = BACKGROUND_CONTEXT,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tlet updatePrompt = UPDATE_SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t\tupdatePrompt = `${updatePrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\tconst request: SummaryRequest = (aiContext, options, requestContext) =>\n\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext);\n\treturn summarizeMessages(\n\t\tcurrentMessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tinitialPrompt,\n\t\tupdatePrompt,\n\t\tpreviousSummary,\n\t\trequest,\n\t\tcontext,\n\t);\n}\n\nexport interface SummaryGenerationOptions {\n\tmodel: Model<Api>;\n\treserveTokens: number;\n\tcustomInstructions?: string;\n\tpreviousSummary?: string;\n\tthinkingLevel?: ThinkingLevel;\n}\n\n/** Generate one summary through a caller-owned one-request boundary. */\nexport function generateSummaryWithRequest(\n\tcurrentMessages: AgentMessage[],\n\toptions: SummaryGenerationOptions,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst { model, reserveTokens, customInstructions, previousSummary, thinkingLevel } = options;\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tlet updatePrompt = UPDATE_SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t\tupdatePrompt = `${updatePrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\treturn summarizeMessages(\n\t\tcurrentMessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tinitialPrompt,\n\t\tupdatePrompt,\n\t\tpreviousSummary,\n\t\trequest,\n\t\tcontext,\n\t);\n}\n\n/** Prepared inputs for a compaction run. */\nexport interface CompactionPreparation {\n\t/** Messages summarized into the history summary. */\n\tmessagesToSummarize: AgentMessage[];\n\t/** Prefix messages summarized separately when compaction splits a turn. */\n\tturnPrefixMessages: AgentMessage[];\n\t/** Recent messages retained after compaction and stored on the compaction entry. */\n\tretainedTail: AgentMessage[];\n\t/** Whether compaction splits a turn. */\n\tisSplitTurn: boolean;\n\t/** Estimated context tokens before compaction. */\n\ttokensBefore: number;\n\t/** Previous compaction summary used for iterative updates. */\n\tpreviousSummary?: string;\n\t/** File operations extracted from summarized history. */\n\tfileOps: FileOperations;\n\t/** Settings used to prepare compaction. */\n\tsettings: CompactionSettings;\n}\n\n/** Prepare session entries for compaction, or return undefined when compaction is not applicable. */\nexport function prepareCompaction(\n\tpathEntries: Entry[],\n\tsettings: CompactionSettings,\n): Result<CompactionPreparation | undefined, CompactionError> {\n\tif (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === \"compaction\") {\n\t\treturn ok(undefined);\n\t}\n\n\tlet prevCompactionIndex = -1;\n\tfor (let i = pathEntries.length - 1; i >= 0; i--) {\n\t\tif (pathEntries[i].type === \"compaction\") {\n\t\t\tprevCompactionIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet previousSummary: string | undefined;\n\tlet compactableEntries = pathEntries;\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = pathEntries[prevCompactionIndex] as CompactionEntry;\n\t\tpreviousSummary = prevCompaction.summary;\n\t\tconst virtualRetainedEntries: Entry[] = prevCompaction.retainedTail.map((message, index) => ({\n\t\t\ttype: \"message\",\n\t\t\tid: `${prevCompaction.id}:retained:${index}`,\n\t\t\tparentId: index === 0 ? prevCompaction.id : `${prevCompaction.id}:retained:${index - 1}`,\n\t\t\tseq: prevCompaction.seq,\n\t\t\ttimestamp: message.timestamp,\n\t\t\tmessage,\n\t\t}));\n\t\tcompactableEntries = [...virtualRetainedEntries, ...pathEntries.slice(prevCompactionIndex + 1)];\n\t}\n\tconst boundaryEnd = compactableEntries.length;\n\n\tconst tokensBefore = estimateContextTokens(\n\t\tbuildContextEntries(pathEntries).flatMap(sessionEntryToContextMessages),\n\t).tokens;\n\tconst cutPoint = findCutPoint(compactableEntries, 0, boundaryEnd, settings.keepRecentTokens);\n\tconst historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;\n\tconst messagesToSummarize: AgentMessage[] = [];\n\tfor (let i = 0; i < historyEnd; i++) {\n\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\tif (msg) messagesToSummarize.push(msg);\n\t}\n\tconst turnPrefixMessages: AgentMessage[] = [];\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (let i = cutPoint.turnStartIndex; i < cutPoint.firstKeptEntryIndex; i++) {\n\t\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\t\tif (msg) turnPrefixMessages.push(msg);\n\t\t}\n\t}\n\tconst retainedTail: AgentMessage[] = [];\n\tfor (let i = cutPoint.firstKeptEntryIndex; i < boundaryEnd; i++) {\n\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\tif (msg) retainedTail.push(msg);\n\t}\n\tconst fileOps = extractFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (const msg of turnPrefixMessages) {\n\t\t\textractFileOpsFromMessage(msg, fileOps);\n\t\t}\n\t}\n\n\treturn ok({\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn: cutPoint.isSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t});\n}\n\n/** Optional cut-point override for the pi-client/pi-server legacy session tree. */\nexport interface CompactionPreparationOptions {\n\tfirstKeptEntryId?: string;\n}\n\n/** Prepared compaction inputs with the retained entry id required by the pi-server protocol. */\nexport interface LegacyCompactionPreparation extends CompactionPreparation {\n\tfirstKeptEntryId: string;\n}\n\nfunction estimateLegacyProjectedContextTokens(\n\tprojection: ReturnType<typeof buildLegacySessionProjection>,\n\tpathEntries: SessionTreeEntry[],\n): ContextUsageEstimate {\n\tconst estimate = estimateContextTokens(projection.messages);\n\tif (estimate.lastUsageIndex !== null) {\n\t\tlet projectedMessageIndex = 0;\n\t\tlet usageEntryId: string | undefined;\n\t\tfor (const entry of projection.entries) {\n\t\t\tconst nextMessageIndex = projectedMessageIndex + entry.messages.length;\n\t\t\tif (estimate.lastUsageIndex < nextMessageIndex) {\n\t\t\t\tusageEntryId = entry.sourceEntry.id;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprojectedMessageIndex = nextMessageIndex;\n\t\t}\n\n\t\tconst usageEntryIndex = usageEntryId ? pathEntries.findIndex((entry) => entry.id === usageEntryId) : -1;\n\t\tlet latestInvalidatingEntryIndex = -1;\n\t\tfor (let index = pathEntries.length - 1; index >= 0; index--) {\n\t\t\tconst entry = pathEntries[index];\n\t\t\tif (entry.type === \"context_edit\" || entry.type === \"compaction\") {\n\t\t\t\tlatestInvalidatingEntryIndex = index;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (usageEntryIndex > latestInvalidatingEntryIndex) return estimate;\n\t}\n\n\tconst currentSystem = getCurrentSystemMessage(projection.messages);\n\tlet tokens = currentSystem ? estimateTokens(currentSystem) : 0;\n\tfor (const message of projection.messages) {\n\t\tif (message.role !== \"system\") tokens += estimateTokens(message);\n\t}\n\treturn { tokens, usageTokens: 0, trailingTokens: tokens, lastUsageIndex: null };\n}\n\nfunction getLegacyProjectedMessagesForCompaction(entry: LegacyProjectedSessionEntry): AgentMessage[] {\n\tif (entry.sourceEntry.type === \"compaction\") return [];\n\t// System messages are prompt state. The compaction entry snapshots their\n\t// effective value so they must not be summarized or retained as conversation.\n\treturn entry.messages.filter((message) => message.role !== \"system\");\n}\n\nfunction getLegacyRetainedTailForCompaction(compaction: LegacyCompactionEntry): AgentMessage[] {\n\treturn (compaction.retainedTail ?? []).filter(\n\t\t(message) => message.role !== \"system\" && !(message.role === \"assistant\" && message.stopReason === \"deferred\"),\n\t);\n}\n\n/** Prepare a pi-client/pi-server session branch without changing its durable entry representation. */\nexport function prepareLegacyCompaction(\n\tpathEntries: SessionTreeEntry[],\n\tsettings: CompactionSettings,\n\toptions: CompactionPreparationOptions = {},\n): Result<LegacyCompactionPreparation | undefined, CompactionError> {\n\tif (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === \"compaction\") {\n\t\treturn ok(undefined);\n\t}\n\n\tconst projection = buildLegacySessionProjection(pathEntries);\n\tconst projectedEntries = projection.entries;\n\tlet prevCompactionIndex = -1;\n\tfor (let index = pathEntries.length - 1; index >= 0; index--) {\n\t\tif (pathEntries[index].type === \"compaction\") {\n\t\t\tprevCompactionIndex = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet previousSummary: string | undefined;\n\tlet boundaryStart = 0;\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = pathEntries[prevCompactionIndex] as LegacyCompactionEntry;\n\t\tpreviousSummary = prevCompaction.summary;\n\t\tconst projectedCompactionIndex = projectedEntries.findIndex(\n\t\t\t(entry) => entry.sourceEntry.id === prevCompaction.id,\n\t\t);\n\t\tboundaryStart = projectedCompactionIndex >= 0 ? projectedCompactionIndex + 1 : projectedEntries.length;\n\t}\n\tconst boundaryEnd = projectedEntries.length;\n\tconst tokensBefore = estimateLegacyProjectedContextTokens(projection, pathEntries).tokens;\n\tconst previousRetainedTail =\n\t\tprevCompactionIndex >= 0\n\t\t\t? getLegacyRetainedTailForCompaction(pathEntries[prevCompactionIndex] as LegacyCompactionEntry)\n\t\t\t: [];\n\n\tconst forcedFirstKeptEntryIndex = options.firstKeptEntryId\n\t\t? projectedEntries.findIndex((entry) => entry.sourceEntry.id === options.firstKeptEntryId)\n\t\t: -1;\n\tif (\n\t\toptions.firstKeptEntryId &&\n\t\t(forcedFirstKeptEntryIndex < boundaryStart || forcedFirstKeptEntryIndex >= boundaryEnd)\n\t) {\n\t\treturn err(new CompactionError(\"invalid_session\", \"Forced first kept entry was not found\"));\n\t}\n\tconst cutPoint =\n\t\tforcedFirstKeptEntryIndex >= boundaryStart && forcedFirstKeptEntryIndex < boundaryEnd\n\t\t\t? { firstKeptEntryIndex: forcedFirstKeptEntryIndex, turnStartIndex: -1, isSplitTurn: false }\n\t\t\t: findLegacyProjectedCutPoint(projectedEntries, boundaryStart, boundaryEnd, settings.keepRecentTokens);\n\tconst firstKeptEntry = projectedEntries[cutPoint.firstKeptEntryIndex]?.sourceEntry;\n\tif (!firstKeptEntry?.id) {\n\t\treturn err(new CompactionError(\"invalid_session\", \"First kept entry has no UUID - session may need migration\"));\n\t}\n\n\tconst historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;\n\tconst messagesToSummarize = [\n\t\t...previousRetainedTail,\n\t\t...projectedEntries.slice(boundaryStart, historyEnd).flatMap(getLegacyProjectedMessagesForCompaction),\n\t];\n\tconst turnPrefixMessages = cutPoint.isSplitTurn\n\t\t? projectedEntries\n\t\t\t\t.slice(cutPoint.turnStartIndex, cutPoint.firstKeptEntryIndex)\n\t\t\t\t.flatMap(getLegacyProjectedMessagesForCompaction)\n\t\t: [];\n\tconst retainedTail = projectedEntries\n\t\t.slice(cutPoint.firstKeptEntryIndex, boundaryEnd)\n\t\t.flatMap(getLegacyProjectedMessagesForCompaction);\n\tif (messagesToSummarize.length === 0 && turnPrefixMessages.length === 0) return ok(undefined);\n\tconst fileOps = extractLegacyFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (const message of turnPrefixMessages) extractFileOpsFromMessage(message, fileOps);\n\t}\n\n\treturn ok({\n\t\tfirstKeptEntryId: firstKeptEntry.id,\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn: cutPoint.isSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t});\n}\n\nconst TURN_PREFIX_SUMMARIZATION_PROMPT = `This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.`;\n\nconst UPDATE_TURN_PREFIX_SUMMARIZATION_PROMPT = `The messages above are the next part of the same oversized turn prefix.\n\nUpdate the existing turn-prefix summary in <previous-summary> tags. Keep the same sections:\n\n## Original Request\n## Early Progress\n## Context for Suffix\n\nBe concise. Preserve exact file paths, function names, and error messages.`;\n\nexport { serializeConversation } from \"./utils.ts\";\n\n/** Generate compaction summary data from prepared session history. */\nexport function compact(\n\tpreparation: CompactionPreparation,\n\tmodels: Models,\n\tmodel: Model<Api>,\n\tcustomInstructions: string | undefined,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tretry: RetryPolicy | undefined,\n\tcallbacks: RetryCallbacks | undefined,\n\tcontext: Context,\n): Promise<Result<CompactResult, CompactionError>> {\n\treturn compactWithRequest(\n\t\tpreparation,\n\t\t{ model, customInstructions, thinkingLevel },\n\t\t(aiContext, options, requestContext) =>\n\t\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext),\n\t\tcontext,\n\t);\n}\n\nexport interface CompactGenerationOptions {\n\tmodel: Model<Api>;\n\tcustomInstructions?: string;\n\tthinkingLevel?: ThinkingLevel;\n}\n\n/** Generate compaction data through a caller-owned boundary for each provider request. */\nexport async function compactWithRequest(\n\tpreparation: CompactionPreparation,\n\toptions: CompactGenerationOptions,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<CompactResult, CompactionError>> {\n\tconst { model, customInstructions, thinkingLevel } = options;\n\tconst {\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t} = preparation;\n\n\tlet summary: string;\n\tlet summaryUsage: Usage;\n\n\tif (isSplitTurn && turnPrefixMessages.length > 0) {\n\t\tlet historyText = \"No prior history.\";\n\t\tlet historyUsage: Usage | undefined;\n\t\tif (messagesToSummarize.length > 0) {\n\t\t\tconst historyResult = await generateSummaryWithRequest(\n\t\t\t\tmessagesToSummarize,\n\t\t\t\t{ model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel },\n\t\t\t\trequest,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tif (!historyResult.ok) return err(historyResult.error);\n\t\t\thistoryText = historyResult.value.text;\n\t\t\thistoryUsage = historyResult.value.usage;\n\t\t}\n\t\tconst turnPrefixResult = await generateTurnPrefixSummary(\n\t\t\tturnPrefixMessages,\n\t\t\tmodel,\n\t\t\tsettings.reserveTokens,\n\t\t\tthinkingLevel,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!turnPrefixResult.ok) return err(turnPrefixResult.error);\n\t\tsummary = `${historyText}\\n\\n---\\n\\n**Turn Context (split turn):**\\n\\n${turnPrefixResult.value.text}`;\n\t\tsummaryUsage = historyUsage ? addUsage(historyUsage, turnPrefixResult.value.usage) : turnPrefixResult.value.usage;\n\t} else {\n\t\tconst summaryResult = await generateSummaryWithRequest(\n\t\t\tmessagesToSummarize,\n\t\t\t{ model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel },\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!summaryResult.ok) return err(summaryResult.error);\n\t\tsummary = summaryResult.value.text;\n\t\tsummaryUsage = summaryResult.value.usage;\n\t}\n\n\tconst { readFiles, modifiedFiles } = computeFileLists(fileOps);\n\tsummary += formatFileOperations(readFiles, modifiedFiles);\n\tconst details: CompactionDetails = { readFiles, modifiedFiles };\n\n\treturn ok({ summary, tokensBefore, usage: summaryUsage, retainedTail, details });\n}\n\n/** Compact a pi-client/pi-server session branch and preserve its retained entry id. */\nexport async function compactLegacy(\n\tpreparation: LegacyCompactionPreparation,\n\tmodels: Models,\n\tmodel: Model<Api>,\n\tcustomInstructions?: string,\n\tsignal?: AbortSignal,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n): Promise<Result<LegacyCompactResult, CompactionError>> {\n\tconst context = signal ? withAbortSignal(signal, BACKGROUND_CONTEXT) : BACKGROUND_CONTEXT;\n\tconst request: SummaryRequest = (aiContext, options, requestContext) =>\n\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext);\n\tconst result = await compactWithRequest(preparation, { model, customInstructions, thinkingLevel }, request, context);\n\treturn result.ok ? ok({ ...result.value, firstKeptEntryId: preparation.firstKeptEntryId }) : err(result.error);\n}\nasync function generateTurnPrefixSummary(\n\tmessages: AgentMessage[],\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst maxTokens = Math.min(\n\t\tMath.floor(0.5 * reserveTokens),\n\t\tmodel.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY,\n\t);\n\tconst result = await summarizeMessages(\n\t\tmessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tTURN_PREFIX_SUMMARIZATION_PROMPT,\n\t\tUPDATE_TURN_PREFIX_SUMMARIZATION_PROMPT,\n\t\tundefined,\n\t\trequest,\n\t\tcontext,\n\t);\n\tif (!result.ok && result.error.code === \"summarization_failed\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Turn prefix summarization failed: ${result.error.message.replace(/^Summarization failed: /, \"\")}`,\n\t\t\t),\n\t\t);\n\t}\n\treturn result;\n}\n"]}
1
+ {"version":3,"file":"compaction.d.ts","sourceRoot":"","sources":["../../../src/harness/compaction/compaction.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Context as AiContext,\n\ttype Api,\n\ttype AssistantMessage,\n\tcontentText,\n\tgetCurrentSystemMessage,\n\tisContextOverflow,\n\ttype Model,\n\ttype Models,\n\tnormalizeContext,\n\ttype RetryCallbacks,\n\ttype RetryPolicy,\n\tretryAssistantCall,\n\ttype SimpleStreamOptions,\n\ttype SystemMessage,\n\ttype Usage,\n\tuuidv7,\n} from \"@earendil-works/pi-ai\";\nimport type { AgentMessage, ThinkingLevel } from \"../../types.ts\";\nimport { BACKGROUND_CONTEXT, type Context, getTelemetryContext, withAbortSignal } from \"../context.ts\";\nimport {\n\tbuildLegacySessionProjection,\n\ttype LegacyCompactionEntry,\n\ttype LegacyProjectedSessionEntry,\n\tlegacyEntryToContextMessages,\n\ttype SessionTreeEntry,\n} from \"../legacy-session.ts\";\nimport { convertToLlm, createBranchSummaryMessage, createCompactionSummaryMessage } from \"../messages.ts\";\nimport { buildContextEntries, sessionEntryToContextMessages } from \"../session/context.ts\";\nimport type { CompactionEntry, Entry, JsonValue } from \"../session/types.ts\";\nimport { CompactionError, err, ok, type Result } from \"../types.ts\";\nimport { addUsage } from \"../utils/usage.ts\";\nimport {\n\tcomputeFileLists,\n\tcreateFileOps,\n\textractFileOpsFromMessage,\n\ttype FileOperations,\n\tformatFileOperations,\n\tserializeConversation,\n} from \"./utils.ts\";\n\n/** File-operation details stored on generated compaction entries. */\nexport interface CompactionDetails extends Record<string, JsonValue> {\n\t/** Files read in the compacted history. */\n\treadFiles: string[];\n\t/** Files modified in the compacted history. */\n\tmodifiedFiles: string[];\n\tcachePath: { mode: \"exact_prefix\" | \"chunked\"; reason: string };\n}\nfunction safeJsonStringify(value: unknown): string {\n\ttry {\n\t\treturn JSON.stringify(value) ?? \"undefined\";\n\t} catch {\n\t\treturn \"[unserializable]\";\n\t}\n}\n\nfunction extractFileOperations(\n\tmessages: AgentMessage[],\n\tentries: Entry[],\n\tprevCompactionIndex: number,\n): FileOperations {\n\tconst fileOps = createFileOps();\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = entries[prevCompactionIndex] as CompactionEntry;\n\t\tif (\n\t\t\ttypeof prevCompaction.details === \"object\" &&\n\t\t\tprevCompaction.details !== null &&\n\t\t\t!Array.isArray(prevCompaction.details)\n\t\t) {\n\t\t\tif (Array.isArray(prevCompaction.details.readFiles)) {\n\t\t\t\tfor (const path of prevCompaction.details.readFiles) {\n\t\t\t\t\tif (typeof path === \"string\") fileOps.read.add(path);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Array.isArray(prevCompaction.details.modifiedFiles)) {\n\t\t\t\tfor (const path of prevCompaction.details.modifiedFiles) {\n\t\t\t\t\tif (typeof path === \"string\") fileOps.edited.add(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (const msg of messages) {\n\t\textractFileOpsFromMessage(msg, fileOps);\n\t}\n\n\treturn fileOps;\n}\nfunction getMessageFromEntry(entry: Entry): AgentMessage | undefined {\n\tif (entry.type === \"message\") {\n\t\treturn entry.message as AgentMessage;\n\t}\n\tif (entry.type === \"branch_summary\") {\n\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\t}\n\tif (entry.type === \"compaction\") {\n\t\treturn createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp);\n\t}\n\treturn undefined;\n}\n\nfunction getMessageFromEntryForCompaction(entry: Entry): AgentMessage | undefined {\n\tif (entry.type === \"compaction\") {\n\t\treturn undefined;\n\t}\n\treturn getMessageFromEntry(entry);\n}\n\nfunction extractLegacyFileOperations(\n\tmessages: AgentMessage[],\n\tentries: SessionTreeEntry[],\n\tprevCompactionIndex: number,\n): FileOperations {\n\tconst fileOps = createFileOps();\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = entries[prevCompactionIndex] as LegacyCompactionEntry;\n\t\tif (!prevCompaction.fromHook && prevCompaction.details) {\n\t\t\tconst details = prevCompaction.details as CompactionDetails;\n\t\t\tif (Array.isArray(details.readFiles)) {\n\t\t\t\tfor (const file of details.readFiles) fileOps.read.add(file);\n\t\t\t}\n\t\t\tif (Array.isArray(details.modifiedFiles)) {\n\t\t\t\tfor (const file of details.modifiedFiles) fileOps.edited.add(file);\n\t\t\t}\n\t\t}\n\t}\n\tfor (const message of messages) extractFileOpsFromMessage(message, fileOps);\n\treturn fileOps;\n}\n\n/** Generated compaction data ready to be persisted as a compaction entry. */\nexport interface CompactResult<T = JsonValue> {\n\t/** Summary text that replaces compacted history in future context. */\n\tsummary: string;\n\t/** Estimated context tokens before compaction. */\n\ttokensBefore: number;\n\t/** Usage from the LLM call(s) that generated this summary, if available. */\n\tusage?: Usage;\n\t/** Retained recent messages stored directly on the compaction entry. */\n\tretainedTail: AgentMessage[];\n\t/** Optional implementation-specific details stored with the compaction entry. */\n\tdetails?: T;\n}\n\n/** Compaction result used by the pi-client/pi-server session-tree protocol. */\nexport interface LegacyCompactResult<T = unknown> extends CompactResult<T> {\n\t/** Entry id where retained history starts. */\n\tfirstKeptEntryId: string;\n}\n\nexport type SummaryRequest = (\n\taiContext: AiContext,\n\toptions: SimpleStreamOptions,\n\tcontext: Context,\n\tpreservePromptCache?: boolean,\n) => Promise<AssistantMessage>;\n\nexport type CompactionCacheRequestOptions = Pick<\n\tSimpleStreamOptions,\n\t\"cacheRetention\" | \"sessionId\" | \"transport\" | \"thinkingBudgets\" | \"maxRetryDelayMs\" | \"timeoutMs\"\n>;\n\nexport function createSummaryRequestOptions(\n\toptions: SimpleStreamOptions,\n\tcontext: Context,\n\tpreservePromptCache = false,\n): SimpleStreamOptions {\n\treturn {\n\t\t...options,\n\t\tsignal: context.abortSignal,\n\t\ttelemetryContext: getTelemetryContext(context),\n\t\t...(!preservePromptCache ? { cacheRetention: \"none\" as const } : {}),\n\t\tsessionId: preservePromptCache ? options.sessionId : (options.sessionId ?? uuidv7()),\n\t};\n}\n\nexport async function completeSimpleWithRetries(\n\tmodels: Models,\n\tmodel: Model<Api>,\n\taiContext: AiContext,\n\toptions: SimpleStreamOptions,\n\tretry: RetryPolicy | undefined,\n\tcallbacks: RetryCallbacks | undefined,\n\tcontext: Context,\n\tpreservePromptCache = false,\n): Promise<AssistantMessage> {\n\t// Chunked and branch summaries are one-off requests. The exact-prefix compaction path opts in explicitly.\n\tconst requestOptions = createSummaryRequestOptions(options, context, preservePromptCache);\n\treturn retryAssistantCall(\n\t\t() => models.completeSimple(model, aiContext, requestOptions),\n\t\tretry,\n\t\trequestOptions.signal,\n\t\tcallbacks,\n\t);\n}\n\n/** Compaction thresholds and retention settings. */\nexport interface CompactionSettings {\n\t/** Enable automatic compaction decisions. */\n\tenabled: boolean;\n\t/** Tokens reserved for summary prompt and output. */\n\treserveTokens: number;\n\t/** Approximate recent-context tokens to keep after compaction. */\n\tkeepRecentTokens: number;\n}\n\n/** Default compaction settings used by the harness. */\nexport const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tkeepRecentTokens: 20000,\n};\n\n/** Calculate total context tokens from provider usage. */\nexport function calculateContextTokens(usage: Usage): number {\n\treturn usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;\n}\nfunction getAssistantUsage(msg: AgentMessage): Usage | undefined {\n\tif (msg.role === \"assistant\" && \"usage\" in msg) {\n\t\tconst assistantMsg = msg as AssistantMessage;\n\t\tif (\n\t\t\tassistantMsg.stopReason !== \"aborted\" &&\n\t\t\tassistantMsg.stopReason !== \"error\" &&\n\t\t\tassistantMsg.usage &&\n\t\t\tcalculateContextTokens(assistantMsg.usage) > 0\n\t\t) {\n\t\t\treturn assistantMsg.usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Return usage from the last valid assistant message in session entries. */\nexport function getLastAssistantUsage(entries: Entry[]): Usage | undefined {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"message\") {\n\t\t\tconst usage = getAssistantUsage(entry.message as AgentMessage);\n\t\t\tif (usage) return usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Estimated context-token usage for a message list. */\nexport interface ContextUsageEstimate {\n\t/** Estimated total context tokens. */\n\ttokens: number;\n\t/** Tokens reported by the most recent assistant usage block. */\n\tusageTokens: number;\n\t/** Estimated tokens after the most recent assistant usage block. */\n\ttrailingTokens: number;\n\t/** Index of the message that provided usage, or null when none exists. */\n\tlastUsageIndex: number | null;\n}\n\nfunction getLastAssistantUsageInfo(messages: AgentMessage[]): { usage: Usage; index: number } | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst usage = getAssistantUsage(messages[i]);\n\t\tif (usage) return { usage, index: i };\n\t}\n\treturn undefined;\n}\n\n/** Estimate context tokens for messages using provider usage when available. */\nexport function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\n\tif (!usageInfo) {\n\t\tlet estimated = 0;\n\t\tfor (const message of messages) {\n\t\t\testimated += estimateTokens(message);\n\t\t}\n\t\treturn {\n\t\t\ttokens: estimated,\n\t\t\tusageTokens: 0,\n\t\t\ttrailingTokens: estimated,\n\t\t\tlastUsageIndex: null,\n\t\t};\n\t}\n\n\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\tlet trailingTokens = 0;\n\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\ttrailingTokens += estimateTokens(messages[i]);\n\t}\n\n\treturn {\n\t\ttokens: usageTokens + trailingTokens,\n\t\tusageTokens,\n\t\ttrailingTokens,\n\t\tlastUsageIndex: usageInfo.index,\n\t};\n}\n\n/** Return whether context usage exceeds the configured compaction threshold. */\nexport function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {\n\tif (!settings.enabled) return false;\n\treturn contextTokens > contextWindow - settings.reserveTokens;\n}\n\nconst ESTIMATED_IMAGE_CHARS = 4800;\n\nfunction estimateTextAndImageContentChars(content: string | Array<{ type: string; text?: string }>): number {\n\tif (typeof content === \"string\") {\n\t\treturn content.length;\n\t}\n\n\tlet chars = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"text\" && block.text) {\n\t\t\tchars += block.text.length;\n\t\t} else if (block.type === \"image\") {\n\t\t\tchars += ESTIMATED_IMAGE_CHARS;\n\t\t}\n\t}\n\treturn chars;\n}\n\n/** Estimate token count for one message using a conservative character heuristic. */\nexport function estimateTokens(message: AgentMessage): number {\n\tlet chars = 0;\n\n\tswitch (message.role) {\n\t\tcase \"system\": {\n\t\t\tconst system = message as SystemMessage;\n\t\t\tchars = estimateTextAndImageContentChars(system.content);\n\t\t\tif (system.sections) {\n\t\t\t\tfor (const section of Object.values(system.sections)) {\n\t\t\t\t\tif (section) chars += section.length;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (system.toolsAdded) chars += safeJsonStringify(system.toolsAdded).length;\n\t\t\tif (system.toolsRemoved) chars += safeJsonStringify(system.toolsRemoved).length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"user\": {\n\t\t\tchars = estimateTextAndImageContentChars(\n\t\t\t\t(message as { content: string | Array<{ type: string; text?: string }> }).content,\n\t\t\t);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"assistant\": {\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\tfor (const block of assistant.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tchars += block.text.length;\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tchars += block.thinking.length;\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tchars += block.name.length + safeJsonStringify(block.arguments).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"custom\":\n\t\tcase \"toolResult\": {\n\t\t\tchars = estimateTextAndImageContentChars(message.content);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"bashExecution\": {\n\t\t\tchars = message.command.length + message.output.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\": {\n\t\t\tchars = message.summary.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t}\n\n\treturn 0;\n}\nfunction findValidCutPoints(entries: Entry[], startIndex: number, endIndex: number): number[] {\n\tconst cutPoints: number[] = [];\n\tfor (let i = startIndex; i < endIndex; i++) {\n\t\tconst entry = entries[i];\n\t\tswitch (entry.type) {\n\t\t\tcase \"message\": {\n\t\t\t\tconst role = entry.message.role;\n\t\t\t\tswitch (role) {\n\t\t\t\t\tcase \"bashExecution\":\n\t\t\t\t\tcase \"custom\":\n\t\t\t\t\tcase \"branchSummary\":\n\t\t\t\t\tcase \"compactionSummary\":\n\t\t\t\t\tcase \"user\":\n\t\t\t\t\tcase \"assistant\":\n\t\t\t\t\t\tcutPoints.push(i);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"toolResult\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"compaction\":\n\t\t\tcase \"branch_summary\":\n\t\t\tcase \"custom\":\n\t\t\t\tbreak;\n\t\t}\n\t\tif (entry.type === \"branch_summary\") cutPoints.push(i);\n\t}\n\treturn cutPoints;\n}\n\n/** Find the user-visible message that starts the turn containing an entry. */\nexport function findTurnStartIndex(entries: Entry[], entryIndex: number, startIndex: number): number {\n\tfor (let i = entryIndex; i >= startIndex; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"branch_summary\") {\n\t\t\treturn i;\n\t\t}\n\t\tif (entry.type === \"message\") {\n\t\t\tconst role = entry.message.role;\n\t\t\tif (role === \"user\" || role === \"bashExecution\") {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t}\n\treturn -1;\n}\n\n/** Cut point selected for compaction. */\nexport interface CutPointResult {\n\t/** Index of the first entry retained after compaction. */\n\tfirstKeptEntryIndex: number;\n\t/** Index of the turn-start entry when the cut splits a turn, otherwise -1. */\n\tturnStartIndex: number;\n\t/** Whether the selected cut point splits an in-progress turn. */\n\tisSplitTurn: boolean;\n}\n\n/** Find the compaction cut point that keeps approximately the requested recent-token budget. */\nexport function findCutPoint(\n\tentries: Entry[],\n\tstartIndex: number,\n\tendIndex: number,\n\tkeepRecentTokens: number,\n): CutPointResult {\n\tconst cutPoints = findValidCutPoints(entries, startIndex, endIndex);\n\n\tif (cutPoints.length === 0) {\n\t\treturn { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };\n\t}\n\tlet accumulatedTokens = 0;\n\tlet cutIndex = cutPoints[0];\n\n\tfor (let i = endIndex - 1; i >= startIndex; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type !== \"message\") continue;\n\t\tconst messageTokens = estimateTokens(entry.message as AgentMessage);\n\t\taccumulatedTokens += messageTokens;\n\t\tif (accumulatedTokens >= keepRecentTokens) {\n\t\t\tfor (let c = 0; c < cutPoints.length; c++) {\n\t\t\t\tif (cutPoints[c] >= i) {\n\t\t\t\t\tcutIndex = cutPoints[c];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\twhile (cutIndex > startIndex) {\n\t\tconst prevEntry = entries[cutIndex - 1];\n\t\tif (prevEntry.type === \"compaction\") {\n\t\t\tbreak;\n\t\t}\n\t\tif (prevEntry.type === \"message\") {\n\t\t\tbreak;\n\t\t}\n\t\tcutIndex--;\n\t}\n\tconst cutEntry = entries[cutIndex];\n\tconst isUserMessage = cutEntry.type === \"message\" && cutEntry.message.role === \"user\";\n\tconst turnStartIndex = isUserMessage ? -1 : findTurnStartIndex(entries, cutIndex, startIndex);\n\n\treturn {\n\t\tfirstKeptEntryIndex: cutIndex,\n\t\tturnStartIndex,\n\t\tisSplitTurn: !isUserMessage && turnStartIndex !== -1,\n\t};\n}\n\nfunction isLegacyProjectionCutPointMessage(message: AgentMessage): boolean {\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"assistant\":\n\t\tcase \"bashExecution\":\n\t\tcase \"custom\":\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn true;\n\t\tcase \"toolResult\":\n\t\tcase \"system\":\n\t\t\treturn false;\n\t}\n}\n\nfunction isLegacyProjectionTurnStartMessage(message: AgentMessage): boolean {\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"bashExecution\":\n\t\tcase \"custom\":\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn true;\n\t\tcase \"assistant\":\n\t\tcase \"toolResult\":\n\t\tcase \"system\":\n\t\t\treturn false;\n\t}\n}\n\nfunction findLegacyProjectedValidCutPoints(\n\tentries: LegacyProjectedSessionEntry[],\n\tstartIndex: number,\n\tendIndex: number,\n): number[] {\n\tconst cutPoints: number[] = [];\n\tfor (let index = startIndex; index < endIndex; index++) {\n\t\tconst entry = entries[index];\n\t\tif (entry.sourceEntry.type !== \"compaction\" && entry.messages.some(isLegacyProjectionCutPointMessage)) {\n\t\t\tcutPoints.push(index);\n\t\t}\n\t}\n\treturn cutPoints;\n}\n\nfunction findLegacyProjectedTurnStartIndex(\n\tentries: LegacyProjectedSessionEntry[],\n\tentryIndex: number,\n\tstartIndex: number,\n): number {\n\tfor (let index = entryIndex; index >= startIndex; index--) {\n\t\tif (entries[index].messages.some(isLegacyProjectionTurnStartMessage)) return index;\n\t}\n\treturn -1;\n}\n\nfunction findLegacyProjectedCutPoint(\n\tentries: LegacyProjectedSessionEntry[],\n\tstartIndex: number,\n\tendIndex: number,\n\tkeepRecentTokens: number,\n): CutPointResult {\n\tconst cutPoints = findLegacyProjectedValidCutPoints(entries, startIndex, endIndex);\n\tif (cutPoints.length === 0) {\n\t\treturn { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };\n\t}\n\n\tlet accumulatedTokens = 0;\n\tlet exceededBudget = false;\n\tlet cutIndex = cutPoints[0];\n\tfor (let index = endIndex - 1; index >= startIndex; index--) {\n\t\tconst messageTokens = entries[index].messages.reduce((sum, message) => sum + estimateTokens(message), 0);\n\t\tif (messageTokens === 0) continue;\n\t\taccumulatedTokens += messageTokens;\n\t\tif (accumulatedTokens >= keepRecentTokens) {\n\t\t\texceededBudget = true;\n\t\t\tcutIndex = cutPoints.find((candidate) => candidate >= index) ?? cutPoints[cutPoints.length - 1];\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// A completed recovery attempt and its omission edits are context-invisible after\n\t// the last visible input. Advance past that closed suffix without skipping a\n\t// replacement edit for a visible input.\n\tconst suffix = entries.slice(cutIndex + 1, endIndex);\n\tconst isIntrinsicallyVisible = (entry: LegacyProjectedSessionEntry): boolean =>\n\t\tentry.sourceEntry.type !== \"context_edit\" && legacyEntryToContextMessages(entry.sourceEntry).length > 0;\n\tconst isOmitted = (entry: LegacyProjectedSessionEntry): boolean =>\n\t\tisIntrinsicallyVisible(entry) && entry.messages.length === 0;\n\tconst omittedSuffixIds = new Set(suffix.filter(isOmitted).map((entry) => entry.sourceEntry.id));\n\tconst hasExternalReplacement = suffix.some(\n\t\t(entry) =>\n\t\t\tentry.sourceEntry.type === \"context_edit\" &&\n\t\t\tentry.sourceEntry.replacement !== null &&\n\t\t\t!omittedSuffixIds.has(entry.sourceEntry.targetId),\n\t);\n\tconst isRecoveryOmissionSuffix =\n\t\texceededBudget &&\n\t\t!hasExternalReplacement &&\n\t\tsuffix.some(\n\t\t\t(entry) =>\n\t\t\t\tentry.sourceEntry.type === \"message\" && entry.sourceEntry.message.role === \"assistant\" && isOmitted(entry),\n\t\t) &&\n\t\tsuffix.every(\n\t\t\t(entry) => entry.sourceEntry.type !== \"compaction\" && (!isIntrinsicallyVisible(entry) || isOmitted(entry)),\n\t\t);\n\tif (isRecoveryOmissionSuffix) cutIndex++;\n\n\twhile (cutIndex > startIndex) {\n\t\tconst previousEntry = entries[cutIndex - 1];\n\t\tif (previousEntry.sourceEntry.type === \"compaction\" || previousEntry.messages.length > 0) break;\n\t\tcutIndex--;\n\t}\n\tconst startsTurn = entries[cutIndex].messages.some(isLegacyProjectionTurnStartMessage);\n\tconst turnStartIndex = startsTurn ? -1 : findLegacyProjectedTurnStartIndex(entries, cutIndex, startIndex);\n\treturn {\n\t\tfirstKeptEntryIndex: cutIndex,\n\t\tturnStartIndex,\n\t\tisSplitTurn: !startsTurn && turnStartIndex !== -1,\n\t};\n}\n\nexport const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;\n\nconst SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.\n\nUse this EXACT format:\n\n## Goal\n[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]\n\n## Constraints & Preferences\n- [Any constraints, preferences, or requirements mentioned by user]\n- [Or \"(none)\" if none were mentioned]\n\n## Progress\n### Done\n- [x] [Completed tasks/changes]\n\n### In Progress\n- [ ] [Current work]\n\n### Blocked\n- [Issues preventing progress, if any]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale]\n\n## Operational State\n- Modified files: [Exact paths, or \"(none)\"]\n- Read files: [Exact paths, or \"(none)\"]\n- Open failures: [Current unresolved failures/errors, or \"(none)\"]\n- Last command: [Most recent test/build/shell command and exit code, or \"(none)\"]\n- Last failing assertion/error: [Exact assertion, stack frame, or failing lines if available, or \"(none)\"]\n- Pending TODO: [Concrete remaining work, or \"(none)\"]\n\n## Next Steps\n1. [Ordered list of what should happen next]\n\n## Critical Context\n- [Any data, examples, or references needed to continue]\n- [Or \"(none)\" if not applicable]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\nconst UPDATE_SUMMARIZATION_PROMPT = `The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.\n\nUpdate the existing structured summary with new information. RULES:\n- PRESERVE all existing information from the previous summary\n- ADD new progress, decisions, and context from the new messages\n- UPDATE the Progress section: move items from \"In Progress\" to \"Done\" when completed\n- UPDATE \"Next Steps\" based on what was accomplished\n- PRESERVE exact file paths, function names, and error messages\n- If something is no longer relevant, you may remove it\n\nUse this EXACT format:\n\n## Goal\n[Preserve existing goals, add new ones if the task expanded]\n\n## Constraints & Preferences\n- [Preserve existing, add new ones discovered]\n\n## Progress\n### Done\n- [x] [Include previously done items AND newly completed items]\n\n### In Progress\n- [ ] [Current work - update based on progress]\n\n### Blocked\n- [Current blockers - remove if resolved]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale] (preserve all previous, add new)\n\n## Operational State\n- Modified files: [Preserve/update exact paths, or \"(none)\"]\n- Read files: [Preserve/update exact paths, or \"(none)\"]\n- Open failures: [Current unresolved failures/errors, or \"(none)\"]\n- Last command: [Most recent test/build/shell command and exit code, or \"(none)\"]\n- Last failing assertion/error: [Exact assertion, stack frame, or failing lines if available, or \"(none)\"]\n- Pending TODO: [Concrete remaining work, or \"(none)\"]\n\n## Next Steps\n1. [Update based on current state]\n\n## Critical Context\n- [Preserve important context, add new if needed]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\nfunction getSummaryMaxTokens(model: Model<any>, reserveTokens: number): number {\n\treturn Math.min(Math.floor(0.8 * reserveTokens), model.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY);\n}\n\nfunction estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction buildSummaryPrompt(conversationText: string, basePrompt: string, previousSummary: string | undefined): string {\n\tlet promptText = `<conversation>\\n${conversationText}\\n</conversation>\\n\\n`;\n\tif (previousSummary) {\n\t\tpromptText += `<previous-summary>\\n${previousSummary}\\n</previous-summary>\\n\\n`;\n\t}\n\treturn promptText + basePrompt;\n}\n\nfunction getSummaryInputBudget(\n\tmodel: Model<any>,\n\tmaxTokens: number,\n\tbasePrompt: string,\n\tpreviousSummary: string | undefined,\n): number {\n\tif (model.contextWindow <= 0) return Number.POSITIVE_INFINITY;\n\tconst overheadTokens = estimateTextTokens(buildSummaryPrompt(\"\", basePrompt, previousSummary));\n\treturn Math.max(1, Math.floor(model.contextWindow - maxTokens - overheadTokens));\n}\n\nfunction toSummarySegments(messages: AgentMessage[]): string[] {\n\treturn messages\n\t\t.map((message) => serializeConversation(convertToLlm([message])))\n\t\t.filter((segment) => segment.length > 0);\n}\n\nfunction takeSummaryChunk(segments: string[], tokenBudget: number): { chunk: string; remaining: string[] } {\n\tif (!Number.isFinite(tokenBudget)) return { chunk: segments.join(\"\\n\\n\"), remaining: [] };\n\n\tconst chunk: string[] = [];\n\tlet chunkTokens = 0;\n\n\tfor (let i = 0; i < segments.length; i++) {\n\t\tconst segment = segments[i];\n\t\tconst messageTokens = Math.max(1, estimateTextTokens(segment));\n\t\tif (chunk.length === 0 && messageTokens > tokenBudget) {\n\t\t\tconst chunkChars = Math.max(1, Math.floor(tokenBudget * 4));\n\t\t\tconst remainingSegment = segment.slice(chunkChars);\n\t\t\tconst remaining = remainingSegment ? [remainingSegment, ...segments.slice(i + 1)] : segments.slice(i + 1);\n\t\t\treturn { chunk: segment.slice(0, chunkChars), remaining };\n\t\t}\n\t\tif (chunk.length > 0 && chunkTokens + messageTokens > tokenBudget) {\n\t\t\treturn { chunk: chunk.join(\"\\n\\n\"), remaining: segments.slice(i) };\n\t\t}\n\t\tchunk.push(segment);\n\t\tchunkTokens += messageTokens;\n\t}\n\n\treturn { chunk: chunk.join(\"\\n\\n\"), remaining: [] };\n}\n\nasync function summarizeChunk(\n\tconversationText: string,\n\tmodel: Model<Api>,\n\tmaxTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tinitialPrompt: string,\n\tupdatePrompt: string,\n\tpreviousSummary: string | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst basePrompt = previousSummary ? updatePrompt : initialPrompt;\n\tconst promptText = buildSummaryPrompt(conversationText, basePrompt, previousSummary);\n\tconst summarizationMessages = [\n\t\t{\n\t\t\trole: \"user\" as const,\n\t\t\tcontent: [{ type: \"text\" as const, text: promptText }],\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t];\n\n\tconst completionOptions =\n\t\tmodel.reasoning && thinkingLevel && thinkingLevel !== \"off\"\n\t\t\t? { maxTokens, reasoning: thinkingLevel }\n\t\t\t: { maxTokens };\n\n\tconst response = await request(\n\t\t{ systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: summarizationMessages },\n\t\tcreateSummaryRequestOptions(completionOptions, context),\n\t\tcontext,\n\t);\n\n\tif (isContextOverflow(response, model.contextWindow) && conversationText.length > 1) {\n\t\tconst middle = Math.ceil(conversationText.length / 2);\n\t\tconst leftSummary = await summarizeChunk(\n\t\t\tconversationText.slice(0, middle),\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tpreviousSummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!leftSummary.ok) return leftSummary;\n\t\tconst rightSummary = await summarizeChunk(\n\t\t\tconversationText.slice(middle),\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tleftSummary.value.text,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!rightSummary.ok) return rightSummary;\n\t\treturn ok({\n\t\t\ttext: rightSummary.value.text,\n\t\t\tusage: addUsage(leftSummary.value.usage, rightSummary.value.usage),\n\t\t});\n\t}\n\tif (response.stopReason === \"aborted\") {\n\t\treturn err(new CompactionError(\"aborted\", response.errorMessage || \"Summarization aborted\"));\n\t}\n\tif (response.stopReason === \"error\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Summarization failed: ${response.errorMessage || \"Unknown error\"}`,\n\t\t\t),\n\t\t);\n\t}\n\tif (response.stopReason === \"length\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t\"Summarization failed: generation hit the token cap and the summary is incomplete\",\n\t\t\t),\n\t\t);\n\t}\n\tif (response.content.some((block) => block.type === \"toolCall\")) {\n\t\treturn err(new CompactionError(\"summarization_failed\", \"Summarization attempted to call a tool\"));\n\t}\n\n\treturn ok({ text: contentText(response.content), usage: response.usage });\n}\n\nasync function summarizeMessages(\n\tmessages: AgentMessage[],\n\tmodel: Model<Api>,\n\tmaxTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tinitialPrompt: string,\n\tupdatePrompt: string,\n\tpreviousSummary: string | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tlet remaining = toSummarySegments(messages);\n\tif (remaining.length === 0) {\n\t\treturn summarizeChunk(\n\t\t\t\"\",\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tpreviousSummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t}\n\tlet summary = previousSummary;\n\tlet summaryUsage: Usage | undefined;\n\twhile (remaining.length > 0) {\n\t\tconst basePrompt = summary ? updatePrompt : initialPrompt;\n\t\tconst next = takeSummaryChunk(remaining, getSummaryInputBudget(model, maxTokens, basePrompt, summary));\n\t\tconst chunkSummary = await summarizeChunk(\n\t\t\tnext.chunk,\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tsummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!chunkSummary.ok) return chunkSummary;\n\t\tsummary = chunkSummary.value.text;\n\t\tsummaryUsage = summaryUsage ? addUsage(summaryUsage, chunkSummary.value.usage) : chunkSummary.value.usage;\n\t\tremaining = next.remaining;\n\t}\n\tif (!summaryUsage) {\n\t\treturn err(new CompactionError(\"summarization_failed\", \"Summarization returned no usage data\"));\n\t}\n\treturn ok({ text: summary ?? \"\", usage: summaryUsage });\n}\n\nasync function summarizeCachePrefix(\n\tpreparation: CompactionPreparation,\n\tcacheContext: AiContext,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions: string | undefined,\n\tpreviousSummary: string | undefined,\n\tthinkingLevel: ThinkingLevel | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n\tcacheOptions: CompactionCacheRequestOptions,\n): Promise<\n\t| { kind: \"unavailable\"; reason: string }\n\t| { kind: \"overflow\" }\n\t| { kind: \"error\"; error: CompactionError }\n\t| { kind: \"summary\"; value: { text: string; usage: Usage } }\n> {\n\tconst cachePrefixMessages = preparation.cachePrefixMessages;\n\tif (!cachePrefixMessages) return { kind: \"unavailable\", reason: \"projected_prefix_unavailable\" };\n\tif (!cacheOptions.sessionId) return { kind: \"unavailable\", reason: \"session_id_unavailable\" };\n\tconst fullContext = normalizeContext(cacheContext);\n\tconst prefixContext = normalizeContext({\n\t\tsystemPrompt: cacheContext.systemPrompt,\n\t\ttools: cacheContext.tools,\n\t\tmessages: convertToLlm(cachePrefixMessages),\n\t});\n\tif (\n\t\tprefixContext.messages.length > fullContext.messages.length ||\n\t\tprefixContext.messages.some(\n\t\t\t(message, index) => JSON.stringify(message) !== JSON.stringify(fullContext.messages[index]),\n\t\t)\n\t) {\n\t\treturn { kind: \"unavailable\", reason: \"projected_prefix_mismatch\" };\n\t}\n\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\tconst prefixScope =\n\t\t\"Summarize the conversation in the provider context above up to this instruction. That context is the canonical prefix selected by the compaction cut point; the retained tail is excluded. Do not call tools; output only the checkpoint summary. Report only observed failures. Preserve the latest exact failing assertion/error from the prior summary or transcript. Mark it resolved only if the same failing command/assertion passes or direct evidence fixes it; an unrelated later check does not resolve it. Otherwise keep the exact failure as unresolved/last known. Use (none) only when no prior or observed failure exists. Put unrun checks under Pending TODO, never Open failures.\";\n\tconst instruction = previousSummary\n\t\t? `${prefixScope}\\n\\nA prior compaction summary appears in the provider context above inside <summary> tags. Preserve its information and update the structured summary using the conversation messages that follow it. Keep the same sections and exact file paths, function names, and error messages.\\n\\n${initialPrompt}`\n\t\t: `${prefixScope}\\n\\n${initialPrompt}`;\n\tconst summaryContext = normalizeContext({\n\t\tmessages: [\n\t\t\t...prefixContext.messages,\n\t\t\t{ role: \"user\", content: [{ type: \"text\", text: instruction }], timestamp: Date.now() },\n\t\t],\n\t});\n\tconst options: SimpleStreamOptions = {\n\t\tmaxTokens,\n\t\t...(model.reasoning && thinkingLevel && thinkingLevel !== \"off\" ? { reasoning: thinkingLevel } : {}),\n\t\t...cacheOptions,\n\t};\n\tconst response = await request(summaryContext, createSummaryRequestOptions(options, context, true), context, true);\n\tif (response.stopReason === \"error\" && isContextOverflow(response, model.contextWindow)) return { kind: \"overflow\" };\n\tif (response.stopReason === \"aborted\") {\n\t\treturn { kind: \"error\", error: new CompactionError(\"aborted\", response.errorMessage || \"Summarization aborted\") };\n\t}\n\tif (response.stopReason === \"error\") {\n\t\treturn {\n\t\t\tkind: \"error\",\n\t\t\terror: new CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Summarization failed: ${response.errorMessage || \"Unknown error\"}`,\n\t\t\t),\n\t\t};\n\t}\n\tif (response.stopReason === \"length\") {\n\t\treturn {\n\t\t\tkind: \"error\",\n\t\t\terror: new CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t\"Summarization failed: generation hit the token cap and the summary is incomplete\",\n\t\t\t),\n\t\t};\n\t}\n\tif (response.content.some((block) => block.type === \"toolCall\")) {\n\t\treturn {\n\t\t\tkind: \"error\",\n\t\t\terror: new CompactionError(\"summarization_failed\", \"Summarization attempted to call a tool\"),\n\t\t};\n\t}\n\treturn { kind: \"summary\", value: { text: contentText(response.content), usage: response.usage } };\n}\n\n/** Generate or update a conversation summary for compaction. */\nexport async function generateSummary(\n\tcurrentMessages: AgentMessage[],\n\tmodels: Models,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions?: string,\n\tpreviousSummary?: string,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcontext: Context = BACKGROUND_CONTEXT,\n): Promise<Result<string, CompactionError>> {\n\tconst result = await generateSummaryWithUsage(\n\t\tcurrentMessages,\n\t\tmodels,\n\t\tmodel,\n\t\treserveTokens,\n\t\tcustomInstructions,\n\t\tpreviousSummary,\n\t\tthinkingLevel,\n\t\tretry,\n\t\tcallbacks,\n\t\tcontext,\n\t);\n\treturn result.ok ? ok(result.value.text) : err(result.error);\n}\n\n/** Generate or update a conversation summary and return its provider usage. */\nexport function generateSummaryWithUsage(\n\tcurrentMessages: AgentMessage[],\n\tmodels: Models,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions?: string,\n\tpreviousSummary?: string,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcontext: Context = BACKGROUND_CONTEXT,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tlet updatePrompt = UPDATE_SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t\tupdatePrompt = `${updatePrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\tconst request: SummaryRequest = (aiContext, options, requestContext) =>\n\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext);\n\treturn summarizeMessages(\n\t\tcurrentMessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tinitialPrompt,\n\t\tupdatePrompt,\n\t\tpreviousSummary,\n\t\trequest,\n\t\tcontext,\n\t);\n}\n\nexport interface SummaryGenerationOptions {\n\tmodel: Model<Api>;\n\treserveTokens: number;\n\tcustomInstructions?: string;\n\tpreviousSummary?: string;\n\tthinkingLevel?: ThinkingLevel;\n}\n\n/** Generate one summary through a caller-owned one-request boundary. */\nexport function generateSummaryWithRequest(\n\tcurrentMessages: AgentMessage[],\n\toptions: SummaryGenerationOptions,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst { model, reserveTokens, customInstructions, previousSummary, thinkingLevel } = options;\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tlet updatePrompt = UPDATE_SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t\tupdatePrompt = `${updatePrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\treturn summarizeMessages(\n\t\tcurrentMessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tinitialPrompt,\n\t\tupdatePrompt,\n\t\tpreviousSummary,\n\t\trequest,\n\t\tcontext,\n\t);\n}\n\n/** Prepared inputs for a compaction run. */\nexport interface CompactionPreparation {\n\t/** Canonical model-visible session prefix before the current cut point. */\n\tcachePrefixMessages?: AgentMessage[];\n\t/** Messages summarized into the history summary. */\n\tmessagesToSummarize: AgentMessage[];\n\t/** Prefix messages summarized separately when compaction splits a turn. */\n\tturnPrefixMessages: AgentMessage[];\n\t/** Recent messages retained after compaction and stored on the compaction entry. */\n\tretainedTail: AgentMessage[];\n\t/** Whether compaction splits a turn. */\n\tisSplitTurn: boolean;\n\t/** Estimated context tokens before compaction. */\n\ttokensBefore: number;\n\t/** Previous compaction summary used for iterative updates. */\n\tpreviousSummary?: string;\n\t/** File operations extracted from summarized history. */\n\tfileOps: FileOperations;\n\t/** Settings used to prepare compaction. */\n\tsettings: CompactionSettings;\n}\n\n/** Prepare session entries for compaction, or return undefined when compaction is not applicable. */\nexport function prepareCompaction(\n\tpathEntries: Entry[],\n\tsettings: CompactionSettings,\n): Result<CompactionPreparation | undefined, CompactionError> {\n\tif (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === \"compaction\") {\n\t\treturn ok(undefined);\n\t}\n\n\tlet prevCompactionIndex = -1;\n\tfor (let i = pathEntries.length - 1; i >= 0; i--) {\n\t\tif (pathEntries[i].type === \"compaction\") {\n\t\t\tprevCompactionIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet previousSummary: string | undefined;\n\tlet compactableEntries = pathEntries;\n\tif (prevCompactionIndex >= 0) {\n\t\tconst previousCompaction = pathEntries[prevCompactionIndex] as CompactionEntry;\n\t\tpreviousSummary = previousCompaction.summary;\n\t\tconst virtualRetainedEntries: Entry[] = previousCompaction.retainedTail.map((message, index) => ({\n\t\t\ttype: \"message\",\n\t\t\tid: `${previousCompaction.id}:retained:${index}`,\n\t\t\tparentId: index === 0 ? previousCompaction.id : `${previousCompaction.id}:retained:${index - 1}`,\n\t\t\tseq: previousCompaction.seq,\n\t\t\ttimestamp: message.timestamp,\n\t\t\tmessage,\n\t\t}));\n\t\tcompactableEntries = [...virtualRetainedEntries, ...pathEntries.slice(prevCompactionIndex + 1)];\n\t}\n\tconst boundaryEnd = compactableEntries.length;\n\n\tconst tokensBefore = estimateContextTokens(\n\t\tbuildContextEntries(pathEntries).flatMap(sessionEntryToContextMessages),\n\t).tokens;\n\tconst cutPoint = findCutPoint(compactableEntries, 0, boundaryEnd, settings.keepRecentTokens);\n\tconst historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;\n\tconst messagesToSummarize: AgentMessage[] = [];\n\tfor (let i = 0; i < historyEnd; i++) {\n\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\tif (msg) messagesToSummarize.push(msg);\n\t}\n\tconst turnPrefixMessages: AgentMessage[] = [];\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (let i = cutPoint.turnStartIndex; i < cutPoint.firstKeptEntryIndex; i++) {\n\t\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\t\tif (msg) turnPrefixMessages.push(msg);\n\t\t}\n\t}\n\tconst retainedTail: AgentMessage[] = [];\n\tfor (let i = cutPoint.firstKeptEntryIndex; i < boundaryEnd; i++) {\n\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\tif (msg) retainedTail.push(msg);\n\t}\n\tconst cachePrefixMessages: AgentMessage[] = [];\n\tif (prevCompactionIndex >= 0) {\n\t\tconst previousCompaction = pathEntries[prevCompactionIndex] as CompactionEntry;\n\t\tcachePrefixMessages.push(\n\t\t\tcreateCompactionSummaryMessage(\n\t\t\t\tpreviousCompaction.summary,\n\t\t\t\tpreviousCompaction.tokensBefore,\n\t\t\t\tpreviousCompaction.timestamp,\n\t\t\t),\n\t\t);\n\t\tconst previousRetainedCount = Math.min(historyEnd, previousCompaction.retainedTail.length);\n\t\tfor (let i = 0; i < previousRetainedCount; i++) {\n\t\t\tconst message = previousCompaction.retainedTail[i];\n\t\t\tif (message) cachePrefixMessages.push(message);\n\t\t}\n\t\tconst newHistoryEnd = Math.max(0, historyEnd - previousCompaction.retainedTail.length);\n\t\tfor (const entry of pathEntries.slice(prevCompactionIndex + 1, prevCompactionIndex + 1 + newHistoryEnd)) {\n\t\t\tconst message = getMessageFromEntryForCompaction(entry);\n\t\t\tif (message) cachePrefixMessages.push(message);\n\t\t}\n\t} else {\n\t\tfor (const entry of pathEntries.slice(0, historyEnd)) {\n\t\t\tconst message = getMessageFromEntryForCompaction(entry);\n\t\t\tif (message) cachePrefixMessages.push(message);\n\t\t}\n\t}\n\tconst fileOps = extractFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (const msg of turnPrefixMessages) {\n\t\t\textractFileOpsFromMessage(msg, fileOps);\n\t\t}\n\t}\n\n\treturn ok({\n\t\tcachePrefixMessages,\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn: cutPoint.isSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t});\n}\n\n/** Optional cut-point override for the pi-client/pi-server legacy session tree. */\nexport interface CompactionPreparationOptions {\n\tfirstKeptEntryId?: string;\n}\n\n/** Prepared compaction inputs with the retained entry id required by the pi-server protocol. */\nexport interface LegacyCompactionPreparation extends CompactionPreparation {\n\tfirstKeptEntryId: string;\n}\n\nfunction estimateLegacyProjectedContextTokens(\n\tprojection: ReturnType<typeof buildLegacySessionProjection>,\n\tpathEntries: SessionTreeEntry[],\n): ContextUsageEstimate {\n\tconst estimate = estimateContextTokens(projection.messages);\n\tif (estimate.lastUsageIndex !== null) {\n\t\tlet projectedMessageIndex = 0;\n\t\tlet usageEntryId: string | undefined;\n\t\tfor (const entry of projection.entries) {\n\t\t\tconst nextMessageIndex = projectedMessageIndex + entry.messages.length;\n\t\t\tif (estimate.lastUsageIndex < nextMessageIndex) {\n\t\t\t\tusageEntryId = entry.sourceEntry.id;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprojectedMessageIndex = nextMessageIndex;\n\t\t}\n\n\t\tconst usageEntryIndex = usageEntryId ? pathEntries.findIndex((entry) => entry.id === usageEntryId) : -1;\n\t\tlet latestInvalidatingEntryIndex = -1;\n\t\tfor (let index = pathEntries.length - 1; index >= 0; index--) {\n\t\t\tconst entry = pathEntries[index];\n\t\t\tif (entry.type === \"context_edit\" || entry.type === \"compaction\") {\n\t\t\t\tlatestInvalidatingEntryIndex = index;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (usageEntryIndex > latestInvalidatingEntryIndex) return estimate;\n\t}\n\n\tconst currentSystem = getCurrentSystemMessage(projection.messages);\n\tlet tokens = currentSystem ? estimateTokens(currentSystem) : 0;\n\tfor (const message of projection.messages) {\n\t\tif (message.role !== \"system\") tokens += estimateTokens(message);\n\t}\n\treturn { tokens, usageTokens: 0, trailingTokens: tokens, lastUsageIndex: null };\n}\n\nfunction getLegacyProjectedMessagesForCompaction(entry: LegacyProjectedSessionEntry): AgentMessage[] {\n\tif (entry.sourceEntry.type === \"compaction\") return [];\n\t// System messages are prompt state. The compaction entry snapshots their\n\t// effective value so they must not be summarized or retained as conversation.\n\treturn entry.messages.filter((message) => message.role !== \"system\");\n}\n\nfunction getLegacyRetainedTailForCompaction(compaction: LegacyCompactionEntry): AgentMessage[] {\n\treturn (compaction.retainedTail ?? []).filter(\n\t\t(message) => message.role !== \"system\" && !(message.role === \"assistant\" && message.stopReason === \"deferred\"),\n\t);\n}\n\n/** Prepare a pi-client/pi-server session branch without changing its durable entry representation. */\nexport function prepareLegacyCompaction(\n\tpathEntries: SessionTreeEntry[],\n\tsettings: CompactionSettings,\n\toptions: CompactionPreparationOptions = {},\n): Result<LegacyCompactionPreparation | undefined, CompactionError> {\n\tif (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === \"compaction\") {\n\t\treturn ok(undefined);\n\t}\n\n\tconst projection = buildLegacySessionProjection(pathEntries);\n\tconst projectedEntries = projection.entries;\n\tlet prevCompactionIndex = -1;\n\tfor (let index = pathEntries.length - 1; index >= 0; index--) {\n\t\tif (pathEntries[index].type === \"compaction\") {\n\t\t\tprevCompactionIndex = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet previousSummary: string | undefined;\n\tlet boundaryStart = 0;\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = pathEntries[prevCompactionIndex] as LegacyCompactionEntry;\n\t\tpreviousSummary = prevCompaction.summary;\n\t\tconst projectedCompactionIndex = projectedEntries.findIndex(\n\t\t\t(entry) => entry.sourceEntry.id === prevCompaction.id,\n\t\t);\n\t\tboundaryStart = projectedCompactionIndex >= 0 ? projectedCompactionIndex + 1 : projectedEntries.length;\n\t}\n\tconst boundaryEnd = projectedEntries.length;\n\tconst tokensBefore = estimateLegacyProjectedContextTokens(projection, pathEntries).tokens;\n\tconst previousRetainedTail =\n\t\tprevCompactionIndex >= 0\n\t\t\t? getLegacyRetainedTailForCompaction(pathEntries[prevCompactionIndex] as LegacyCompactionEntry)\n\t\t\t: [];\n\n\tconst forcedFirstKeptEntryIndex = options.firstKeptEntryId\n\t\t? projectedEntries.findIndex((entry) => entry.sourceEntry.id === options.firstKeptEntryId)\n\t\t: -1;\n\tif (\n\t\toptions.firstKeptEntryId &&\n\t\t(forcedFirstKeptEntryIndex < boundaryStart || forcedFirstKeptEntryIndex >= boundaryEnd)\n\t) {\n\t\treturn err(new CompactionError(\"invalid_session\", \"Forced first kept entry was not found\"));\n\t}\n\tconst cutPoint =\n\t\tforcedFirstKeptEntryIndex >= boundaryStart && forcedFirstKeptEntryIndex < boundaryEnd\n\t\t\t? { firstKeptEntryIndex: forcedFirstKeptEntryIndex, turnStartIndex: -1, isSplitTurn: false }\n\t\t\t: findLegacyProjectedCutPoint(projectedEntries, boundaryStart, boundaryEnd, settings.keepRecentTokens);\n\tconst firstKeptEntry = projectedEntries[cutPoint.firstKeptEntryIndex]?.sourceEntry;\n\tif (!firstKeptEntry?.id) {\n\t\treturn err(new CompactionError(\"invalid_session\", \"First kept entry has no UUID - session may need migration\"));\n\t}\n\n\tconst historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;\n\tconst messagesToSummarize = [\n\t\t...previousRetainedTail,\n\t\t...projectedEntries.slice(boundaryStart, historyEnd).flatMap(getLegacyProjectedMessagesForCompaction),\n\t];\n\tconst cachePrefixMessages = projectedEntries.slice(0, historyEnd).flatMap((entry) => entry.messages);\n\tconst turnPrefixMessages = cutPoint.isSplitTurn\n\t\t? projectedEntries\n\t\t\t\t.slice(cutPoint.turnStartIndex, cutPoint.firstKeptEntryIndex)\n\t\t\t\t.flatMap(getLegacyProjectedMessagesForCompaction)\n\t\t: [];\n\tconst retainedTail = projectedEntries\n\t\t.slice(cutPoint.firstKeptEntryIndex, boundaryEnd)\n\t\t.flatMap(getLegacyProjectedMessagesForCompaction);\n\tif (messagesToSummarize.length === 0 && turnPrefixMessages.length === 0) return ok(undefined);\n\tconst fileOps = extractLegacyFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (const message of turnPrefixMessages) extractFileOpsFromMessage(message, fileOps);\n\t}\n\n\treturn ok({\n\t\tfirstKeptEntryId: firstKeptEntry.id,\n\t\tcachePrefixMessages,\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn: cutPoint.isSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t});\n}\n\nconst TURN_PREFIX_SUMMARIZATION_PROMPT = `This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.`;\n\nconst UPDATE_TURN_PREFIX_SUMMARIZATION_PROMPT = `The messages above are the next part of the same oversized turn prefix.\n\nUpdate the existing turn-prefix summary in <previous-summary> tags. Keep the same sections:\n\n## Original Request\n## Early Progress\n## Context for Suffix\n\nBe concise. Preserve exact file paths, function names, and error messages.`;\n\nexport { serializeConversation } from \"./utils.ts\";\n\n/** Generate compaction summary data from prepared session history. */\nexport function compact(\n\tpreparation: CompactionPreparation,\n\tmodels: Models,\n\tmodel: Model<Api>,\n\tcustomInstructions: string | undefined,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tretry: RetryPolicy | undefined,\n\tcallbacks: RetryCallbacks | undefined,\n\tcontext: Context,\n): Promise<Result<CompactResult, CompactionError>> {\n\treturn compactWithRequest(\n\t\tpreparation,\n\t\t{ model, customInstructions, thinkingLevel },\n\t\t(aiContext, options, requestContext) =>\n\t\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext),\n\t\tcontext,\n\t);\n}\n\nexport interface CompactGenerationOptions {\n\tmodel: Model<Api>;\n\tcustomInstructions?: string;\n\tthinkingLevel?: ThinkingLevel;\n\tcacheContext?: AiContext;\n\tcacheOptions?: CompactionCacheRequestOptions;\n\tcacheFallbackReason?: string;\n}\n\n/** Generate compaction data through a caller-owned boundary for each provider request. */\nexport async function compactWithRequest(\n\tpreparation: CompactionPreparation,\n\toptions: CompactGenerationOptions,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<CompactResult, CompactionError>> {\n\tconst { model, customInstructions, thinkingLevel, cacheContext, cacheOptions } = options;\n\tconst {\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t} = preparation;\n\n\tlet summary: string;\n\tlet summaryUsage: Usage;\n\tlet cachePath: CompactionDetails[\"cachePath\"] = {\n\t\tmode: \"chunked\",\n\t\treason: isSplitTurn ? \"split_turn\" : (options.cacheFallbackReason ?? \"cache_context_unavailable\"),\n\t};\n\tconst requestWithRetries: SummaryRequest = (aiContext, requestOptions, requestContext, preservePromptCache) =>\n\t\trequest(aiContext, requestOptions, requestContext, preservePromptCache);\n\n\tif (isSplitTurn && turnPrefixMessages.length > 0) {\n\t\tlet historyText = \"No prior history.\";\n\t\tlet historyUsage: Usage | undefined;\n\t\tif (messagesToSummarize.length > 0) {\n\t\t\tconst historyResult = await generateSummaryWithRequest(\n\t\t\t\tmessagesToSummarize,\n\t\t\t\t{ model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel },\n\t\t\t\trequest,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tif (!historyResult.ok) return err(historyResult.error);\n\t\t\thistoryText = historyResult.value.text;\n\t\t\thistoryUsage = historyResult.value.usage;\n\t\t}\n\t\tconst turnPrefixResult = await generateTurnPrefixSummary(\n\t\t\tturnPrefixMessages,\n\t\t\tmodel,\n\t\t\tsettings.reserveTokens,\n\t\t\tthinkingLevel,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!turnPrefixResult.ok) return err(turnPrefixResult.error);\n\t\tsummary = `${historyText}\\n\\n---\\n\\n**Turn Context (split turn):**\\n\\n${turnPrefixResult.value.text}`;\n\t\tsummaryUsage = historyUsage ? addUsage(historyUsage, turnPrefixResult.value.usage) : turnPrefixResult.value.usage;\n\t} else {\n\t\tconst prefixResult =\n\t\t\tcacheContext && cacheOptions\n\t\t\t\t? await summarizeCachePrefix(\n\t\t\t\t\t\tpreparation,\n\t\t\t\t\t\tcacheContext,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tsettings.reserveTokens,\n\t\t\t\t\t\tcustomInstructions,\n\t\t\t\t\t\tpreviousSummary,\n\t\t\t\t\t\tthinkingLevel,\n\t\t\t\t\t\trequestWithRetries,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tcacheOptions,\n\t\t\t\t\t)\n\t\t\t\t: { kind: \"unavailable\" as const, reason: options.cacheFallbackReason ?? \"cache_context_unavailable\" };\n\t\tif (prefixResult.kind === \"error\") return err(prefixResult.error);\n\t\tif (prefixResult.kind === \"summary\") {\n\t\t\tsummary = prefixResult.value.text;\n\t\t\tsummaryUsage = prefixResult.value.usage;\n\t\t\tcachePath = { mode: \"exact_prefix\", reason: \"provider_prefix_request\" };\n\t\t} else {\n\t\t\tconst summaryResult = await generateSummaryWithRequest(\n\t\t\t\tmessagesToSummarize,\n\t\t\t\t{ model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel },\n\t\t\t\trequestWithRetries,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tif (!summaryResult.ok) return err(summaryResult.error);\n\t\t\tsummary = summaryResult.value.text;\n\t\t\tsummaryUsage = summaryResult.value.usage;\n\t\t\tif (prefixResult.kind === \"overflow\") {\n\t\t\t\tcachePath = { mode: \"chunked\", reason: \"provider_context_overflow\" };\n\t\t\t} else {\n\t\t\t\tcachePath = { mode: \"chunked\", reason: prefixResult.reason };\n\t\t\t}\n\t\t}\n\t}\n\n\tconst { readFiles, modifiedFiles } = computeFileLists(fileOps);\n\tsummary += formatFileOperations(readFiles, modifiedFiles);\n\tconst details: CompactionDetails = { readFiles, modifiedFiles, cachePath };\n\n\treturn ok({ summary, tokensBefore, usage: summaryUsage, retainedTail, details });\n}\n\n/** Compact a pi-client/pi-server session branch and preserve its retained entry id. */\nexport async function compactLegacy(\n\tpreparation: LegacyCompactionPreparation,\n\tmodels: Models,\n\tmodel: Model<Api>,\n\tcustomInstructions?: string,\n\tsignal?: AbortSignal,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcacheContext?: AiContext,\n\tcacheOptions?: CompactionCacheRequestOptions,\n\tcacheFallbackReason?: string,\n): Promise<Result<LegacyCompactResult, CompactionError>> {\n\tconst context = signal ? withAbortSignal(signal, BACKGROUND_CONTEXT) : BACKGROUND_CONTEXT;\n\tconst request: SummaryRequest = (aiContext, options, requestContext, preservePromptCache) =>\n\t\tcompleteSimpleWithRetries(\n\t\t\tmodels,\n\t\t\tmodel,\n\t\t\taiContext,\n\t\t\toptions,\n\t\t\tretry,\n\t\t\tcallbacks,\n\t\t\trequestContext,\n\t\t\tpreservePromptCache,\n\t\t);\n\tconst result = await compactWithRequest(\n\t\tpreparation,\n\t\t{ model, customInstructions, thinkingLevel, cacheContext, cacheOptions, cacheFallbackReason },\n\t\trequest,\n\t\tcontext,\n\t);\n\treturn result.ok ? ok({ ...result.value, firstKeptEntryId: preparation.firstKeptEntryId }) : err(result.error);\n}\nasync function generateTurnPrefixSummary(\n\tmessages: AgentMessage[],\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst maxTokens = Math.min(\n\t\tMath.floor(0.5 * reserveTokens),\n\t\tmodel.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY,\n\t);\n\tconst result = await summarizeMessages(\n\t\tmessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tTURN_PREFIX_SUMMARIZATION_PROMPT,\n\t\tUPDATE_TURN_PREFIX_SUMMARIZATION_PROMPT,\n\t\tundefined,\n\t\trequest,\n\t\tcontext,\n\t);\n\tif (!result.ok && result.error.code === \"summarization_failed\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Turn prefix summarization failed: ${result.error.message.replace(/^Summarization failed: /, \"\")}`,\n\t\t\t),\n\t\t);\n\t}\n\treturn result;\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { contentText, getCurrentSystemMessage, isContextOverflow, retryAssistantCall, uuidv7, } from "@earendil-works/pi-ai";
1
+ import { contentText, getCurrentSystemMessage, isContextOverflow, normalizeContext, retryAssistantCall, uuidv7, } from "@earendil-works/pi-ai";
2
2
  import { BACKGROUND_CONTEXT, getTelemetryContext, withAbortSignal } from "../context.js";
3
3
  import { buildLegacySessionProjection, legacyEntryToContextMessages, } from "../legacy-session.js";
4
4
  import { convertToLlm, createBranchSummaryMessage, createCompactionSummaryMessage } from "../messages.js";
@@ -78,18 +78,18 @@ function extractLegacyFileOperations(messages, entries, prevCompactionIndex) {
78
78
  extractFileOpsFromMessage(message, fileOps);
79
79
  return fileOps;
80
80
  }
81
- export function createSummaryRequestOptions(options, context) {
81
+ export function createSummaryRequestOptions(options, context, preservePromptCache = false) {
82
82
  return {
83
83
  ...options,
84
84
  signal: context.abortSignal,
85
85
  telemetryContext: getTelemetryContext(context),
86
- cacheRetention: "none",
87
- sessionId: options.sessionId ?? uuidv7(),
86
+ ...(!preservePromptCache ? { cacheRetention: "none" } : {}),
87
+ sessionId: preservePromptCache ? options.sessionId : (options.sessionId ?? uuidv7()),
88
88
  };
89
89
  }
90
- export async function completeSimpleWithRetries(models, model, aiContext, options, retry, callbacks, context) {
91
- // Summaries are standalone requests, so isolate routing and avoid cache writes that cannot be reused.
92
- const requestOptions = createSummaryRequestOptions(options, context);
90
+ export async function completeSimpleWithRetries(models, model, aiContext, options, retry, callbacks, context, preservePromptCache = false) {
91
+ // Chunked and branch summaries are one-off requests. The exact-prefix compaction path opts in explicitly.
92
+ const requestOptions = createSummaryRequestOptions(options, context, preservePromptCache);
93
93
  return retryAssistantCall(() => models.completeSimple(model, aiContext, requestOptions), retry, requestOptions.signal, callbacks);
94
94
  }
95
95
  /** Default compaction settings used by the harness. */
@@ -620,6 +620,68 @@ async function summarizeMessages(messages, model, maxTokens, thinkingLevel, init
620
620
  }
621
621
  return ok({ text: summary ?? "", usage: summaryUsage });
622
622
  }
623
+ async function summarizeCachePrefix(preparation, cacheContext, model, reserveTokens, customInstructions, previousSummary, thinkingLevel, request, context, cacheOptions) {
624
+ const cachePrefixMessages = preparation.cachePrefixMessages;
625
+ if (!cachePrefixMessages)
626
+ return { kind: "unavailable", reason: "projected_prefix_unavailable" };
627
+ if (!cacheOptions.sessionId)
628
+ return { kind: "unavailable", reason: "session_id_unavailable" };
629
+ const fullContext = normalizeContext(cacheContext);
630
+ const prefixContext = normalizeContext({
631
+ systemPrompt: cacheContext.systemPrompt,
632
+ tools: cacheContext.tools,
633
+ messages: convertToLlm(cachePrefixMessages),
634
+ });
635
+ if (prefixContext.messages.length > fullContext.messages.length ||
636
+ prefixContext.messages.some((message, index) => JSON.stringify(message) !== JSON.stringify(fullContext.messages[index]))) {
637
+ return { kind: "unavailable", reason: "projected_prefix_mismatch" };
638
+ }
639
+ const maxTokens = getSummaryMaxTokens(model, reserveTokens);
640
+ let initialPrompt = SUMMARIZATION_PROMPT;
641
+ if (customInstructions) {
642
+ initialPrompt = `${initialPrompt}\n\nAdditional focus: ${customInstructions}`;
643
+ }
644
+ const prefixScope = "Summarize the conversation in the provider context above up to this instruction. That context is the canonical prefix selected by the compaction cut point; the retained tail is excluded. Do not call tools; output only the checkpoint summary. Report only observed failures. Preserve the latest exact failing assertion/error from the prior summary or transcript. Mark it resolved only if the same failing command/assertion passes or direct evidence fixes it; an unrelated later check does not resolve it. Otherwise keep the exact failure as unresolved/last known. Use (none) only when no prior or observed failure exists. Put unrun checks under Pending TODO, never Open failures.";
645
+ const instruction = previousSummary
646
+ ? `${prefixScope}\n\nA prior compaction summary appears in the provider context above inside <summary> tags. Preserve its information and update the structured summary using the conversation messages that follow it. Keep the same sections and exact file paths, function names, and error messages.\n\n${initialPrompt}`
647
+ : `${prefixScope}\n\n${initialPrompt}`;
648
+ const summaryContext = normalizeContext({
649
+ messages: [
650
+ ...prefixContext.messages,
651
+ { role: "user", content: [{ type: "text", text: instruction }], timestamp: Date.now() },
652
+ ],
653
+ });
654
+ const options = {
655
+ maxTokens,
656
+ ...(model.reasoning && thinkingLevel && thinkingLevel !== "off" ? { reasoning: thinkingLevel } : {}),
657
+ ...cacheOptions,
658
+ };
659
+ const response = await request(summaryContext, createSummaryRequestOptions(options, context, true), context, true);
660
+ if (response.stopReason === "error" && isContextOverflow(response, model.contextWindow))
661
+ return { kind: "overflow" };
662
+ if (response.stopReason === "aborted") {
663
+ return { kind: "error", error: new CompactionError("aborted", response.errorMessage || "Summarization aborted") };
664
+ }
665
+ if (response.stopReason === "error") {
666
+ return {
667
+ kind: "error",
668
+ error: new CompactionError("summarization_failed", `Summarization failed: ${response.errorMessage || "Unknown error"}`),
669
+ };
670
+ }
671
+ if (response.stopReason === "length") {
672
+ return {
673
+ kind: "error",
674
+ error: new CompactionError("summarization_failed", "Summarization failed: generation hit the token cap and the summary is incomplete"),
675
+ };
676
+ }
677
+ if (response.content.some((block) => block.type === "toolCall")) {
678
+ return {
679
+ kind: "error",
680
+ error: new CompactionError("summarization_failed", "Summarization attempted to call a tool"),
681
+ };
682
+ }
683
+ return { kind: "summary", value: { text: contentText(response.content), usage: response.usage } };
684
+ }
623
685
  /** Generate or update a conversation summary for compaction. */
624
686
  export async function generateSummary(currentMessages, models, model, reserveTokens, customInstructions, previousSummary, thinkingLevel, retry, callbacks, context = BACKGROUND_CONTEXT) {
625
687
  const result = await generateSummaryWithUsage(currentMessages, models, model, reserveTokens, customInstructions, previousSummary, thinkingLevel, retry, callbacks, context);
@@ -664,13 +726,13 @@ export function prepareCompaction(pathEntries, settings) {
664
726
  let previousSummary;
665
727
  let compactableEntries = pathEntries;
666
728
  if (prevCompactionIndex >= 0) {
667
- const prevCompaction = pathEntries[prevCompactionIndex];
668
- previousSummary = prevCompaction.summary;
669
- const virtualRetainedEntries = prevCompaction.retainedTail.map((message, index) => ({
729
+ const previousCompaction = pathEntries[prevCompactionIndex];
730
+ previousSummary = previousCompaction.summary;
731
+ const virtualRetainedEntries = previousCompaction.retainedTail.map((message, index) => ({
670
732
  type: "message",
671
- id: `${prevCompaction.id}:retained:${index}`,
672
- parentId: index === 0 ? prevCompaction.id : `${prevCompaction.id}:retained:${index - 1}`,
673
- seq: prevCompaction.seq,
733
+ id: `${previousCompaction.id}:retained:${index}`,
734
+ parentId: index === 0 ? previousCompaction.id : `${previousCompaction.id}:retained:${index - 1}`,
735
+ seq: previousCompaction.seq,
674
736
  timestamp: message.timestamp,
675
737
  message,
676
738
  }));
@@ -700,6 +762,30 @@ export function prepareCompaction(pathEntries, settings) {
700
762
  if (msg)
701
763
  retainedTail.push(msg);
702
764
  }
765
+ const cachePrefixMessages = [];
766
+ if (prevCompactionIndex >= 0) {
767
+ const previousCompaction = pathEntries[prevCompactionIndex];
768
+ cachePrefixMessages.push(createCompactionSummaryMessage(previousCompaction.summary, previousCompaction.tokensBefore, previousCompaction.timestamp));
769
+ const previousRetainedCount = Math.min(historyEnd, previousCompaction.retainedTail.length);
770
+ for (let i = 0; i < previousRetainedCount; i++) {
771
+ const message = previousCompaction.retainedTail[i];
772
+ if (message)
773
+ cachePrefixMessages.push(message);
774
+ }
775
+ const newHistoryEnd = Math.max(0, historyEnd - previousCompaction.retainedTail.length);
776
+ for (const entry of pathEntries.slice(prevCompactionIndex + 1, prevCompactionIndex + 1 + newHistoryEnd)) {
777
+ const message = getMessageFromEntryForCompaction(entry);
778
+ if (message)
779
+ cachePrefixMessages.push(message);
780
+ }
781
+ }
782
+ else {
783
+ for (const entry of pathEntries.slice(0, historyEnd)) {
784
+ const message = getMessageFromEntryForCompaction(entry);
785
+ if (message)
786
+ cachePrefixMessages.push(message);
787
+ }
788
+ }
703
789
  const fileOps = extractFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);
704
790
  if (cutPoint.isSplitTurn) {
705
791
  for (const msg of turnPrefixMessages) {
@@ -707,6 +793,7 @@ export function prepareCompaction(pathEntries, settings) {
707
793
  }
708
794
  }
709
795
  return ok({
796
+ cachePrefixMessages,
710
797
  messagesToSummarize,
711
798
  turnPrefixMessages,
712
799
  retainedTail,
@@ -806,6 +893,7 @@ export function prepareLegacyCompaction(pathEntries, settings, options = {}) {
806
893
  ...previousRetainedTail,
807
894
  ...projectedEntries.slice(boundaryStart, historyEnd).flatMap(getLegacyProjectedMessagesForCompaction),
808
895
  ];
896
+ const cachePrefixMessages = projectedEntries.slice(0, historyEnd).flatMap((entry) => entry.messages);
809
897
  const turnPrefixMessages = cutPoint.isSplitTurn
810
898
  ? projectedEntries
811
899
  .slice(cutPoint.turnStartIndex, cutPoint.firstKeptEntryIndex)
@@ -823,6 +911,7 @@ export function prepareLegacyCompaction(pathEntries, settings, options = {}) {
823
911
  }
824
912
  return ok({
825
913
  firstKeptEntryId: firstKeptEntry.id,
914
+ cachePrefixMessages,
826
915
  messagesToSummarize,
827
916
  turnPrefixMessages,
828
917
  retainedTail,
@@ -863,10 +952,15 @@ export function compact(preparation, models, model, customInstructions, thinking
863
952
  }
864
953
  /** Generate compaction data through a caller-owned boundary for each provider request. */
865
954
  export async function compactWithRequest(preparation, options, request, context) {
866
- const { model, customInstructions, thinkingLevel } = options;
955
+ const { model, customInstructions, thinkingLevel, cacheContext, cacheOptions } = options;
867
956
  const { messagesToSummarize, turnPrefixMessages, retainedTail, isSplitTurn, tokensBefore, previousSummary, fileOps, settings, } = preparation;
868
957
  let summary;
869
958
  let summaryUsage;
959
+ let cachePath = {
960
+ mode: "chunked",
961
+ reason: isSplitTurn ? "split_turn" : (options.cacheFallbackReason ?? "cache_context_unavailable"),
962
+ };
963
+ const requestWithRetries = (aiContext, requestOptions, requestContext, preservePromptCache) => request(aiContext, requestOptions, requestContext, preservePromptCache);
870
964
  if (isSplitTurn && turnPrefixMessages.length > 0) {
871
965
  let historyText = "No prior history.";
872
966
  let historyUsage;
@@ -884,22 +978,40 @@ export async function compactWithRequest(preparation, options, request, context)
884
978
  summaryUsage = historyUsage ? addUsage(historyUsage, turnPrefixResult.value.usage) : turnPrefixResult.value.usage;
885
979
  }
886
980
  else {
887
- const summaryResult = await generateSummaryWithRequest(messagesToSummarize, { model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel }, request, context);
888
- if (!summaryResult.ok)
889
- return err(summaryResult.error);
890
- summary = summaryResult.value.text;
891
- summaryUsage = summaryResult.value.usage;
981
+ const prefixResult = cacheContext && cacheOptions
982
+ ? await summarizeCachePrefix(preparation, cacheContext, model, settings.reserveTokens, customInstructions, previousSummary, thinkingLevel, requestWithRetries, context, cacheOptions)
983
+ : { kind: "unavailable", reason: options.cacheFallbackReason ?? "cache_context_unavailable" };
984
+ if (prefixResult.kind === "error")
985
+ return err(prefixResult.error);
986
+ if (prefixResult.kind === "summary") {
987
+ summary = prefixResult.value.text;
988
+ summaryUsage = prefixResult.value.usage;
989
+ cachePath = { mode: "exact_prefix", reason: "provider_prefix_request" };
990
+ }
991
+ else {
992
+ const summaryResult = await generateSummaryWithRequest(messagesToSummarize, { model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel }, requestWithRetries, context);
993
+ if (!summaryResult.ok)
994
+ return err(summaryResult.error);
995
+ summary = summaryResult.value.text;
996
+ summaryUsage = summaryResult.value.usage;
997
+ if (prefixResult.kind === "overflow") {
998
+ cachePath = { mode: "chunked", reason: "provider_context_overflow" };
999
+ }
1000
+ else {
1001
+ cachePath = { mode: "chunked", reason: prefixResult.reason };
1002
+ }
1003
+ }
892
1004
  }
893
1005
  const { readFiles, modifiedFiles } = computeFileLists(fileOps);
894
1006
  summary += formatFileOperations(readFiles, modifiedFiles);
895
- const details = { readFiles, modifiedFiles };
1007
+ const details = { readFiles, modifiedFiles, cachePath };
896
1008
  return ok({ summary, tokensBefore, usage: summaryUsage, retainedTail, details });
897
1009
  }
898
1010
  /** Compact a pi-client/pi-server session branch and preserve its retained entry id. */
899
- export async function compactLegacy(preparation, models, model, customInstructions, signal, thinkingLevel, retry, callbacks) {
1011
+ export async function compactLegacy(preparation, models, model, customInstructions, signal, thinkingLevel, retry, callbacks, cacheContext, cacheOptions, cacheFallbackReason) {
900
1012
  const context = signal ? withAbortSignal(signal, BACKGROUND_CONTEXT) : BACKGROUND_CONTEXT;
901
- const request = (aiContext, options, requestContext) => completeSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext);
902
- const result = await compactWithRequest(preparation, { model, customInstructions, thinkingLevel }, request, context);
1013
+ const request = (aiContext, options, requestContext, preservePromptCache) => completeSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext, preservePromptCache);
1014
+ const result = await compactWithRequest(preparation, { model, customInstructions, thinkingLevel, cacheContext, cacheOptions, cacheFallbackReason }, request, context);
903
1015
  return result.ok ? ok({ ...result.value, firstKeptEntryId: preparation.firstKeptEntryId }) : err(result.error);
904
1016
  }
905
1017
  async function generateTurnPrefixSummary(messages, model, reserveTokens, thinkingLevel, request, context) {
@@ -1 +1 @@
1
- {"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/harness/compaction/compaction.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Context as AiContext,\n\ttype Api,\n\ttype AssistantMessage,\n\tcontentText,\n\tgetCurrentSystemMessage,\n\tisContextOverflow,\n\ttype Model,\n\ttype Models,\n\ttype RetryCallbacks,\n\ttype RetryPolicy,\n\tretryAssistantCall,\n\ttype SimpleStreamOptions,\n\ttype SystemMessage,\n\ttype Usage,\n\tuuidv7,\n} from \"@earendil-works/pi-ai\";\nimport type { AgentMessage, ThinkingLevel } from \"../../types.ts\";\nimport { BACKGROUND_CONTEXT, type Context, getTelemetryContext, withAbortSignal } from \"../context.ts\";\nimport {\n\tbuildLegacySessionProjection,\n\ttype LegacyCompactionEntry,\n\ttype LegacyProjectedSessionEntry,\n\tlegacyEntryToContextMessages,\n\ttype SessionTreeEntry,\n} from \"../legacy-session.ts\";\nimport { convertToLlm, createBranchSummaryMessage, createCompactionSummaryMessage } from \"../messages.ts\";\nimport { buildContextEntries, sessionEntryToContextMessages } from \"../session/context.ts\";\nimport type { CompactionEntry, Entry, JsonValue } from \"../session/types.ts\";\nimport { CompactionError, err, ok, type Result } from \"../types.ts\";\nimport { addUsage } from \"../utils/usage.ts\";\nimport {\n\tcomputeFileLists,\n\tcreateFileOps,\n\textractFileOpsFromMessage,\n\ttype FileOperations,\n\tformatFileOperations,\n\tserializeConversation,\n} from \"./utils.ts\";\n\n/** File-operation details stored on generated compaction entries. */\nexport interface CompactionDetails extends Record<string, JsonValue> {\n\t/** Files read in the compacted history. */\n\treadFiles: string[];\n\t/** Files modified in the compacted history. */\n\tmodifiedFiles: string[];\n}\nfunction safeJsonStringify(value: unknown): string {\n\ttry {\n\t\treturn JSON.stringify(value) ?? \"undefined\";\n\t} catch {\n\t\treturn \"[unserializable]\";\n\t}\n}\n\nfunction extractFileOperations(\n\tmessages: AgentMessage[],\n\tentries: Entry[],\n\tprevCompactionIndex: number,\n): FileOperations {\n\tconst fileOps = createFileOps();\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = entries[prevCompactionIndex] as CompactionEntry;\n\t\tif (\n\t\t\ttypeof prevCompaction.details === \"object\" &&\n\t\t\tprevCompaction.details !== null &&\n\t\t\t!Array.isArray(prevCompaction.details)\n\t\t) {\n\t\t\tif (Array.isArray(prevCompaction.details.readFiles)) {\n\t\t\t\tfor (const path of prevCompaction.details.readFiles) {\n\t\t\t\t\tif (typeof path === \"string\") fileOps.read.add(path);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Array.isArray(prevCompaction.details.modifiedFiles)) {\n\t\t\t\tfor (const path of prevCompaction.details.modifiedFiles) {\n\t\t\t\t\tif (typeof path === \"string\") fileOps.edited.add(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (const msg of messages) {\n\t\textractFileOpsFromMessage(msg, fileOps);\n\t}\n\n\treturn fileOps;\n}\nfunction getMessageFromEntry(entry: Entry): AgentMessage | undefined {\n\tif (entry.type === \"message\") {\n\t\treturn entry.message as AgentMessage;\n\t}\n\tif (entry.type === \"branch_summary\") {\n\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\t}\n\tif (entry.type === \"compaction\") {\n\t\treturn createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp);\n\t}\n\treturn undefined;\n}\n\nfunction getMessageFromEntryForCompaction(entry: Entry): AgentMessage | undefined {\n\tif (entry.type === \"compaction\") {\n\t\treturn undefined;\n\t}\n\treturn getMessageFromEntry(entry);\n}\n\nfunction extractLegacyFileOperations(\n\tmessages: AgentMessage[],\n\tentries: SessionTreeEntry[],\n\tprevCompactionIndex: number,\n): FileOperations {\n\tconst fileOps = createFileOps();\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = entries[prevCompactionIndex] as LegacyCompactionEntry;\n\t\tif (!prevCompaction.fromHook && prevCompaction.details) {\n\t\t\tconst details = prevCompaction.details as CompactionDetails;\n\t\t\tif (Array.isArray(details.readFiles)) {\n\t\t\t\tfor (const file of details.readFiles) fileOps.read.add(file);\n\t\t\t}\n\t\t\tif (Array.isArray(details.modifiedFiles)) {\n\t\t\t\tfor (const file of details.modifiedFiles) fileOps.edited.add(file);\n\t\t\t}\n\t\t}\n\t}\n\tfor (const message of messages) extractFileOpsFromMessage(message, fileOps);\n\treturn fileOps;\n}\n\n/** Generated compaction data ready to be persisted as a compaction entry. */\nexport interface CompactResult<T = JsonValue> {\n\t/** Summary text that replaces compacted history in future context. */\n\tsummary: string;\n\t/** Estimated context tokens before compaction. */\n\ttokensBefore: number;\n\t/** Usage from the LLM call(s) that generated this summary, if available. */\n\tusage?: Usage;\n\t/** Retained recent messages stored directly on the compaction entry. */\n\tretainedTail: AgentMessage[];\n\t/** Optional implementation-specific details stored with the compaction entry. */\n\tdetails?: T;\n}\n\n/** Compaction result used by the pi-client/pi-server session-tree protocol. */\nexport interface LegacyCompactResult<T = unknown> extends CompactResult<T> {\n\t/** Entry id where retained history starts. */\n\tfirstKeptEntryId: string;\n}\n\nexport type SummaryRequest = (\n\taiContext: AiContext,\n\toptions: SimpleStreamOptions,\n\tcontext: Context,\n) => Promise<AssistantMessage>;\n\nexport function createSummaryRequestOptions(options: SimpleStreamOptions, context: Context): SimpleStreamOptions {\n\treturn {\n\t\t...options,\n\t\tsignal: context.abortSignal,\n\t\ttelemetryContext: getTelemetryContext(context),\n\t\tcacheRetention: \"none\",\n\t\tsessionId: options.sessionId ?? uuidv7(),\n\t};\n}\n\nexport async function completeSimpleWithRetries(\n\tmodels: Models,\n\tmodel: Model<Api>,\n\taiContext: AiContext,\n\toptions: SimpleStreamOptions,\n\tretry: RetryPolicy | undefined,\n\tcallbacks: RetryCallbacks | undefined,\n\tcontext: Context,\n): Promise<AssistantMessage> {\n\t// Summaries are standalone requests, so isolate routing and avoid cache writes that cannot be reused.\n\tconst requestOptions = createSummaryRequestOptions(options, context);\n\treturn retryAssistantCall(\n\t\t() => models.completeSimple(model, aiContext, requestOptions),\n\t\tretry,\n\t\trequestOptions.signal,\n\t\tcallbacks,\n\t);\n}\n\n/** Compaction thresholds and retention settings. */\nexport interface CompactionSettings {\n\t/** Enable automatic compaction decisions. */\n\tenabled: boolean;\n\t/** Tokens reserved for summary prompt and output. */\n\treserveTokens: number;\n\t/** Approximate recent-context tokens to keep after compaction. */\n\tkeepRecentTokens: number;\n}\n\n/** Default compaction settings used by the harness. */\nexport const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tkeepRecentTokens: 20000,\n};\n\n/** Calculate total context tokens from provider usage. */\nexport function calculateContextTokens(usage: Usage): number {\n\treturn usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;\n}\nfunction getAssistantUsage(msg: AgentMessage): Usage | undefined {\n\tif (msg.role === \"assistant\" && \"usage\" in msg) {\n\t\tconst assistantMsg = msg as AssistantMessage;\n\t\tif (\n\t\t\tassistantMsg.stopReason !== \"aborted\" &&\n\t\t\tassistantMsg.stopReason !== \"error\" &&\n\t\t\tassistantMsg.usage &&\n\t\t\tcalculateContextTokens(assistantMsg.usage) > 0\n\t\t) {\n\t\t\treturn assistantMsg.usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Return usage from the last valid assistant message in session entries. */\nexport function getLastAssistantUsage(entries: Entry[]): Usage | undefined {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"message\") {\n\t\t\tconst usage = getAssistantUsage(entry.message as AgentMessage);\n\t\t\tif (usage) return usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Estimated context-token usage for a message list. */\nexport interface ContextUsageEstimate {\n\t/** Estimated total context tokens. */\n\ttokens: number;\n\t/** Tokens reported by the most recent assistant usage block. */\n\tusageTokens: number;\n\t/** Estimated tokens after the most recent assistant usage block. */\n\ttrailingTokens: number;\n\t/** Index of the message that provided usage, or null when none exists. */\n\tlastUsageIndex: number | null;\n}\n\nfunction getLastAssistantUsageInfo(messages: AgentMessage[]): { usage: Usage; index: number } | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst usage = getAssistantUsage(messages[i]);\n\t\tif (usage) return { usage, index: i };\n\t}\n\treturn undefined;\n}\n\n/** Estimate context tokens for messages using provider usage when available. */\nexport function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\n\tif (!usageInfo) {\n\t\tlet estimated = 0;\n\t\tfor (const message of messages) {\n\t\t\testimated += estimateTokens(message);\n\t\t}\n\t\treturn {\n\t\t\ttokens: estimated,\n\t\t\tusageTokens: 0,\n\t\t\ttrailingTokens: estimated,\n\t\t\tlastUsageIndex: null,\n\t\t};\n\t}\n\n\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\tlet trailingTokens = 0;\n\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\ttrailingTokens += estimateTokens(messages[i]);\n\t}\n\n\treturn {\n\t\ttokens: usageTokens + trailingTokens,\n\t\tusageTokens,\n\t\ttrailingTokens,\n\t\tlastUsageIndex: usageInfo.index,\n\t};\n}\n\n/** Return whether context usage exceeds the configured compaction threshold. */\nexport function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {\n\tif (!settings.enabled) return false;\n\treturn contextTokens > contextWindow - settings.reserveTokens;\n}\n\nconst ESTIMATED_IMAGE_CHARS = 4800;\n\nfunction estimateTextAndImageContentChars(content: string | Array<{ type: string; text?: string }>): number {\n\tif (typeof content === \"string\") {\n\t\treturn content.length;\n\t}\n\n\tlet chars = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"text\" && block.text) {\n\t\t\tchars += block.text.length;\n\t\t} else if (block.type === \"image\") {\n\t\t\tchars += ESTIMATED_IMAGE_CHARS;\n\t\t}\n\t}\n\treturn chars;\n}\n\n/** Estimate token count for one message using a conservative character heuristic. */\nexport function estimateTokens(message: AgentMessage): number {\n\tlet chars = 0;\n\n\tswitch (message.role) {\n\t\tcase \"system\": {\n\t\t\tconst system = message as SystemMessage;\n\t\t\tchars = estimateTextAndImageContentChars(system.content);\n\t\t\tif (system.sections) {\n\t\t\t\tfor (const section of Object.values(system.sections)) {\n\t\t\t\t\tif (section) chars += section.length;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (system.toolsAdded) chars += safeJsonStringify(system.toolsAdded).length;\n\t\t\tif (system.toolsRemoved) chars += safeJsonStringify(system.toolsRemoved).length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"user\": {\n\t\t\tchars = estimateTextAndImageContentChars(\n\t\t\t\t(message as { content: string | Array<{ type: string; text?: string }> }).content,\n\t\t\t);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"assistant\": {\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\tfor (const block of assistant.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tchars += block.text.length;\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tchars += block.thinking.length;\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tchars += block.name.length + safeJsonStringify(block.arguments).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"custom\":\n\t\tcase \"toolResult\": {\n\t\t\tchars = estimateTextAndImageContentChars(message.content);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"bashExecution\": {\n\t\t\tchars = message.command.length + message.output.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\": {\n\t\t\tchars = message.summary.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t}\n\n\treturn 0;\n}\nfunction findValidCutPoints(entries: Entry[], startIndex: number, endIndex: number): number[] {\n\tconst cutPoints: number[] = [];\n\tfor (let i = startIndex; i < endIndex; i++) {\n\t\tconst entry = entries[i];\n\t\tswitch (entry.type) {\n\t\t\tcase \"message\": {\n\t\t\t\tconst role = entry.message.role;\n\t\t\t\tswitch (role) {\n\t\t\t\t\tcase \"bashExecution\":\n\t\t\t\t\tcase \"custom\":\n\t\t\t\t\tcase \"branchSummary\":\n\t\t\t\t\tcase \"compactionSummary\":\n\t\t\t\t\tcase \"user\":\n\t\t\t\t\tcase \"assistant\":\n\t\t\t\t\t\tcutPoints.push(i);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"toolResult\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"compaction\":\n\t\t\tcase \"branch_summary\":\n\t\t\tcase \"custom\":\n\t\t\t\tbreak;\n\t\t}\n\t\tif (entry.type === \"branch_summary\") cutPoints.push(i);\n\t}\n\treturn cutPoints;\n}\n\n/** Find the user-visible message that starts the turn containing an entry. */\nexport function findTurnStartIndex(entries: Entry[], entryIndex: number, startIndex: number): number {\n\tfor (let i = entryIndex; i >= startIndex; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"branch_summary\") {\n\t\t\treturn i;\n\t\t}\n\t\tif (entry.type === \"message\") {\n\t\t\tconst role = entry.message.role;\n\t\t\tif (role === \"user\" || role === \"bashExecution\") {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t}\n\treturn -1;\n}\n\n/** Cut point selected for compaction. */\nexport interface CutPointResult {\n\t/** Index of the first entry retained after compaction. */\n\tfirstKeptEntryIndex: number;\n\t/** Index of the turn-start entry when the cut splits a turn, otherwise -1. */\n\tturnStartIndex: number;\n\t/** Whether the selected cut point splits an in-progress turn. */\n\tisSplitTurn: boolean;\n}\n\n/** Find the compaction cut point that keeps approximately the requested recent-token budget. */\nexport function findCutPoint(\n\tentries: Entry[],\n\tstartIndex: number,\n\tendIndex: number,\n\tkeepRecentTokens: number,\n): CutPointResult {\n\tconst cutPoints = findValidCutPoints(entries, startIndex, endIndex);\n\n\tif (cutPoints.length === 0) {\n\t\treturn { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };\n\t}\n\tlet accumulatedTokens = 0;\n\tlet cutIndex = cutPoints[0];\n\n\tfor (let i = endIndex - 1; i >= startIndex; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type !== \"message\") continue;\n\t\tconst messageTokens = estimateTokens(entry.message as AgentMessage);\n\t\taccumulatedTokens += messageTokens;\n\t\tif (accumulatedTokens >= keepRecentTokens) {\n\t\t\tfor (let c = 0; c < cutPoints.length; c++) {\n\t\t\t\tif (cutPoints[c] >= i) {\n\t\t\t\t\tcutIndex = cutPoints[c];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\twhile (cutIndex > startIndex) {\n\t\tconst prevEntry = entries[cutIndex - 1];\n\t\tif (prevEntry.type === \"compaction\") {\n\t\t\tbreak;\n\t\t}\n\t\tif (prevEntry.type === \"message\") {\n\t\t\tbreak;\n\t\t}\n\t\tcutIndex--;\n\t}\n\tconst cutEntry = entries[cutIndex];\n\tconst isUserMessage = cutEntry.type === \"message\" && cutEntry.message.role === \"user\";\n\tconst turnStartIndex = isUserMessage ? -1 : findTurnStartIndex(entries, cutIndex, startIndex);\n\n\treturn {\n\t\tfirstKeptEntryIndex: cutIndex,\n\t\tturnStartIndex,\n\t\tisSplitTurn: !isUserMessage && turnStartIndex !== -1,\n\t};\n}\n\nfunction isLegacyProjectionCutPointMessage(message: AgentMessage): boolean {\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"assistant\":\n\t\tcase \"bashExecution\":\n\t\tcase \"custom\":\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn true;\n\t\tcase \"toolResult\":\n\t\tcase \"system\":\n\t\t\treturn false;\n\t}\n}\n\nfunction isLegacyProjectionTurnStartMessage(message: AgentMessage): boolean {\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"bashExecution\":\n\t\tcase \"custom\":\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn true;\n\t\tcase \"assistant\":\n\t\tcase \"toolResult\":\n\t\tcase \"system\":\n\t\t\treturn false;\n\t}\n}\n\nfunction findLegacyProjectedValidCutPoints(\n\tentries: LegacyProjectedSessionEntry[],\n\tstartIndex: number,\n\tendIndex: number,\n): number[] {\n\tconst cutPoints: number[] = [];\n\tfor (let index = startIndex; index < endIndex; index++) {\n\t\tconst entry = entries[index];\n\t\tif (entry.sourceEntry.type !== \"compaction\" && entry.messages.some(isLegacyProjectionCutPointMessage)) {\n\t\t\tcutPoints.push(index);\n\t\t}\n\t}\n\treturn cutPoints;\n}\n\nfunction findLegacyProjectedTurnStartIndex(\n\tentries: LegacyProjectedSessionEntry[],\n\tentryIndex: number,\n\tstartIndex: number,\n): number {\n\tfor (let index = entryIndex; index >= startIndex; index--) {\n\t\tif (entries[index].messages.some(isLegacyProjectionTurnStartMessage)) return index;\n\t}\n\treturn -1;\n}\n\nfunction findLegacyProjectedCutPoint(\n\tentries: LegacyProjectedSessionEntry[],\n\tstartIndex: number,\n\tendIndex: number,\n\tkeepRecentTokens: number,\n): CutPointResult {\n\tconst cutPoints = findLegacyProjectedValidCutPoints(entries, startIndex, endIndex);\n\tif (cutPoints.length === 0) {\n\t\treturn { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };\n\t}\n\n\tlet accumulatedTokens = 0;\n\tlet exceededBudget = false;\n\tlet cutIndex = cutPoints[0];\n\tfor (let index = endIndex - 1; index >= startIndex; index--) {\n\t\tconst messageTokens = entries[index].messages.reduce((sum, message) => sum + estimateTokens(message), 0);\n\t\tif (messageTokens === 0) continue;\n\t\taccumulatedTokens += messageTokens;\n\t\tif (accumulatedTokens >= keepRecentTokens) {\n\t\t\texceededBudget = true;\n\t\t\tcutIndex = cutPoints.find((candidate) => candidate >= index) ?? cutPoints[cutPoints.length - 1];\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// A completed recovery attempt and its omission edits are context-invisible after\n\t// the last visible input. Advance past that closed suffix without skipping a\n\t// replacement edit for a visible input.\n\tconst suffix = entries.slice(cutIndex + 1, endIndex);\n\tconst isIntrinsicallyVisible = (entry: LegacyProjectedSessionEntry): boolean =>\n\t\tentry.sourceEntry.type !== \"context_edit\" && legacyEntryToContextMessages(entry.sourceEntry).length > 0;\n\tconst isOmitted = (entry: LegacyProjectedSessionEntry): boolean =>\n\t\tisIntrinsicallyVisible(entry) && entry.messages.length === 0;\n\tconst omittedSuffixIds = new Set(suffix.filter(isOmitted).map((entry) => entry.sourceEntry.id));\n\tconst hasExternalReplacement = suffix.some(\n\t\t(entry) =>\n\t\t\tentry.sourceEntry.type === \"context_edit\" &&\n\t\t\tentry.sourceEntry.replacement !== null &&\n\t\t\t!omittedSuffixIds.has(entry.sourceEntry.targetId),\n\t);\n\tconst isRecoveryOmissionSuffix =\n\t\texceededBudget &&\n\t\t!hasExternalReplacement &&\n\t\tsuffix.some(\n\t\t\t(entry) =>\n\t\t\t\tentry.sourceEntry.type === \"message\" && entry.sourceEntry.message.role === \"assistant\" && isOmitted(entry),\n\t\t) &&\n\t\tsuffix.every(\n\t\t\t(entry) => entry.sourceEntry.type !== \"compaction\" && (!isIntrinsicallyVisible(entry) || isOmitted(entry)),\n\t\t);\n\tif (isRecoveryOmissionSuffix) cutIndex++;\n\n\twhile (cutIndex > startIndex) {\n\t\tconst previousEntry = entries[cutIndex - 1];\n\t\tif (previousEntry.sourceEntry.type === \"compaction\" || previousEntry.messages.length > 0) break;\n\t\tcutIndex--;\n\t}\n\tconst startsTurn = entries[cutIndex].messages.some(isLegacyProjectionTurnStartMessage);\n\tconst turnStartIndex = startsTurn ? -1 : findLegacyProjectedTurnStartIndex(entries, cutIndex, startIndex);\n\treturn {\n\t\tfirstKeptEntryIndex: cutIndex,\n\t\tturnStartIndex,\n\t\tisSplitTurn: !startsTurn && turnStartIndex !== -1,\n\t};\n}\n\nexport const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;\n\nconst SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.\n\nUse this EXACT format:\n\n## Goal\n[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]\n\n## Constraints & Preferences\n- [Any constraints, preferences, or requirements mentioned by user]\n- [Or \"(none)\" if none were mentioned]\n\n## Progress\n### Done\n- [x] [Completed tasks/changes]\n\n### In Progress\n- [ ] [Current work]\n\n### Blocked\n- [Issues preventing progress, if any]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale]\n\n## Operational State\n- Modified files: [Exact paths, or \"(none)\"]\n- Read files: [Exact paths, or \"(none)\"]\n- Open failures: [Current unresolved failures/errors, or \"(none)\"]\n- Last command: [Most recent test/build/shell command and exit code, or \"(none)\"]\n- Last failing assertion/error: [Exact assertion, stack frame, or failing lines if available, or \"(none)\"]\n- Pending TODO: [Concrete remaining work, or \"(none)\"]\n\n## Next Steps\n1. [Ordered list of what should happen next]\n\n## Critical Context\n- [Any data, examples, or references needed to continue]\n- [Or \"(none)\" if not applicable]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\nconst UPDATE_SUMMARIZATION_PROMPT = `The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.\n\nUpdate the existing structured summary with new information. RULES:\n- PRESERVE all existing information from the previous summary\n- ADD new progress, decisions, and context from the new messages\n- UPDATE the Progress section: move items from \"In Progress\" to \"Done\" when completed\n- UPDATE \"Next Steps\" based on what was accomplished\n- PRESERVE exact file paths, function names, and error messages\n- If something is no longer relevant, you may remove it\n\nUse this EXACT format:\n\n## Goal\n[Preserve existing goals, add new ones if the task expanded]\n\n## Constraints & Preferences\n- [Preserve existing, add new ones discovered]\n\n## Progress\n### Done\n- [x] [Include previously done items AND newly completed items]\n\n### In Progress\n- [ ] [Current work - update based on progress]\n\n### Blocked\n- [Current blockers - remove if resolved]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale] (preserve all previous, add new)\n\n## Operational State\n- Modified files: [Preserve/update exact paths, or \"(none)\"]\n- Read files: [Preserve/update exact paths, or \"(none)\"]\n- Open failures: [Current unresolved failures/errors, or \"(none)\"]\n- Last command: [Most recent test/build/shell command and exit code, or \"(none)\"]\n- Last failing assertion/error: [Exact assertion, stack frame, or failing lines if available, or \"(none)\"]\n- Pending TODO: [Concrete remaining work, or \"(none)\"]\n\n## Next Steps\n1. [Update based on current state]\n\n## Critical Context\n- [Preserve important context, add new if needed]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\nfunction getSummaryMaxTokens(model: Model<any>, reserveTokens: number): number {\n\treturn Math.min(Math.floor(0.8 * reserveTokens), model.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY);\n}\n\nfunction estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction buildSummaryPrompt(conversationText: string, basePrompt: string, previousSummary: string | undefined): string {\n\tlet promptText = `<conversation>\\n${conversationText}\\n</conversation>\\n\\n`;\n\tif (previousSummary) {\n\t\tpromptText += `<previous-summary>\\n${previousSummary}\\n</previous-summary>\\n\\n`;\n\t}\n\treturn promptText + basePrompt;\n}\n\nfunction getSummaryInputBudget(\n\tmodel: Model<any>,\n\tmaxTokens: number,\n\tbasePrompt: string,\n\tpreviousSummary: string | undefined,\n): number {\n\tif (model.contextWindow <= 0) return Number.POSITIVE_INFINITY;\n\tconst overheadTokens = estimateTextTokens(buildSummaryPrompt(\"\", basePrompt, previousSummary));\n\treturn Math.max(1, Math.floor(model.contextWindow - maxTokens - overheadTokens));\n}\n\nfunction toSummarySegments(messages: AgentMessage[]): string[] {\n\treturn messages\n\t\t.map((message) => serializeConversation(convertToLlm([message])))\n\t\t.filter((segment) => segment.length > 0);\n}\n\nfunction takeSummaryChunk(segments: string[], tokenBudget: number): { chunk: string; remaining: string[] } {\n\tif (!Number.isFinite(tokenBudget)) return { chunk: segments.join(\"\\n\\n\"), remaining: [] };\n\n\tconst chunk: string[] = [];\n\tlet chunkTokens = 0;\n\n\tfor (let i = 0; i < segments.length; i++) {\n\t\tconst segment = segments[i];\n\t\tconst messageTokens = Math.max(1, estimateTextTokens(segment));\n\t\tif (chunk.length === 0 && messageTokens > tokenBudget) {\n\t\t\tconst chunkChars = Math.max(1, Math.floor(tokenBudget * 4));\n\t\t\tconst remainingSegment = segment.slice(chunkChars);\n\t\t\tconst remaining = remainingSegment ? [remainingSegment, ...segments.slice(i + 1)] : segments.slice(i + 1);\n\t\t\treturn { chunk: segment.slice(0, chunkChars), remaining };\n\t\t}\n\t\tif (chunk.length > 0 && chunkTokens + messageTokens > tokenBudget) {\n\t\t\treturn { chunk: chunk.join(\"\\n\\n\"), remaining: segments.slice(i) };\n\t\t}\n\t\tchunk.push(segment);\n\t\tchunkTokens += messageTokens;\n\t}\n\n\treturn { chunk: chunk.join(\"\\n\\n\"), remaining: [] };\n}\n\nasync function summarizeChunk(\n\tconversationText: string,\n\tmodel: Model<Api>,\n\tmaxTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tinitialPrompt: string,\n\tupdatePrompt: string,\n\tpreviousSummary: string | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst basePrompt = previousSummary ? updatePrompt : initialPrompt;\n\tconst promptText = buildSummaryPrompt(conversationText, basePrompt, previousSummary);\n\tconst summarizationMessages = [\n\t\t{\n\t\t\trole: \"user\" as const,\n\t\t\tcontent: [{ type: \"text\" as const, text: promptText }],\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t];\n\n\tconst completionOptions =\n\t\tmodel.reasoning && thinkingLevel && thinkingLevel !== \"off\"\n\t\t\t? { maxTokens, reasoning: thinkingLevel }\n\t\t\t: { maxTokens };\n\n\tconst response = await request(\n\t\t{ systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: summarizationMessages },\n\t\tcreateSummaryRequestOptions(completionOptions, context),\n\t\tcontext,\n\t);\n\n\tif (isContextOverflow(response, model.contextWindow) && conversationText.length > 1) {\n\t\tconst middle = Math.ceil(conversationText.length / 2);\n\t\tconst leftSummary = await summarizeChunk(\n\t\t\tconversationText.slice(0, middle),\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tpreviousSummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!leftSummary.ok) return leftSummary;\n\t\tconst rightSummary = await summarizeChunk(\n\t\t\tconversationText.slice(middle),\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tleftSummary.value.text,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!rightSummary.ok) return rightSummary;\n\t\treturn ok({\n\t\t\ttext: rightSummary.value.text,\n\t\t\tusage: addUsage(leftSummary.value.usage, rightSummary.value.usage),\n\t\t});\n\t}\n\tif (response.stopReason === \"aborted\") {\n\t\treturn err(new CompactionError(\"aborted\", response.errorMessage || \"Summarization aborted\"));\n\t}\n\tif (response.stopReason === \"error\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Summarization failed: ${response.errorMessage || \"Unknown error\"}`,\n\t\t\t),\n\t\t);\n\t}\n\tif (response.stopReason === \"length\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t\"Summarization failed: generation hit the token cap and the summary is incomplete\",\n\t\t\t),\n\t\t);\n\t}\n\tif (response.content.some((block) => block.type === \"toolCall\")) {\n\t\treturn err(new CompactionError(\"summarization_failed\", \"Summarization attempted to call a tool\"));\n\t}\n\n\treturn ok({ text: contentText(response.content), usage: response.usage });\n}\n\nasync function summarizeMessages(\n\tmessages: AgentMessage[],\n\tmodel: Model<Api>,\n\tmaxTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tinitialPrompt: string,\n\tupdatePrompt: string,\n\tpreviousSummary: string | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tlet remaining = toSummarySegments(messages);\n\tif (remaining.length === 0) {\n\t\treturn summarizeChunk(\n\t\t\t\"\",\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tpreviousSummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t}\n\tlet summary = previousSummary;\n\tlet summaryUsage: Usage | undefined;\n\twhile (remaining.length > 0) {\n\t\tconst basePrompt = summary ? updatePrompt : initialPrompt;\n\t\tconst next = takeSummaryChunk(remaining, getSummaryInputBudget(model, maxTokens, basePrompt, summary));\n\t\tconst chunkSummary = await summarizeChunk(\n\t\t\tnext.chunk,\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tsummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!chunkSummary.ok) return chunkSummary;\n\t\tsummary = chunkSummary.value.text;\n\t\tsummaryUsage = summaryUsage ? addUsage(summaryUsage, chunkSummary.value.usage) : chunkSummary.value.usage;\n\t\tremaining = next.remaining;\n\t}\n\tif (!summaryUsage) {\n\t\treturn err(new CompactionError(\"summarization_failed\", \"Summarization returned no usage data\"));\n\t}\n\treturn ok({ text: summary ?? \"\", usage: summaryUsage });\n}\n\n/** Generate or update a conversation summary for compaction. */\nexport async function generateSummary(\n\tcurrentMessages: AgentMessage[],\n\tmodels: Models,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions?: string,\n\tpreviousSummary?: string,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcontext: Context = BACKGROUND_CONTEXT,\n): Promise<Result<string, CompactionError>> {\n\tconst result = await generateSummaryWithUsage(\n\t\tcurrentMessages,\n\t\tmodels,\n\t\tmodel,\n\t\treserveTokens,\n\t\tcustomInstructions,\n\t\tpreviousSummary,\n\t\tthinkingLevel,\n\t\tretry,\n\t\tcallbacks,\n\t\tcontext,\n\t);\n\treturn result.ok ? ok(result.value.text) : err(result.error);\n}\n\n/** Generate or update a conversation summary and return its provider usage. */\nexport function generateSummaryWithUsage(\n\tcurrentMessages: AgentMessage[],\n\tmodels: Models,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions?: string,\n\tpreviousSummary?: string,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcontext: Context = BACKGROUND_CONTEXT,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tlet updatePrompt = UPDATE_SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t\tupdatePrompt = `${updatePrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\tconst request: SummaryRequest = (aiContext, options, requestContext) =>\n\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext);\n\treturn summarizeMessages(\n\t\tcurrentMessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tinitialPrompt,\n\t\tupdatePrompt,\n\t\tpreviousSummary,\n\t\trequest,\n\t\tcontext,\n\t);\n}\n\nexport interface SummaryGenerationOptions {\n\tmodel: Model<Api>;\n\treserveTokens: number;\n\tcustomInstructions?: string;\n\tpreviousSummary?: string;\n\tthinkingLevel?: ThinkingLevel;\n}\n\n/** Generate one summary through a caller-owned one-request boundary. */\nexport function generateSummaryWithRequest(\n\tcurrentMessages: AgentMessage[],\n\toptions: SummaryGenerationOptions,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst { model, reserveTokens, customInstructions, previousSummary, thinkingLevel } = options;\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tlet updatePrompt = UPDATE_SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t\tupdatePrompt = `${updatePrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\treturn summarizeMessages(\n\t\tcurrentMessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tinitialPrompt,\n\t\tupdatePrompt,\n\t\tpreviousSummary,\n\t\trequest,\n\t\tcontext,\n\t);\n}\n\n/** Prepared inputs for a compaction run. */\nexport interface CompactionPreparation {\n\t/** Messages summarized into the history summary. */\n\tmessagesToSummarize: AgentMessage[];\n\t/** Prefix messages summarized separately when compaction splits a turn. */\n\tturnPrefixMessages: AgentMessage[];\n\t/** Recent messages retained after compaction and stored on the compaction entry. */\n\tretainedTail: AgentMessage[];\n\t/** Whether compaction splits a turn. */\n\tisSplitTurn: boolean;\n\t/** Estimated context tokens before compaction. */\n\ttokensBefore: number;\n\t/** Previous compaction summary used for iterative updates. */\n\tpreviousSummary?: string;\n\t/** File operations extracted from summarized history. */\n\tfileOps: FileOperations;\n\t/** Settings used to prepare compaction. */\n\tsettings: CompactionSettings;\n}\n\n/** Prepare session entries for compaction, or return undefined when compaction is not applicable. */\nexport function prepareCompaction(\n\tpathEntries: Entry[],\n\tsettings: CompactionSettings,\n): Result<CompactionPreparation | undefined, CompactionError> {\n\tif (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === \"compaction\") {\n\t\treturn ok(undefined);\n\t}\n\n\tlet prevCompactionIndex = -1;\n\tfor (let i = pathEntries.length - 1; i >= 0; i--) {\n\t\tif (pathEntries[i].type === \"compaction\") {\n\t\t\tprevCompactionIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet previousSummary: string | undefined;\n\tlet compactableEntries = pathEntries;\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = pathEntries[prevCompactionIndex] as CompactionEntry;\n\t\tpreviousSummary = prevCompaction.summary;\n\t\tconst virtualRetainedEntries: Entry[] = prevCompaction.retainedTail.map((message, index) => ({\n\t\t\ttype: \"message\",\n\t\t\tid: `${prevCompaction.id}:retained:${index}`,\n\t\t\tparentId: index === 0 ? prevCompaction.id : `${prevCompaction.id}:retained:${index - 1}`,\n\t\t\tseq: prevCompaction.seq,\n\t\t\ttimestamp: message.timestamp,\n\t\t\tmessage,\n\t\t}));\n\t\tcompactableEntries = [...virtualRetainedEntries, ...pathEntries.slice(prevCompactionIndex + 1)];\n\t}\n\tconst boundaryEnd = compactableEntries.length;\n\n\tconst tokensBefore = estimateContextTokens(\n\t\tbuildContextEntries(pathEntries).flatMap(sessionEntryToContextMessages),\n\t).tokens;\n\tconst cutPoint = findCutPoint(compactableEntries, 0, boundaryEnd, settings.keepRecentTokens);\n\tconst historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;\n\tconst messagesToSummarize: AgentMessage[] = [];\n\tfor (let i = 0; i < historyEnd; i++) {\n\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\tif (msg) messagesToSummarize.push(msg);\n\t}\n\tconst turnPrefixMessages: AgentMessage[] = [];\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (let i = cutPoint.turnStartIndex; i < cutPoint.firstKeptEntryIndex; i++) {\n\t\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\t\tif (msg) turnPrefixMessages.push(msg);\n\t\t}\n\t}\n\tconst retainedTail: AgentMessage[] = [];\n\tfor (let i = cutPoint.firstKeptEntryIndex; i < boundaryEnd; i++) {\n\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\tif (msg) retainedTail.push(msg);\n\t}\n\tconst fileOps = extractFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (const msg of turnPrefixMessages) {\n\t\t\textractFileOpsFromMessage(msg, fileOps);\n\t\t}\n\t}\n\n\treturn ok({\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn: cutPoint.isSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t});\n}\n\n/** Optional cut-point override for the pi-client/pi-server legacy session tree. */\nexport interface CompactionPreparationOptions {\n\tfirstKeptEntryId?: string;\n}\n\n/** Prepared compaction inputs with the retained entry id required by the pi-server protocol. */\nexport interface LegacyCompactionPreparation extends CompactionPreparation {\n\tfirstKeptEntryId: string;\n}\n\nfunction estimateLegacyProjectedContextTokens(\n\tprojection: ReturnType<typeof buildLegacySessionProjection>,\n\tpathEntries: SessionTreeEntry[],\n): ContextUsageEstimate {\n\tconst estimate = estimateContextTokens(projection.messages);\n\tif (estimate.lastUsageIndex !== null) {\n\t\tlet projectedMessageIndex = 0;\n\t\tlet usageEntryId: string | undefined;\n\t\tfor (const entry of projection.entries) {\n\t\t\tconst nextMessageIndex = projectedMessageIndex + entry.messages.length;\n\t\t\tif (estimate.lastUsageIndex < nextMessageIndex) {\n\t\t\t\tusageEntryId = entry.sourceEntry.id;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprojectedMessageIndex = nextMessageIndex;\n\t\t}\n\n\t\tconst usageEntryIndex = usageEntryId ? pathEntries.findIndex((entry) => entry.id === usageEntryId) : -1;\n\t\tlet latestInvalidatingEntryIndex = -1;\n\t\tfor (let index = pathEntries.length - 1; index >= 0; index--) {\n\t\t\tconst entry = pathEntries[index];\n\t\t\tif (entry.type === \"context_edit\" || entry.type === \"compaction\") {\n\t\t\t\tlatestInvalidatingEntryIndex = index;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (usageEntryIndex > latestInvalidatingEntryIndex) return estimate;\n\t}\n\n\tconst currentSystem = getCurrentSystemMessage(projection.messages);\n\tlet tokens = currentSystem ? estimateTokens(currentSystem) : 0;\n\tfor (const message of projection.messages) {\n\t\tif (message.role !== \"system\") tokens += estimateTokens(message);\n\t}\n\treturn { tokens, usageTokens: 0, trailingTokens: tokens, lastUsageIndex: null };\n}\n\nfunction getLegacyProjectedMessagesForCompaction(entry: LegacyProjectedSessionEntry): AgentMessage[] {\n\tif (entry.sourceEntry.type === \"compaction\") return [];\n\t// System messages are prompt state. The compaction entry snapshots their\n\t// effective value so they must not be summarized or retained as conversation.\n\treturn entry.messages.filter((message) => message.role !== \"system\");\n}\n\nfunction getLegacyRetainedTailForCompaction(compaction: LegacyCompactionEntry): AgentMessage[] {\n\treturn (compaction.retainedTail ?? []).filter(\n\t\t(message) => message.role !== \"system\" && !(message.role === \"assistant\" && message.stopReason === \"deferred\"),\n\t);\n}\n\n/** Prepare a pi-client/pi-server session branch without changing its durable entry representation. */\nexport function prepareLegacyCompaction(\n\tpathEntries: SessionTreeEntry[],\n\tsettings: CompactionSettings,\n\toptions: CompactionPreparationOptions = {},\n): Result<LegacyCompactionPreparation | undefined, CompactionError> {\n\tif (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === \"compaction\") {\n\t\treturn ok(undefined);\n\t}\n\n\tconst projection = buildLegacySessionProjection(pathEntries);\n\tconst projectedEntries = projection.entries;\n\tlet prevCompactionIndex = -1;\n\tfor (let index = pathEntries.length - 1; index >= 0; index--) {\n\t\tif (pathEntries[index].type === \"compaction\") {\n\t\t\tprevCompactionIndex = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet previousSummary: string | undefined;\n\tlet boundaryStart = 0;\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = pathEntries[prevCompactionIndex] as LegacyCompactionEntry;\n\t\tpreviousSummary = prevCompaction.summary;\n\t\tconst projectedCompactionIndex = projectedEntries.findIndex(\n\t\t\t(entry) => entry.sourceEntry.id === prevCompaction.id,\n\t\t);\n\t\tboundaryStart = projectedCompactionIndex >= 0 ? projectedCompactionIndex + 1 : projectedEntries.length;\n\t}\n\tconst boundaryEnd = projectedEntries.length;\n\tconst tokensBefore = estimateLegacyProjectedContextTokens(projection, pathEntries).tokens;\n\tconst previousRetainedTail =\n\t\tprevCompactionIndex >= 0\n\t\t\t? getLegacyRetainedTailForCompaction(pathEntries[prevCompactionIndex] as LegacyCompactionEntry)\n\t\t\t: [];\n\n\tconst forcedFirstKeptEntryIndex = options.firstKeptEntryId\n\t\t? projectedEntries.findIndex((entry) => entry.sourceEntry.id === options.firstKeptEntryId)\n\t\t: -1;\n\tif (\n\t\toptions.firstKeptEntryId &&\n\t\t(forcedFirstKeptEntryIndex < boundaryStart || forcedFirstKeptEntryIndex >= boundaryEnd)\n\t) {\n\t\treturn err(new CompactionError(\"invalid_session\", \"Forced first kept entry was not found\"));\n\t}\n\tconst cutPoint =\n\t\tforcedFirstKeptEntryIndex >= boundaryStart && forcedFirstKeptEntryIndex < boundaryEnd\n\t\t\t? { firstKeptEntryIndex: forcedFirstKeptEntryIndex, turnStartIndex: -1, isSplitTurn: false }\n\t\t\t: findLegacyProjectedCutPoint(projectedEntries, boundaryStart, boundaryEnd, settings.keepRecentTokens);\n\tconst firstKeptEntry = projectedEntries[cutPoint.firstKeptEntryIndex]?.sourceEntry;\n\tif (!firstKeptEntry?.id) {\n\t\treturn err(new CompactionError(\"invalid_session\", \"First kept entry has no UUID - session may need migration\"));\n\t}\n\n\tconst historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;\n\tconst messagesToSummarize = [\n\t\t...previousRetainedTail,\n\t\t...projectedEntries.slice(boundaryStart, historyEnd).flatMap(getLegacyProjectedMessagesForCompaction),\n\t];\n\tconst turnPrefixMessages = cutPoint.isSplitTurn\n\t\t? projectedEntries\n\t\t\t\t.slice(cutPoint.turnStartIndex, cutPoint.firstKeptEntryIndex)\n\t\t\t\t.flatMap(getLegacyProjectedMessagesForCompaction)\n\t\t: [];\n\tconst retainedTail = projectedEntries\n\t\t.slice(cutPoint.firstKeptEntryIndex, boundaryEnd)\n\t\t.flatMap(getLegacyProjectedMessagesForCompaction);\n\tif (messagesToSummarize.length === 0 && turnPrefixMessages.length === 0) return ok(undefined);\n\tconst fileOps = extractLegacyFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (const message of turnPrefixMessages) extractFileOpsFromMessage(message, fileOps);\n\t}\n\n\treturn ok({\n\t\tfirstKeptEntryId: firstKeptEntry.id,\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn: cutPoint.isSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t});\n}\n\nconst TURN_PREFIX_SUMMARIZATION_PROMPT = `This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.`;\n\nconst UPDATE_TURN_PREFIX_SUMMARIZATION_PROMPT = `The messages above are the next part of the same oversized turn prefix.\n\nUpdate the existing turn-prefix summary in <previous-summary> tags. Keep the same sections:\n\n## Original Request\n## Early Progress\n## Context for Suffix\n\nBe concise. Preserve exact file paths, function names, and error messages.`;\n\nexport { serializeConversation } from \"./utils.ts\";\n\n/** Generate compaction summary data from prepared session history. */\nexport function compact(\n\tpreparation: CompactionPreparation,\n\tmodels: Models,\n\tmodel: Model<Api>,\n\tcustomInstructions: string | undefined,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tretry: RetryPolicy | undefined,\n\tcallbacks: RetryCallbacks | undefined,\n\tcontext: Context,\n): Promise<Result<CompactResult, CompactionError>> {\n\treturn compactWithRequest(\n\t\tpreparation,\n\t\t{ model, customInstructions, thinkingLevel },\n\t\t(aiContext, options, requestContext) =>\n\t\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext),\n\t\tcontext,\n\t);\n}\n\nexport interface CompactGenerationOptions {\n\tmodel: Model<Api>;\n\tcustomInstructions?: string;\n\tthinkingLevel?: ThinkingLevel;\n}\n\n/** Generate compaction data through a caller-owned boundary for each provider request. */\nexport async function compactWithRequest(\n\tpreparation: CompactionPreparation,\n\toptions: CompactGenerationOptions,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<CompactResult, CompactionError>> {\n\tconst { model, customInstructions, thinkingLevel } = options;\n\tconst {\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t} = preparation;\n\n\tlet summary: string;\n\tlet summaryUsage: Usage;\n\n\tif (isSplitTurn && turnPrefixMessages.length > 0) {\n\t\tlet historyText = \"No prior history.\";\n\t\tlet historyUsage: Usage | undefined;\n\t\tif (messagesToSummarize.length > 0) {\n\t\t\tconst historyResult = await generateSummaryWithRequest(\n\t\t\t\tmessagesToSummarize,\n\t\t\t\t{ model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel },\n\t\t\t\trequest,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tif (!historyResult.ok) return err(historyResult.error);\n\t\t\thistoryText = historyResult.value.text;\n\t\t\thistoryUsage = historyResult.value.usage;\n\t\t}\n\t\tconst turnPrefixResult = await generateTurnPrefixSummary(\n\t\t\tturnPrefixMessages,\n\t\t\tmodel,\n\t\t\tsettings.reserveTokens,\n\t\t\tthinkingLevel,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!turnPrefixResult.ok) return err(turnPrefixResult.error);\n\t\tsummary = `${historyText}\\n\\n---\\n\\n**Turn Context (split turn):**\\n\\n${turnPrefixResult.value.text}`;\n\t\tsummaryUsage = historyUsage ? addUsage(historyUsage, turnPrefixResult.value.usage) : turnPrefixResult.value.usage;\n\t} else {\n\t\tconst summaryResult = await generateSummaryWithRequest(\n\t\t\tmessagesToSummarize,\n\t\t\t{ model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel },\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!summaryResult.ok) return err(summaryResult.error);\n\t\tsummary = summaryResult.value.text;\n\t\tsummaryUsage = summaryResult.value.usage;\n\t}\n\n\tconst { readFiles, modifiedFiles } = computeFileLists(fileOps);\n\tsummary += formatFileOperations(readFiles, modifiedFiles);\n\tconst details: CompactionDetails = { readFiles, modifiedFiles };\n\n\treturn ok({ summary, tokensBefore, usage: summaryUsage, retainedTail, details });\n}\n\n/** Compact a pi-client/pi-server session branch and preserve its retained entry id. */\nexport async function compactLegacy(\n\tpreparation: LegacyCompactionPreparation,\n\tmodels: Models,\n\tmodel: Model<Api>,\n\tcustomInstructions?: string,\n\tsignal?: AbortSignal,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n): Promise<Result<LegacyCompactResult, CompactionError>> {\n\tconst context = signal ? withAbortSignal(signal, BACKGROUND_CONTEXT) : BACKGROUND_CONTEXT;\n\tconst request: SummaryRequest = (aiContext, options, requestContext) =>\n\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext);\n\tconst result = await compactWithRequest(preparation, { model, customInstructions, thinkingLevel }, request, context);\n\treturn result.ok ? ok({ ...result.value, firstKeptEntryId: preparation.firstKeptEntryId }) : err(result.error);\n}\nasync function generateTurnPrefixSummary(\n\tmessages: AgentMessage[],\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst maxTokens = Math.min(\n\t\tMath.floor(0.5 * reserveTokens),\n\t\tmodel.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY,\n\t);\n\tconst result = await summarizeMessages(\n\t\tmessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tTURN_PREFIX_SUMMARIZATION_PROMPT,\n\t\tUPDATE_TURN_PREFIX_SUMMARIZATION_PROMPT,\n\t\tundefined,\n\t\trequest,\n\t\tcontext,\n\t);\n\tif (!result.ok && result.error.code === \"summarization_failed\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Turn prefix summarization failed: ${result.error.message.replace(/^Summarization failed: /, \"\")}`,\n\t\t\t),\n\t\t);\n\t}\n\treturn result;\n}\n"]}
1
+ {"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/harness/compaction/compaction.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\ttype Context as AiContext,\n\ttype Api,\n\ttype AssistantMessage,\n\tcontentText,\n\tgetCurrentSystemMessage,\n\tisContextOverflow,\n\ttype Model,\n\ttype Models,\n\tnormalizeContext,\n\ttype RetryCallbacks,\n\ttype RetryPolicy,\n\tretryAssistantCall,\n\ttype SimpleStreamOptions,\n\ttype SystemMessage,\n\ttype Usage,\n\tuuidv7,\n} from \"@earendil-works/pi-ai\";\nimport type { AgentMessage, ThinkingLevel } from \"../../types.ts\";\nimport { BACKGROUND_CONTEXT, type Context, getTelemetryContext, withAbortSignal } from \"../context.ts\";\nimport {\n\tbuildLegacySessionProjection,\n\ttype LegacyCompactionEntry,\n\ttype LegacyProjectedSessionEntry,\n\tlegacyEntryToContextMessages,\n\ttype SessionTreeEntry,\n} from \"../legacy-session.ts\";\nimport { convertToLlm, createBranchSummaryMessage, createCompactionSummaryMessage } from \"../messages.ts\";\nimport { buildContextEntries, sessionEntryToContextMessages } from \"../session/context.ts\";\nimport type { CompactionEntry, Entry, JsonValue } from \"../session/types.ts\";\nimport { CompactionError, err, ok, type Result } from \"../types.ts\";\nimport { addUsage } from \"../utils/usage.ts\";\nimport {\n\tcomputeFileLists,\n\tcreateFileOps,\n\textractFileOpsFromMessage,\n\ttype FileOperations,\n\tformatFileOperations,\n\tserializeConversation,\n} from \"./utils.ts\";\n\n/** File-operation details stored on generated compaction entries. */\nexport interface CompactionDetails extends Record<string, JsonValue> {\n\t/** Files read in the compacted history. */\n\treadFiles: string[];\n\t/** Files modified in the compacted history. */\n\tmodifiedFiles: string[];\n\tcachePath: { mode: \"exact_prefix\" | \"chunked\"; reason: string };\n}\nfunction safeJsonStringify(value: unknown): string {\n\ttry {\n\t\treturn JSON.stringify(value) ?? \"undefined\";\n\t} catch {\n\t\treturn \"[unserializable]\";\n\t}\n}\n\nfunction extractFileOperations(\n\tmessages: AgentMessage[],\n\tentries: Entry[],\n\tprevCompactionIndex: number,\n): FileOperations {\n\tconst fileOps = createFileOps();\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = entries[prevCompactionIndex] as CompactionEntry;\n\t\tif (\n\t\t\ttypeof prevCompaction.details === \"object\" &&\n\t\t\tprevCompaction.details !== null &&\n\t\t\t!Array.isArray(prevCompaction.details)\n\t\t) {\n\t\t\tif (Array.isArray(prevCompaction.details.readFiles)) {\n\t\t\t\tfor (const path of prevCompaction.details.readFiles) {\n\t\t\t\t\tif (typeof path === \"string\") fileOps.read.add(path);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (Array.isArray(prevCompaction.details.modifiedFiles)) {\n\t\t\t\tfor (const path of prevCompaction.details.modifiedFiles) {\n\t\t\t\t\tif (typeof path === \"string\") fileOps.edited.add(path);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfor (const msg of messages) {\n\t\textractFileOpsFromMessage(msg, fileOps);\n\t}\n\n\treturn fileOps;\n}\nfunction getMessageFromEntry(entry: Entry): AgentMessage | undefined {\n\tif (entry.type === \"message\") {\n\t\treturn entry.message as AgentMessage;\n\t}\n\tif (entry.type === \"branch_summary\") {\n\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\t}\n\tif (entry.type === \"compaction\") {\n\t\treturn createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp);\n\t}\n\treturn undefined;\n}\n\nfunction getMessageFromEntryForCompaction(entry: Entry): AgentMessage | undefined {\n\tif (entry.type === \"compaction\") {\n\t\treturn undefined;\n\t}\n\treturn getMessageFromEntry(entry);\n}\n\nfunction extractLegacyFileOperations(\n\tmessages: AgentMessage[],\n\tentries: SessionTreeEntry[],\n\tprevCompactionIndex: number,\n): FileOperations {\n\tconst fileOps = createFileOps();\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = entries[prevCompactionIndex] as LegacyCompactionEntry;\n\t\tif (!prevCompaction.fromHook && prevCompaction.details) {\n\t\t\tconst details = prevCompaction.details as CompactionDetails;\n\t\t\tif (Array.isArray(details.readFiles)) {\n\t\t\t\tfor (const file of details.readFiles) fileOps.read.add(file);\n\t\t\t}\n\t\t\tif (Array.isArray(details.modifiedFiles)) {\n\t\t\t\tfor (const file of details.modifiedFiles) fileOps.edited.add(file);\n\t\t\t}\n\t\t}\n\t}\n\tfor (const message of messages) extractFileOpsFromMessage(message, fileOps);\n\treturn fileOps;\n}\n\n/** Generated compaction data ready to be persisted as a compaction entry. */\nexport interface CompactResult<T = JsonValue> {\n\t/** Summary text that replaces compacted history in future context. */\n\tsummary: string;\n\t/** Estimated context tokens before compaction. */\n\ttokensBefore: number;\n\t/** Usage from the LLM call(s) that generated this summary, if available. */\n\tusage?: Usage;\n\t/** Retained recent messages stored directly on the compaction entry. */\n\tretainedTail: AgentMessage[];\n\t/** Optional implementation-specific details stored with the compaction entry. */\n\tdetails?: T;\n}\n\n/** Compaction result used by the pi-client/pi-server session-tree protocol. */\nexport interface LegacyCompactResult<T = unknown> extends CompactResult<T> {\n\t/** Entry id where retained history starts. */\n\tfirstKeptEntryId: string;\n}\n\nexport type SummaryRequest = (\n\taiContext: AiContext,\n\toptions: SimpleStreamOptions,\n\tcontext: Context,\n\tpreservePromptCache?: boolean,\n) => Promise<AssistantMessage>;\n\nexport type CompactionCacheRequestOptions = Pick<\n\tSimpleStreamOptions,\n\t\"cacheRetention\" | \"sessionId\" | \"transport\" | \"thinkingBudgets\" | \"maxRetryDelayMs\" | \"timeoutMs\"\n>;\n\nexport function createSummaryRequestOptions(\n\toptions: SimpleStreamOptions,\n\tcontext: Context,\n\tpreservePromptCache = false,\n): SimpleStreamOptions {\n\treturn {\n\t\t...options,\n\t\tsignal: context.abortSignal,\n\t\ttelemetryContext: getTelemetryContext(context),\n\t\t...(!preservePromptCache ? { cacheRetention: \"none\" as const } : {}),\n\t\tsessionId: preservePromptCache ? options.sessionId : (options.sessionId ?? uuidv7()),\n\t};\n}\n\nexport async function completeSimpleWithRetries(\n\tmodels: Models,\n\tmodel: Model<Api>,\n\taiContext: AiContext,\n\toptions: SimpleStreamOptions,\n\tretry: RetryPolicy | undefined,\n\tcallbacks: RetryCallbacks | undefined,\n\tcontext: Context,\n\tpreservePromptCache = false,\n): Promise<AssistantMessage> {\n\t// Chunked and branch summaries are one-off requests. The exact-prefix compaction path opts in explicitly.\n\tconst requestOptions = createSummaryRequestOptions(options, context, preservePromptCache);\n\treturn retryAssistantCall(\n\t\t() => models.completeSimple(model, aiContext, requestOptions),\n\t\tretry,\n\t\trequestOptions.signal,\n\t\tcallbacks,\n\t);\n}\n\n/** Compaction thresholds and retention settings. */\nexport interface CompactionSettings {\n\t/** Enable automatic compaction decisions. */\n\tenabled: boolean;\n\t/** Tokens reserved for summary prompt and output. */\n\treserveTokens: number;\n\t/** Approximate recent-context tokens to keep after compaction. */\n\tkeepRecentTokens: number;\n}\n\n/** Default compaction settings used by the harness. */\nexport const DEFAULT_COMPACTION_SETTINGS: CompactionSettings = {\n\tenabled: true,\n\treserveTokens: 16384,\n\tkeepRecentTokens: 20000,\n};\n\n/** Calculate total context tokens from provider usage. */\nexport function calculateContextTokens(usage: Usage): number {\n\treturn usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;\n}\nfunction getAssistantUsage(msg: AgentMessage): Usage | undefined {\n\tif (msg.role === \"assistant\" && \"usage\" in msg) {\n\t\tconst assistantMsg = msg as AssistantMessage;\n\t\tif (\n\t\t\tassistantMsg.stopReason !== \"aborted\" &&\n\t\t\tassistantMsg.stopReason !== \"error\" &&\n\t\t\tassistantMsg.usage &&\n\t\t\tcalculateContextTokens(assistantMsg.usage) > 0\n\t\t) {\n\t\t\treturn assistantMsg.usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Return usage from the last valid assistant message in session entries. */\nexport function getLastAssistantUsage(entries: Entry[]): Usage | undefined {\n\tfor (let i = entries.length - 1; i >= 0; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"message\") {\n\t\t\tconst usage = getAssistantUsage(entry.message as AgentMessage);\n\t\t\tif (usage) return usage;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Estimated context-token usage for a message list. */\nexport interface ContextUsageEstimate {\n\t/** Estimated total context tokens. */\n\ttokens: number;\n\t/** Tokens reported by the most recent assistant usage block. */\n\tusageTokens: number;\n\t/** Estimated tokens after the most recent assistant usage block. */\n\ttrailingTokens: number;\n\t/** Index of the message that provided usage, or null when none exists. */\n\tlastUsageIndex: number | null;\n}\n\nfunction getLastAssistantUsageInfo(messages: AgentMessage[]): { usage: Usage; index: number } | undefined {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst usage = getAssistantUsage(messages[i]);\n\t\tif (usage) return { usage, index: i };\n\t}\n\treturn undefined;\n}\n\n/** Estimate context tokens for messages using provider usage when available. */\nexport function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate {\n\tconst usageInfo = getLastAssistantUsageInfo(messages);\n\n\tif (!usageInfo) {\n\t\tlet estimated = 0;\n\t\tfor (const message of messages) {\n\t\t\testimated += estimateTokens(message);\n\t\t}\n\t\treturn {\n\t\t\ttokens: estimated,\n\t\t\tusageTokens: 0,\n\t\t\ttrailingTokens: estimated,\n\t\t\tlastUsageIndex: null,\n\t\t};\n\t}\n\n\tconst usageTokens = calculateContextTokens(usageInfo.usage);\n\tlet trailingTokens = 0;\n\tfor (let i = usageInfo.index + 1; i < messages.length; i++) {\n\t\ttrailingTokens += estimateTokens(messages[i]);\n\t}\n\n\treturn {\n\t\ttokens: usageTokens + trailingTokens,\n\t\tusageTokens,\n\t\ttrailingTokens,\n\t\tlastUsageIndex: usageInfo.index,\n\t};\n}\n\n/** Return whether context usage exceeds the configured compaction threshold. */\nexport function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean {\n\tif (!settings.enabled) return false;\n\treturn contextTokens > contextWindow - settings.reserveTokens;\n}\n\nconst ESTIMATED_IMAGE_CHARS = 4800;\n\nfunction estimateTextAndImageContentChars(content: string | Array<{ type: string; text?: string }>): number {\n\tif (typeof content === \"string\") {\n\t\treturn content.length;\n\t}\n\n\tlet chars = 0;\n\tfor (const block of content) {\n\t\tif (block.type === \"text\" && block.text) {\n\t\t\tchars += block.text.length;\n\t\t} else if (block.type === \"image\") {\n\t\t\tchars += ESTIMATED_IMAGE_CHARS;\n\t\t}\n\t}\n\treturn chars;\n}\n\n/** Estimate token count for one message using a conservative character heuristic. */\nexport function estimateTokens(message: AgentMessage): number {\n\tlet chars = 0;\n\n\tswitch (message.role) {\n\t\tcase \"system\": {\n\t\t\tconst system = message as SystemMessage;\n\t\t\tchars = estimateTextAndImageContentChars(system.content);\n\t\t\tif (system.sections) {\n\t\t\t\tfor (const section of Object.values(system.sections)) {\n\t\t\t\t\tif (section) chars += section.length;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (system.toolsAdded) chars += safeJsonStringify(system.toolsAdded).length;\n\t\t\tif (system.toolsRemoved) chars += safeJsonStringify(system.toolsRemoved).length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"user\": {\n\t\t\tchars = estimateTextAndImageContentChars(\n\t\t\t\t(message as { content: string | Array<{ type: string; text?: string }> }).content,\n\t\t\t);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"assistant\": {\n\t\t\tconst assistant = message as AssistantMessage;\n\t\t\tfor (const block of assistant.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tchars += block.text.length;\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tchars += block.thinking.length;\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tchars += block.name.length + safeJsonStringify(block.arguments).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"custom\":\n\t\tcase \"toolResult\": {\n\t\t\tchars = estimateTextAndImageContentChars(message.content);\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"bashExecution\": {\n\t\t\tchars = message.command.length + message.output.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\": {\n\t\t\tchars = message.summary.length;\n\t\t\treturn Math.ceil(chars / 4);\n\t\t}\n\t}\n\n\treturn 0;\n}\nfunction findValidCutPoints(entries: Entry[], startIndex: number, endIndex: number): number[] {\n\tconst cutPoints: number[] = [];\n\tfor (let i = startIndex; i < endIndex; i++) {\n\t\tconst entry = entries[i];\n\t\tswitch (entry.type) {\n\t\t\tcase \"message\": {\n\t\t\t\tconst role = entry.message.role;\n\t\t\t\tswitch (role) {\n\t\t\t\t\tcase \"bashExecution\":\n\t\t\t\t\tcase \"custom\":\n\t\t\t\t\tcase \"branchSummary\":\n\t\t\t\t\tcase \"compactionSummary\":\n\t\t\t\t\tcase \"user\":\n\t\t\t\t\tcase \"assistant\":\n\t\t\t\t\t\tcutPoints.push(i);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"toolResult\":\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"compaction\":\n\t\t\tcase \"branch_summary\":\n\t\t\tcase \"custom\":\n\t\t\t\tbreak;\n\t\t}\n\t\tif (entry.type === \"branch_summary\") cutPoints.push(i);\n\t}\n\treturn cutPoints;\n}\n\n/** Find the user-visible message that starts the turn containing an entry. */\nexport function findTurnStartIndex(entries: Entry[], entryIndex: number, startIndex: number): number {\n\tfor (let i = entryIndex; i >= startIndex; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type === \"branch_summary\") {\n\t\t\treturn i;\n\t\t}\n\t\tif (entry.type === \"message\") {\n\t\t\tconst role = entry.message.role;\n\t\t\tif (role === \"user\" || role === \"bashExecution\") {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t}\n\treturn -1;\n}\n\n/** Cut point selected for compaction. */\nexport interface CutPointResult {\n\t/** Index of the first entry retained after compaction. */\n\tfirstKeptEntryIndex: number;\n\t/** Index of the turn-start entry when the cut splits a turn, otherwise -1. */\n\tturnStartIndex: number;\n\t/** Whether the selected cut point splits an in-progress turn. */\n\tisSplitTurn: boolean;\n}\n\n/** Find the compaction cut point that keeps approximately the requested recent-token budget. */\nexport function findCutPoint(\n\tentries: Entry[],\n\tstartIndex: number,\n\tendIndex: number,\n\tkeepRecentTokens: number,\n): CutPointResult {\n\tconst cutPoints = findValidCutPoints(entries, startIndex, endIndex);\n\n\tif (cutPoints.length === 0) {\n\t\treturn { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };\n\t}\n\tlet accumulatedTokens = 0;\n\tlet cutIndex = cutPoints[0];\n\n\tfor (let i = endIndex - 1; i >= startIndex; i--) {\n\t\tconst entry = entries[i];\n\t\tif (entry.type !== \"message\") continue;\n\t\tconst messageTokens = estimateTokens(entry.message as AgentMessage);\n\t\taccumulatedTokens += messageTokens;\n\t\tif (accumulatedTokens >= keepRecentTokens) {\n\t\t\tfor (let c = 0; c < cutPoints.length; c++) {\n\t\t\t\tif (cutPoints[c] >= i) {\n\t\t\t\t\tcutIndex = cutPoints[c];\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t}\n\twhile (cutIndex > startIndex) {\n\t\tconst prevEntry = entries[cutIndex - 1];\n\t\tif (prevEntry.type === \"compaction\") {\n\t\t\tbreak;\n\t\t}\n\t\tif (prevEntry.type === \"message\") {\n\t\t\tbreak;\n\t\t}\n\t\tcutIndex--;\n\t}\n\tconst cutEntry = entries[cutIndex];\n\tconst isUserMessage = cutEntry.type === \"message\" && cutEntry.message.role === \"user\";\n\tconst turnStartIndex = isUserMessage ? -1 : findTurnStartIndex(entries, cutIndex, startIndex);\n\n\treturn {\n\t\tfirstKeptEntryIndex: cutIndex,\n\t\tturnStartIndex,\n\t\tisSplitTurn: !isUserMessage && turnStartIndex !== -1,\n\t};\n}\n\nfunction isLegacyProjectionCutPointMessage(message: AgentMessage): boolean {\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"assistant\":\n\t\tcase \"bashExecution\":\n\t\tcase \"custom\":\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn true;\n\t\tcase \"toolResult\":\n\t\tcase \"system\":\n\t\t\treturn false;\n\t}\n}\n\nfunction isLegacyProjectionTurnStartMessage(message: AgentMessage): boolean {\n\tswitch (message.role) {\n\t\tcase \"user\":\n\t\tcase \"bashExecution\":\n\t\tcase \"custom\":\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn true;\n\t\tcase \"assistant\":\n\t\tcase \"toolResult\":\n\t\tcase \"system\":\n\t\t\treturn false;\n\t}\n}\n\nfunction findLegacyProjectedValidCutPoints(\n\tentries: LegacyProjectedSessionEntry[],\n\tstartIndex: number,\n\tendIndex: number,\n): number[] {\n\tconst cutPoints: number[] = [];\n\tfor (let index = startIndex; index < endIndex; index++) {\n\t\tconst entry = entries[index];\n\t\tif (entry.sourceEntry.type !== \"compaction\" && entry.messages.some(isLegacyProjectionCutPointMessage)) {\n\t\t\tcutPoints.push(index);\n\t\t}\n\t}\n\treturn cutPoints;\n}\n\nfunction findLegacyProjectedTurnStartIndex(\n\tentries: LegacyProjectedSessionEntry[],\n\tentryIndex: number,\n\tstartIndex: number,\n): number {\n\tfor (let index = entryIndex; index >= startIndex; index--) {\n\t\tif (entries[index].messages.some(isLegacyProjectionTurnStartMessage)) return index;\n\t}\n\treturn -1;\n}\n\nfunction findLegacyProjectedCutPoint(\n\tentries: LegacyProjectedSessionEntry[],\n\tstartIndex: number,\n\tendIndex: number,\n\tkeepRecentTokens: number,\n): CutPointResult {\n\tconst cutPoints = findLegacyProjectedValidCutPoints(entries, startIndex, endIndex);\n\tif (cutPoints.length === 0) {\n\t\treturn { firstKeptEntryIndex: startIndex, turnStartIndex: -1, isSplitTurn: false };\n\t}\n\n\tlet accumulatedTokens = 0;\n\tlet exceededBudget = false;\n\tlet cutIndex = cutPoints[0];\n\tfor (let index = endIndex - 1; index >= startIndex; index--) {\n\t\tconst messageTokens = entries[index].messages.reduce((sum, message) => sum + estimateTokens(message), 0);\n\t\tif (messageTokens === 0) continue;\n\t\taccumulatedTokens += messageTokens;\n\t\tif (accumulatedTokens >= keepRecentTokens) {\n\t\t\texceededBudget = true;\n\t\t\tcutIndex = cutPoints.find((candidate) => candidate >= index) ?? cutPoints[cutPoints.length - 1];\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// A completed recovery attempt and its omission edits are context-invisible after\n\t// the last visible input. Advance past that closed suffix without skipping a\n\t// replacement edit for a visible input.\n\tconst suffix = entries.slice(cutIndex + 1, endIndex);\n\tconst isIntrinsicallyVisible = (entry: LegacyProjectedSessionEntry): boolean =>\n\t\tentry.sourceEntry.type !== \"context_edit\" && legacyEntryToContextMessages(entry.sourceEntry).length > 0;\n\tconst isOmitted = (entry: LegacyProjectedSessionEntry): boolean =>\n\t\tisIntrinsicallyVisible(entry) && entry.messages.length === 0;\n\tconst omittedSuffixIds = new Set(suffix.filter(isOmitted).map((entry) => entry.sourceEntry.id));\n\tconst hasExternalReplacement = suffix.some(\n\t\t(entry) =>\n\t\t\tentry.sourceEntry.type === \"context_edit\" &&\n\t\t\tentry.sourceEntry.replacement !== null &&\n\t\t\t!omittedSuffixIds.has(entry.sourceEntry.targetId),\n\t);\n\tconst isRecoveryOmissionSuffix =\n\t\texceededBudget &&\n\t\t!hasExternalReplacement &&\n\t\tsuffix.some(\n\t\t\t(entry) =>\n\t\t\t\tentry.sourceEntry.type === \"message\" && entry.sourceEntry.message.role === \"assistant\" && isOmitted(entry),\n\t\t) &&\n\t\tsuffix.every(\n\t\t\t(entry) => entry.sourceEntry.type !== \"compaction\" && (!isIntrinsicallyVisible(entry) || isOmitted(entry)),\n\t\t);\n\tif (isRecoveryOmissionSuffix) cutIndex++;\n\n\twhile (cutIndex > startIndex) {\n\t\tconst previousEntry = entries[cutIndex - 1];\n\t\tif (previousEntry.sourceEntry.type === \"compaction\" || previousEntry.messages.length > 0) break;\n\t\tcutIndex--;\n\t}\n\tconst startsTurn = entries[cutIndex].messages.some(isLegacyProjectionTurnStartMessage);\n\tconst turnStartIndex = startsTurn ? -1 : findLegacyProjectedTurnStartIndex(entries, cutIndex, startIndex);\n\treturn {\n\t\tfirstKeptEntryIndex: cutIndex,\n\t\tturnStartIndex,\n\t\tisSplitTurn: !startsTurn && turnStartIndex !== -1,\n\t};\n}\n\nexport const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;\n\nconst SUMMARIZATION_PROMPT = `The messages above are a conversation to summarize. Create a structured context checkpoint summary that another LLM will use to continue the work.\n\nUse this EXACT format:\n\n## Goal\n[What is the user trying to accomplish? Can be multiple items if the session covers different tasks.]\n\n## Constraints & Preferences\n- [Any constraints, preferences, or requirements mentioned by user]\n- [Or \"(none)\" if none were mentioned]\n\n## Progress\n### Done\n- [x] [Completed tasks/changes]\n\n### In Progress\n- [ ] [Current work]\n\n### Blocked\n- [Issues preventing progress, if any]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale]\n\n## Operational State\n- Modified files: [Exact paths, or \"(none)\"]\n- Read files: [Exact paths, or \"(none)\"]\n- Open failures: [Current unresolved failures/errors, or \"(none)\"]\n- Last command: [Most recent test/build/shell command and exit code, or \"(none)\"]\n- Last failing assertion/error: [Exact assertion, stack frame, or failing lines if available, or \"(none)\"]\n- Pending TODO: [Concrete remaining work, or \"(none)\"]\n\n## Next Steps\n1. [Ordered list of what should happen next]\n\n## Critical Context\n- [Any data, examples, or references needed to continue]\n- [Or \"(none)\" if not applicable]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\nconst UPDATE_SUMMARIZATION_PROMPT = `The messages above are NEW conversation messages to incorporate into the existing summary provided in <previous-summary> tags.\n\nUpdate the existing structured summary with new information. RULES:\n- PRESERVE all existing information from the previous summary\n- ADD new progress, decisions, and context from the new messages\n- UPDATE the Progress section: move items from \"In Progress\" to \"Done\" when completed\n- UPDATE \"Next Steps\" based on what was accomplished\n- PRESERVE exact file paths, function names, and error messages\n- If something is no longer relevant, you may remove it\n\nUse this EXACT format:\n\n## Goal\n[Preserve existing goals, add new ones if the task expanded]\n\n## Constraints & Preferences\n- [Preserve existing, add new ones discovered]\n\n## Progress\n### Done\n- [x] [Include previously done items AND newly completed items]\n\n### In Progress\n- [ ] [Current work - update based on progress]\n\n### Blocked\n- [Current blockers - remove if resolved]\n\n## Key Decisions\n- **[Decision]**: [Brief rationale] (preserve all previous, add new)\n\n## Operational State\n- Modified files: [Preserve/update exact paths, or \"(none)\"]\n- Read files: [Preserve/update exact paths, or \"(none)\"]\n- Open failures: [Current unresolved failures/errors, or \"(none)\"]\n- Last command: [Most recent test/build/shell command and exit code, or \"(none)\"]\n- Last failing assertion/error: [Exact assertion, stack frame, or failing lines if available, or \"(none)\"]\n- Pending TODO: [Concrete remaining work, or \"(none)\"]\n\n## Next Steps\n1. [Update based on current state]\n\n## Critical Context\n- [Preserve important context, add new if needed]\n\nKeep each section concise. Preserve exact file paths, function names, and error messages.`;\n\nfunction getSummaryMaxTokens(model: Model<any>, reserveTokens: number): number {\n\treturn Math.min(Math.floor(0.8 * reserveTokens), model.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY);\n}\n\nfunction estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction buildSummaryPrompt(conversationText: string, basePrompt: string, previousSummary: string | undefined): string {\n\tlet promptText = `<conversation>\\n${conversationText}\\n</conversation>\\n\\n`;\n\tif (previousSummary) {\n\t\tpromptText += `<previous-summary>\\n${previousSummary}\\n</previous-summary>\\n\\n`;\n\t}\n\treturn promptText + basePrompt;\n}\n\nfunction getSummaryInputBudget(\n\tmodel: Model<any>,\n\tmaxTokens: number,\n\tbasePrompt: string,\n\tpreviousSummary: string | undefined,\n): number {\n\tif (model.contextWindow <= 0) return Number.POSITIVE_INFINITY;\n\tconst overheadTokens = estimateTextTokens(buildSummaryPrompt(\"\", basePrompt, previousSummary));\n\treturn Math.max(1, Math.floor(model.contextWindow - maxTokens - overheadTokens));\n}\n\nfunction toSummarySegments(messages: AgentMessage[]): string[] {\n\treturn messages\n\t\t.map((message) => serializeConversation(convertToLlm([message])))\n\t\t.filter((segment) => segment.length > 0);\n}\n\nfunction takeSummaryChunk(segments: string[], tokenBudget: number): { chunk: string; remaining: string[] } {\n\tif (!Number.isFinite(tokenBudget)) return { chunk: segments.join(\"\\n\\n\"), remaining: [] };\n\n\tconst chunk: string[] = [];\n\tlet chunkTokens = 0;\n\n\tfor (let i = 0; i < segments.length; i++) {\n\t\tconst segment = segments[i];\n\t\tconst messageTokens = Math.max(1, estimateTextTokens(segment));\n\t\tif (chunk.length === 0 && messageTokens > tokenBudget) {\n\t\t\tconst chunkChars = Math.max(1, Math.floor(tokenBudget * 4));\n\t\t\tconst remainingSegment = segment.slice(chunkChars);\n\t\t\tconst remaining = remainingSegment ? [remainingSegment, ...segments.slice(i + 1)] : segments.slice(i + 1);\n\t\t\treturn { chunk: segment.slice(0, chunkChars), remaining };\n\t\t}\n\t\tif (chunk.length > 0 && chunkTokens + messageTokens > tokenBudget) {\n\t\t\treturn { chunk: chunk.join(\"\\n\\n\"), remaining: segments.slice(i) };\n\t\t}\n\t\tchunk.push(segment);\n\t\tchunkTokens += messageTokens;\n\t}\n\n\treturn { chunk: chunk.join(\"\\n\\n\"), remaining: [] };\n}\n\nasync function summarizeChunk(\n\tconversationText: string,\n\tmodel: Model<Api>,\n\tmaxTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tinitialPrompt: string,\n\tupdatePrompt: string,\n\tpreviousSummary: string | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst basePrompt = previousSummary ? updatePrompt : initialPrompt;\n\tconst promptText = buildSummaryPrompt(conversationText, basePrompt, previousSummary);\n\tconst summarizationMessages = [\n\t\t{\n\t\t\trole: \"user\" as const,\n\t\t\tcontent: [{ type: \"text\" as const, text: promptText }],\n\t\t\ttimestamp: Date.now(),\n\t\t},\n\t];\n\n\tconst completionOptions =\n\t\tmodel.reasoning && thinkingLevel && thinkingLevel !== \"off\"\n\t\t\t? { maxTokens, reasoning: thinkingLevel }\n\t\t\t: { maxTokens };\n\n\tconst response = await request(\n\t\t{ systemPrompt: SUMMARIZATION_SYSTEM_PROMPT, messages: summarizationMessages },\n\t\tcreateSummaryRequestOptions(completionOptions, context),\n\t\tcontext,\n\t);\n\n\tif (isContextOverflow(response, model.contextWindow) && conversationText.length > 1) {\n\t\tconst middle = Math.ceil(conversationText.length / 2);\n\t\tconst leftSummary = await summarizeChunk(\n\t\t\tconversationText.slice(0, middle),\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tpreviousSummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!leftSummary.ok) return leftSummary;\n\t\tconst rightSummary = await summarizeChunk(\n\t\t\tconversationText.slice(middle),\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tleftSummary.value.text,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!rightSummary.ok) return rightSummary;\n\t\treturn ok({\n\t\t\ttext: rightSummary.value.text,\n\t\t\tusage: addUsage(leftSummary.value.usage, rightSummary.value.usage),\n\t\t});\n\t}\n\tif (response.stopReason === \"aborted\") {\n\t\treturn err(new CompactionError(\"aborted\", response.errorMessage || \"Summarization aborted\"));\n\t}\n\tif (response.stopReason === \"error\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Summarization failed: ${response.errorMessage || \"Unknown error\"}`,\n\t\t\t),\n\t\t);\n\t}\n\tif (response.stopReason === \"length\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t\"Summarization failed: generation hit the token cap and the summary is incomplete\",\n\t\t\t),\n\t\t);\n\t}\n\tif (response.content.some((block) => block.type === \"toolCall\")) {\n\t\treturn err(new CompactionError(\"summarization_failed\", \"Summarization attempted to call a tool\"));\n\t}\n\n\treturn ok({ text: contentText(response.content), usage: response.usage });\n}\n\nasync function summarizeMessages(\n\tmessages: AgentMessage[],\n\tmodel: Model<Api>,\n\tmaxTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tinitialPrompt: string,\n\tupdatePrompt: string,\n\tpreviousSummary: string | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tlet remaining = toSummarySegments(messages);\n\tif (remaining.length === 0) {\n\t\treturn summarizeChunk(\n\t\t\t\"\",\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tpreviousSummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t}\n\tlet summary = previousSummary;\n\tlet summaryUsage: Usage | undefined;\n\twhile (remaining.length > 0) {\n\t\tconst basePrompt = summary ? updatePrompt : initialPrompt;\n\t\tconst next = takeSummaryChunk(remaining, getSummaryInputBudget(model, maxTokens, basePrompt, summary));\n\t\tconst chunkSummary = await summarizeChunk(\n\t\t\tnext.chunk,\n\t\t\tmodel,\n\t\t\tmaxTokens,\n\t\t\tthinkingLevel,\n\t\t\tinitialPrompt,\n\t\t\tupdatePrompt,\n\t\t\tsummary,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!chunkSummary.ok) return chunkSummary;\n\t\tsummary = chunkSummary.value.text;\n\t\tsummaryUsage = summaryUsage ? addUsage(summaryUsage, chunkSummary.value.usage) : chunkSummary.value.usage;\n\t\tremaining = next.remaining;\n\t}\n\tif (!summaryUsage) {\n\t\treturn err(new CompactionError(\"summarization_failed\", \"Summarization returned no usage data\"));\n\t}\n\treturn ok({ text: summary ?? \"\", usage: summaryUsage });\n}\n\nasync function summarizeCachePrefix(\n\tpreparation: CompactionPreparation,\n\tcacheContext: AiContext,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions: string | undefined,\n\tpreviousSummary: string | undefined,\n\tthinkingLevel: ThinkingLevel | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n\tcacheOptions: CompactionCacheRequestOptions,\n): Promise<\n\t| { kind: \"unavailable\"; reason: string }\n\t| { kind: \"overflow\" }\n\t| { kind: \"error\"; error: CompactionError }\n\t| { kind: \"summary\"; value: { text: string; usage: Usage } }\n> {\n\tconst cachePrefixMessages = preparation.cachePrefixMessages;\n\tif (!cachePrefixMessages) return { kind: \"unavailable\", reason: \"projected_prefix_unavailable\" };\n\tif (!cacheOptions.sessionId) return { kind: \"unavailable\", reason: \"session_id_unavailable\" };\n\tconst fullContext = normalizeContext(cacheContext);\n\tconst prefixContext = normalizeContext({\n\t\tsystemPrompt: cacheContext.systemPrompt,\n\t\ttools: cacheContext.tools,\n\t\tmessages: convertToLlm(cachePrefixMessages),\n\t});\n\tif (\n\t\tprefixContext.messages.length > fullContext.messages.length ||\n\t\tprefixContext.messages.some(\n\t\t\t(message, index) => JSON.stringify(message) !== JSON.stringify(fullContext.messages[index]),\n\t\t)\n\t) {\n\t\treturn { kind: \"unavailable\", reason: \"projected_prefix_mismatch\" };\n\t}\n\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\tconst prefixScope =\n\t\t\"Summarize the conversation in the provider context above up to this instruction. That context is the canonical prefix selected by the compaction cut point; the retained tail is excluded. Do not call tools; output only the checkpoint summary. Report only observed failures. Preserve the latest exact failing assertion/error from the prior summary or transcript. Mark it resolved only if the same failing command/assertion passes or direct evidence fixes it; an unrelated later check does not resolve it. Otherwise keep the exact failure as unresolved/last known. Use (none) only when no prior or observed failure exists. Put unrun checks under Pending TODO, never Open failures.\";\n\tconst instruction = previousSummary\n\t\t? `${prefixScope}\\n\\nA prior compaction summary appears in the provider context above inside <summary> tags. Preserve its information and update the structured summary using the conversation messages that follow it. Keep the same sections and exact file paths, function names, and error messages.\\n\\n${initialPrompt}`\n\t\t: `${prefixScope}\\n\\n${initialPrompt}`;\n\tconst summaryContext = normalizeContext({\n\t\tmessages: [\n\t\t\t...prefixContext.messages,\n\t\t\t{ role: \"user\", content: [{ type: \"text\", text: instruction }], timestamp: Date.now() },\n\t\t],\n\t});\n\tconst options: SimpleStreamOptions = {\n\t\tmaxTokens,\n\t\t...(model.reasoning && thinkingLevel && thinkingLevel !== \"off\" ? { reasoning: thinkingLevel } : {}),\n\t\t...cacheOptions,\n\t};\n\tconst response = await request(summaryContext, createSummaryRequestOptions(options, context, true), context, true);\n\tif (response.stopReason === \"error\" && isContextOverflow(response, model.contextWindow)) return { kind: \"overflow\" };\n\tif (response.stopReason === \"aborted\") {\n\t\treturn { kind: \"error\", error: new CompactionError(\"aborted\", response.errorMessage || \"Summarization aborted\") };\n\t}\n\tif (response.stopReason === \"error\") {\n\t\treturn {\n\t\t\tkind: \"error\",\n\t\t\terror: new CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Summarization failed: ${response.errorMessage || \"Unknown error\"}`,\n\t\t\t),\n\t\t};\n\t}\n\tif (response.stopReason === \"length\") {\n\t\treturn {\n\t\t\tkind: \"error\",\n\t\t\terror: new CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t\"Summarization failed: generation hit the token cap and the summary is incomplete\",\n\t\t\t),\n\t\t};\n\t}\n\tif (response.content.some((block) => block.type === \"toolCall\")) {\n\t\treturn {\n\t\t\tkind: \"error\",\n\t\t\terror: new CompactionError(\"summarization_failed\", \"Summarization attempted to call a tool\"),\n\t\t};\n\t}\n\treturn { kind: \"summary\", value: { text: contentText(response.content), usage: response.usage } };\n}\n\n/** Generate or update a conversation summary for compaction. */\nexport async function generateSummary(\n\tcurrentMessages: AgentMessage[],\n\tmodels: Models,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions?: string,\n\tpreviousSummary?: string,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcontext: Context = BACKGROUND_CONTEXT,\n): Promise<Result<string, CompactionError>> {\n\tconst result = await generateSummaryWithUsage(\n\t\tcurrentMessages,\n\t\tmodels,\n\t\tmodel,\n\t\treserveTokens,\n\t\tcustomInstructions,\n\t\tpreviousSummary,\n\t\tthinkingLevel,\n\t\tretry,\n\t\tcallbacks,\n\t\tcontext,\n\t);\n\treturn result.ok ? ok(result.value.text) : err(result.error);\n}\n\n/** Generate or update a conversation summary and return its provider usage. */\nexport function generateSummaryWithUsage(\n\tcurrentMessages: AgentMessage[],\n\tmodels: Models,\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tcustomInstructions?: string,\n\tpreviousSummary?: string,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcontext: Context = BACKGROUND_CONTEXT,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tlet updatePrompt = UPDATE_SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t\tupdatePrompt = `${updatePrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\tconst request: SummaryRequest = (aiContext, options, requestContext) =>\n\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext);\n\treturn summarizeMessages(\n\t\tcurrentMessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tinitialPrompt,\n\t\tupdatePrompt,\n\t\tpreviousSummary,\n\t\trequest,\n\t\tcontext,\n\t);\n}\n\nexport interface SummaryGenerationOptions {\n\tmodel: Model<Api>;\n\treserveTokens: number;\n\tcustomInstructions?: string;\n\tpreviousSummary?: string;\n\tthinkingLevel?: ThinkingLevel;\n}\n\n/** Generate one summary through a caller-owned one-request boundary. */\nexport function generateSummaryWithRequest(\n\tcurrentMessages: AgentMessage[],\n\toptions: SummaryGenerationOptions,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst { model, reserveTokens, customInstructions, previousSummary, thinkingLevel } = options;\n\tconst maxTokens = getSummaryMaxTokens(model, reserveTokens);\n\tlet initialPrompt = SUMMARIZATION_PROMPT;\n\tlet updatePrompt = UPDATE_SUMMARIZATION_PROMPT;\n\tif (customInstructions) {\n\t\tinitialPrompt = `${initialPrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t\tupdatePrompt = `${updatePrompt}\\n\\nAdditional focus: ${customInstructions}`;\n\t}\n\treturn summarizeMessages(\n\t\tcurrentMessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tinitialPrompt,\n\t\tupdatePrompt,\n\t\tpreviousSummary,\n\t\trequest,\n\t\tcontext,\n\t);\n}\n\n/** Prepared inputs for a compaction run. */\nexport interface CompactionPreparation {\n\t/** Canonical model-visible session prefix before the current cut point. */\n\tcachePrefixMessages?: AgentMessage[];\n\t/** Messages summarized into the history summary. */\n\tmessagesToSummarize: AgentMessage[];\n\t/** Prefix messages summarized separately when compaction splits a turn. */\n\tturnPrefixMessages: AgentMessage[];\n\t/** Recent messages retained after compaction and stored on the compaction entry. */\n\tretainedTail: AgentMessage[];\n\t/** Whether compaction splits a turn. */\n\tisSplitTurn: boolean;\n\t/** Estimated context tokens before compaction. */\n\ttokensBefore: number;\n\t/** Previous compaction summary used for iterative updates. */\n\tpreviousSummary?: string;\n\t/** File operations extracted from summarized history. */\n\tfileOps: FileOperations;\n\t/** Settings used to prepare compaction. */\n\tsettings: CompactionSettings;\n}\n\n/** Prepare session entries for compaction, or return undefined when compaction is not applicable. */\nexport function prepareCompaction(\n\tpathEntries: Entry[],\n\tsettings: CompactionSettings,\n): Result<CompactionPreparation | undefined, CompactionError> {\n\tif (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === \"compaction\") {\n\t\treturn ok(undefined);\n\t}\n\n\tlet prevCompactionIndex = -1;\n\tfor (let i = pathEntries.length - 1; i >= 0; i--) {\n\t\tif (pathEntries[i].type === \"compaction\") {\n\t\t\tprevCompactionIndex = i;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet previousSummary: string | undefined;\n\tlet compactableEntries = pathEntries;\n\tif (prevCompactionIndex >= 0) {\n\t\tconst previousCompaction = pathEntries[prevCompactionIndex] as CompactionEntry;\n\t\tpreviousSummary = previousCompaction.summary;\n\t\tconst virtualRetainedEntries: Entry[] = previousCompaction.retainedTail.map((message, index) => ({\n\t\t\ttype: \"message\",\n\t\t\tid: `${previousCompaction.id}:retained:${index}`,\n\t\t\tparentId: index === 0 ? previousCompaction.id : `${previousCompaction.id}:retained:${index - 1}`,\n\t\t\tseq: previousCompaction.seq,\n\t\t\ttimestamp: message.timestamp,\n\t\t\tmessage,\n\t\t}));\n\t\tcompactableEntries = [...virtualRetainedEntries, ...pathEntries.slice(prevCompactionIndex + 1)];\n\t}\n\tconst boundaryEnd = compactableEntries.length;\n\n\tconst tokensBefore = estimateContextTokens(\n\t\tbuildContextEntries(pathEntries).flatMap(sessionEntryToContextMessages),\n\t).tokens;\n\tconst cutPoint = findCutPoint(compactableEntries, 0, boundaryEnd, settings.keepRecentTokens);\n\tconst historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;\n\tconst messagesToSummarize: AgentMessage[] = [];\n\tfor (let i = 0; i < historyEnd; i++) {\n\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\tif (msg) messagesToSummarize.push(msg);\n\t}\n\tconst turnPrefixMessages: AgentMessage[] = [];\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (let i = cutPoint.turnStartIndex; i < cutPoint.firstKeptEntryIndex; i++) {\n\t\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\t\tif (msg) turnPrefixMessages.push(msg);\n\t\t}\n\t}\n\tconst retainedTail: AgentMessage[] = [];\n\tfor (let i = cutPoint.firstKeptEntryIndex; i < boundaryEnd; i++) {\n\t\tconst msg = getMessageFromEntryForCompaction(compactableEntries[i]);\n\t\tif (msg) retainedTail.push(msg);\n\t}\n\tconst cachePrefixMessages: AgentMessage[] = [];\n\tif (prevCompactionIndex >= 0) {\n\t\tconst previousCompaction = pathEntries[prevCompactionIndex] as CompactionEntry;\n\t\tcachePrefixMessages.push(\n\t\t\tcreateCompactionSummaryMessage(\n\t\t\t\tpreviousCompaction.summary,\n\t\t\t\tpreviousCompaction.tokensBefore,\n\t\t\t\tpreviousCompaction.timestamp,\n\t\t\t),\n\t\t);\n\t\tconst previousRetainedCount = Math.min(historyEnd, previousCompaction.retainedTail.length);\n\t\tfor (let i = 0; i < previousRetainedCount; i++) {\n\t\t\tconst message = previousCompaction.retainedTail[i];\n\t\t\tif (message) cachePrefixMessages.push(message);\n\t\t}\n\t\tconst newHistoryEnd = Math.max(0, historyEnd - previousCompaction.retainedTail.length);\n\t\tfor (const entry of pathEntries.slice(prevCompactionIndex + 1, prevCompactionIndex + 1 + newHistoryEnd)) {\n\t\t\tconst message = getMessageFromEntryForCompaction(entry);\n\t\t\tif (message) cachePrefixMessages.push(message);\n\t\t}\n\t} else {\n\t\tfor (const entry of pathEntries.slice(0, historyEnd)) {\n\t\t\tconst message = getMessageFromEntryForCompaction(entry);\n\t\t\tif (message) cachePrefixMessages.push(message);\n\t\t}\n\t}\n\tconst fileOps = extractFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (const msg of turnPrefixMessages) {\n\t\t\textractFileOpsFromMessage(msg, fileOps);\n\t\t}\n\t}\n\n\treturn ok({\n\t\tcachePrefixMessages,\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn: cutPoint.isSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t});\n}\n\n/** Optional cut-point override for the pi-client/pi-server legacy session tree. */\nexport interface CompactionPreparationOptions {\n\tfirstKeptEntryId?: string;\n}\n\n/** Prepared compaction inputs with the retained entry id required by the pi-server protocol. */\nexport interface LegacyCompactionPreparation extends CompactionPreparation {\n\tfirstKeptEntryId: string;\n}\n\nfunction estimateLegacyProjectedContextTokens(\n\tprojection: ReturnType<typeof buildLegacySessionProjection>,\n\tpathEntries: SessionTreeEntry[],\n): ContextUsageEstimate {\n\tconst estimate = estimateContextTokens(projection.messages);\n\tif (estimate.lastUsageIndex !== null) {\n\t\tlet projectedMessageIndex = 0;\n\t\tlet usageEntryId: string | undefined;\n\t\tfor (const entry of projection.entries) {\n\t\t\tconst nextMessageIndex = projectedMessageIndex + entry.messages.length;\n\t\t\tif (estimate.lastUsageIndex < nextMessageIndex) {\n\t\t\t\tusageEntryId = entry.sourceEntry.id;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tprojectedMessageIndex = nextMessageIndex;\n\t\t}\n\n\t\tconst usageEntryIndex = usageEntryId ? pathEntries.findIndex((entry) => entry.id === usageEntryId) : -1;\n\t\tlet latestInvalidatingEntryIndex = -1;\n\t\tfor (let index = pathEntries.length - 1; index >= 0; index--) {\n\t\t\tconst entry = pathEntries[index];\n\t\t\tif (entry.type === \"context_edit\" || entry.type === \"compaction\") {\n\t\t\t\tlatestInvalidatingEntryIndex = index;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (usageEntryIndex > latestInvalidatingEntryIndex) return estimate;\n\t}\n\n\tconst currentSystem = getCurrentSystemMessage(projection.messages);\n\tlet tokens = currentSystem ? estimateTokens(currentSystem) : 0;\n\tfor (const message of projection.messages) {\n\t\tif (message.role !== \"system\") tokens += estimateTokens(message);\n\t}\n\treturn { tokens, usageTokens: 0, trailingTokens: tokens, lastUsageIndex: null };\n}\n\nfunction getLegacyProjectedMessagesForCompaction(entry: LegacyProjectedSessionEntry): AgentMessage[] {\n\tif (entry.sourceEntry.type === \"compaction\") return [];\n\t// System messages are prompt state. The compaction entry snapshots their\n\t// effective value so they must not be summarized or retained as conversation.\n\treturn entry.messages.filter((message) => message.role !== \"system\");\n}\n\nfunction getLegacyRetainedTailForCompaction(compaction: LegacyCompactionEntry): AgentMessage[] {\n\treturn (compaction.retainedTail ?? []).filter(\n\t\t(message) => message.role !== \"system\" && !(message.role === \"assistant\" && message.stopReason === \"deferred\"),\n\t);\n}\n\n/** Prepare a pi-client/pi-server session branch without changing its durable entry representation. */\nexport function prepareLegacyCompaction(\n\tpathEntries: SessionTreeEntry[],\n\tsettings: CompactionSettings,\n\toptions: CompactionPreparationOptions = {},\n): Result<LegacyCompactionPreparation | undefined, CompactionError> {\n\tif (pathEntries.length === 0 || pathEntries[pathEntries.length - 1].type === \"compaction\") {\n\t\treturn ok(undefined);\n\t}\n\n\tconst projection = buildLegacySessionProjection(pathEntries);\n\tconst projectedEntries = projection.entries;\n\tlet prevCompactionIndex = -1;\n\tfor (let index = pathEntries.length - 1; index >= 0; index--) {\n\t\tif (pathEntries[index].type === \"compaction\") {\n\t\t\tprevCompactionIndex = index;\n\t\t\tbreak;\n\t\t}\n\t}\n\n\tlet previousSummary: string | undefined;\n\tlet boundaryStart = 0;\n\tif (prevCompactionIndex >= 0) {\n\t\tconst prevCompaction = pathEntries[prevCompactionIndex] as LegacyCompactionEntry;\n\t\tpreviousSummary = prevCompaction.summary;\n\t\tconst projectedCompactionIndex = projectedEntries.findIndex(\n\t\t\t(entry) => entry.sourceEntry.id === prevCompaction.id,\n\t\t);\n\t\tboundaryStart = projectedCompactionIndex >= 0 ? projectedCompactionIndex + 1 : projectedEntries.length;\n\t}\n\tconst boundaryEnd = projectedEntries.length;\n\tconst tokensBefore = estimateLegacyProjectedContextTokens(projection, pathEntries).tokens;\n\tconst previousRetainedTail =\n\t\tprevCompactionIndex >= 0\n\t\t\t? getLegacyRetainedTailForCompaction(pathEntries[prevCompactionIndex] as LegacyCompactionEntry)\n\t\t\t: [];\n\n\tconst forcedFirstKeptEntryIndex = options.firstKeptEntryId\n\t\t? projectedEntries.findIndex((entry) => entry.sourceEntry.id === options.firstKeptEntryId)\n\t\t: -1;\n\tif (\n\t\toptions.firstKeptEntryId &&\n\t\t(forcedFirstKeptEntryIndex < boundaryStart || forcedFirstKeptEntryIndex >= boundaryEnd)\n\t) {\n\t\treturn err(new CompactionError(\"invalid_session\", \"Forced first kept entry was not found\"));\n\t}\n\tconst cutPoint =\n\t\tforcedFirstKeptEntryIndex >= boundaryStart && forcedFirstKeptEntryIndex < boundaryEnd\n\t\t\t? { firstKeptEntryIndex: forcedFirstKeptEntryIndex, turnStartIndex: -1, isSplitTurn: false }\n\t\t\t: findLegacyProjectedCutPoint(projectedEntries, boundaryStart, boundaryEnd, settings.keepRecentTokens);\n\tconst firstKeptEntry = projectedEntries[cutPoint.firstKeptEntryIndex]?.sourceEntry;\n\tif (!firstKeptEntry?.id) {\n\t\treturn err(new CompactionError(\"invalid_session\", \"First kept entry has no UUID - session may need migration\"));\n\t}\n\n\tconst historyEnd = cutPoint.isSplitTurn ? cutPoint.turnStartIndex : cutPoint.firstKeptEntryIndex;\n\tconst messagesToSummarize = [\n\t\t...previousRetainedTail,\n\t\t...projectedEntries.slice(boundaryStart, historyEnd).flatMap(getLegacyProjectedMessagesForCompaction),\n\t];\n\tconst cachePrefixMessages = projectedEntries.slice(0, historyEnd).flatMap((entry) => entry.messages);\n\tconst turnPrefixMessages = cutPoint.isSplitTurn\n\t\t? projectedEntries\n\t\t\t\t.slice(cutPoint.turnStartIndex, cutPoint.firstKeptEntryIndex)\n\t\t\t\t.flatMap(getLegacyProjectedMessagesForCompaction)\n\t\t: [];\n\tconst retainedTail = projectedEntries\n\t\t.slice(cutPoint.firstKeptEntryIndex, boundaryEnd)\n\t\t.flatMap(getLegacyProjectedMessagesForCompaction);\n\tif (messagesToSummarize.length === 0 && turnPrefixMessages.length === 0) return ok(undefined);\n\tconst fileOps = extractLegacyFileOperations(messagesToSummarize, pathEntries, prevCompactionIndex);\n\tif (cutPoint.isSplitTurn) {\n\t\tfor (const message of turnPrefixMessages) extractFileOpsFromMessage(message, fileOps);\n\t}\n\n\treturn ok({\n\t\tfirstKeptEntryId: firstKeptEntry.id,\n\t\tcachePrefixMessages,\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn: cutPoint.isSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t});\n}\n\nconst TURN_PREFIX_SUMMARIZATION_PROMPT = `This is the PREFIX of a turn that was too large to keep. The SUFFIX (recent work) is retained.\n\nSummarize the prefix to provide context for the retained suffix:\n\n## Original Request\n[What did the user ask for in this turn?]\n\n## Early Progress\n- [Key decisions and work done in the prefix]\n\n## Context for Suffix\n- [Information needed to understand the retained recent work]\n\nBe concise. Focus on what's needed to understand the kept suffix.`;\n\nconst UPDATE_TURN_PREFIX_SUMMARIZATION_PROMPT = `The messages above are the next part of the same oversized turn prefix.\n\nUpdate the existing turn-prefix summary in <previous-summary> tags. Keep the same sections:\n\n## Original Request\n## Early Progress\n## Context for Suffix\n\nBe concise. Preserve exact file paths, function names, and error messages.`;\n\nexport { serializeConversation } from \"./utils.ts\";\n\n/** Generate compaction summary data from prepared session history. */\nexport function compact(\n\tpreparation: CompactionPreparation,\n\tmodels: Models,\n\tmodel: Model<Api>,\n\tcustomInstructions: string | undefined,\n\tthinkingLevel: ThinkingLevel | undefined,\n\tretry: RetryPolicy | undefined,\n\tcallbacks: RetryCallbacks | undefined,\n\tcontext: Context,\n): Promise<Result<CompactResult, CompactionError>> {\n\treturn compactWithRequest(\n\t\tpreparation,\n\t\t{ model, customInstructions, thinkingLevel },\n\t\t(aiContext, options, requestContext) =>\n\t\t\tcompleteSimpleWithRetries(models, model, aiContext, options, retry, callbacks, requestContext),\n\t\tcontext,\n\t);\n}\n\nexport interface CompactGenerationOptions {\n\tmodel: Model<Api>;\n\tcustomInstructions?: string;\n\tthinkingLevel?: ThinkingLevel;\n\tcacheContext?: AiContext;\n\tcacheOptions?: CompactionCacheRequestOptions;\n\tcacheFallbackReason?: string;\n}\n\n/** Generate compaction data through a caller-owned boundary for each provider request. */\nexport async function compactWithRequest(\n\tpreparation: CompactionPreparation,\n\toptions: CompactGenerationOptions,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<CompactResult, CompactionError>> {\n\tconst { model, customInstructions, thinkingLevel, cacheContext, cacheOptions } = options;\n\tconst {\n\t\tmessagesToSummarize,\n\t\tturnPrefixMessages,\n\t\tretainedTail,\n\t\tisSplitTurn,\n\t\ttokensBefore,\n\t\tpreviousSummary,\n\t\tfileOps,\n\t\tsettings,\n\t} = preparation;\n\n\tlet summary: string;\n\tlet summaryUsage: Usage;\n\tlet cachePath: CompactionDetails[\"cachePath\"] = {\n\t\tmode: \"chunked\",\n\t\treason: isSplitTurn ? \"split_turn\" : (options.cacheFallbackReason ?? \"cache_context_unavailable\"),\n\t};\n\tconst requestWithRetries: SummaryRequest = (aiContext, requestOptions, requestContext, preservePromptCache) =>\n\t\trequest(aiContext, requestOptions, requestContext, preservePromptCache);\n\n\tif (isSplitTurn && turnPrefixMessages.length > 0) {\n\t\tlet historyText = \"No prior history.\";\n\t\tlet historyUsage: Usage | undefined;\n\t\tif (messagesToSummarize.length > 0) {\n\t\t\tconst historyResult = await generateSummaryWithRequest(\n\t\t\t\tmessagesToSummarize,\n\t\t\t\t{ model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel },\n\t\t\t\trequest,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tif (!historyResult.ok) return err(historyResult.error);\n\t\t\thistoryText = historyResult.value.text;\n\t\t\thistoryUsage = historyResult.value.usage;\n\t\t}\n\t\tconst turnPrefixResult = await generateTurnPrefixSummary(\n\t\t\tturnPrefixMessages,\n\t\t\tmodel,\n\t\t\tsettings.reserveTokens,\n\t\t\tthinkingLevel,\n\t\t\trequest,\n\t\t\tcontext,\n\t\t);\n\t\tif (!turnPrefixResult.ok) return err(turnPrefixResult.error);\n\t\tsummary = `${historyText}\\n\\n---\\n\\n**Turn Context (split turn):**\\n\\n${turnPrefixResult.value.text}`;\n\t\tsummaryUsage = historyUsage ? addUsage(historyUsage, turnPrefixResult.value.usage) : turnPrefixResult.value.usage;\n\t} else {\n\t\tconst prefixResult =\n\t\t\tcacheContext && cacheOptions\n\t\t\t\t? await summarizeCachePrefix(\n\t\t\t\t\t\tpreparation,\n\t\t\t\t\t\tcacheContext,\n\t\t\t\t\t\tmodel,\n\t\t\t\t\t\tsettings.reserveTokens,\n\t\t\t\t\t\tcustomInstructions,\n\t\t\t\t\t\tpreviousSummary,\n\t\t\t\t\t\tthinkingLevel,\n\t\t\t\t\t\trequestWithRetries,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\tcacheOptions,\n\t\t\t\t\t)\n\t\t\t\t: { kind: \"unavailable\" as const, reason: options.cacheFallbackReason ?? \"cache_context_unavailable\" };\n\t\tif (prefixResult.kind === \"error\") return err(prefixResult.error);\n\t\tif (prefixResult.kind === \"summary\") {\n\t\t\tsummary = prefixResult.value.text;\n\t\t\tsummaryUsage = prefixResult.value.usage;\n\t\t\tcachePath = { mode: \"exact_prefix\", reason: \"provider_prefix_request\" };\n\t\t} else {\n\t\t\tconst summaryResult = await generateSummaryWithRequest(\n\t\t\t\tmessagesToSummarize,\n\t\t\t\t{ model, reserveTokens: settings.reserveTokens, customInstructions, previousSummary, thinkingLevel },\n\t\t\t\trequestWithRetries,\n\t\t\t\tcontext,\n\t\t\t);\n\t\t\tif (!summaryResult.ok) return err(summaryResult.error);\n\t\t\tsummary = summaryResult.value.text;\n\t\t\tsummaryUsage = summaryResult.value.usage;\n\t\t\tif (prefixResult.kind === \"overflow\") {\n\t\t\t\tcachePath = { mode: \"chunked\", reason: \"provider_context_overflow\" };\n\t\t\t} else {\n\t\t\t\tcachePath = { mode: \"chunked\", reason: prefixResult.reason };\n\t\t\t}\n\t\t}\n\t}\n\n\tconst { readFiles, modifiedFiles } = computeFileLists(fileOps);\n\tsummary += formatFileOperations(readFiles, modifiedFiles);\n\tconst details: CompactionDetails = { readFiles, modifiedFiles, cachePath };\n\n\treturn ok({ summary, tokensBefore, usage: summaryUsage, retainedTail, details });\n}\n\n/** Compact a pi-client/pi-server session branch and preserve its retained entry id. */\nexport async function compactLegacy(\n\tpreparation: LegacyCompactionPreparation,\n\tmodels: Models,\n\tmodel: Model<Api>,\n\tcustomInstructions?: string,\n\tsignal?: AbortSignal,\n\tthinkingLevel?: ThinkingLevel,\n\tretry?: RetryPolicy,\n\tcallbacks?: RetryCallbacks,\n\tcacheContext?: AiContext,\n\tcacheOptions?: CompactionCacheRequestOptions,\n\tcacheFallbackReason?: string,\n): Promise<Result<LegacyCompactResult, CompactionError>> {\n\tconst context = signal ? withAbortSignal(signal, BACKGROUND_CONTEXT) : BACKGROUND_CONTEXT;\n\tconst request: SummaryRequest = (aiContext, options, requestContext, preservePromptCache) =>\n\t\tcompleteSimpleWithRetries(\n\t\t\tmodels,\n\t\t\tmodel,\n\t\t\taiContext,\n\t\t\toptions,\n\t\t\tretry,\n\t\t\tcallbacks,\n\t\t\trequestContext,\n\t\t\tpreservePromptCache,\n\t\t);\n\tconst result = await compactWithRequest(\n\t\tpreparation,\n\t\t{ model, customInstructions, thinkingLevel, cacheContext, cacheOptions, cacheFallbackReason },\n\t\trequest,\n\t\tcontext,\n\t);\n\treturn result.ok ? ok({ ...result.value, firstKeptEntryId: preparation.firstKeptEntryId }) : err(result.error);\n}\nasync function generateTurnPrefixSummary(\n\tmessages: AgentMessage[],\n\tmodel: Model<Api>,\n\treserveTokens: number,\n\tthinkingLevel: ThinkingLevel | undefined,\n\trequest: SummaryRequest,\n\tcontext: Context,\n): Promise<Result<{ text: string; usage: Usage }, CompactionError>> {\n\tconst maxTokens = Math.min(\n\t\tMath.floor(0.5 * reserveTokens),\n\t\tmodel.maxTokens > 0 ? model.maxTokens : Number.POSITIVE_INFINITY,\n\t);\n\tconst result = await summarizeMessages(\n\t\tmessages,\n\t\tmodel,\n\t\tmaxTokens,\n\t\tthinkingLevel,\n\t\tTURN_PREFIX_SUMMARIZATION_PROMPT,\n\t\tUPDATE_TURN_PREFIX_SUMMARIZATION_PROMPT,\n\t\tundefined,\n\t\trequest,\n\t\tcontext,\n\t);\n\tif (!result.ok && result.error.code === \"summarization_failed\") {\n\t\treturn err(\n\t\t\tnew CompactionError(\n\t\t\t\t\"summarization_failed\",\n\t\t\t\t`Turn prefix summarization failed: ${result.error.message.replace(/^Summarization failed: /, \"\")}`,\n\t\t\t),\n\t\t);\n\t}\n\treturn result;\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -5,7 +5,7 @@ export * from "./agent.ts";
5
5
  export * from "./agent-loop.ts";
6
6
  export * from "./harness/agent-harness.ts";
7
7
  export { type BranchPreparation, type BranchSummaryDetails, type BranchSummaryResult, type CollectEntriesResult, collectEntriesForBranchSummary, type FileOperations, type GenerateBranchSummaryOptions, generateBranchSummary, prepareBranchEntries, } from "./harness/compaction/branch-summarization.ts";
8
- export { type CompactionPreparation, type CompactionPreparationOptions, type CompactionSettings, type CompactResult, calculateContextTokens, compact, compactLegacy, DEFAULT_COMPACTION_SETTINGS, estimateContextTokens, estimateTokens, findCutPoint, findTurnStartIndex, generateSummary, generateSummaryWithUsage, getLastAssistantUsage, type LegacyCompactionPreparation, type LegacyCompactResult, prepareCompaction, prepareLegacyCompaction, serializeConversation, shouldCompact, } from "./harness/compaction/compaction.ts";
8
+ export { type CompactionCacheRequestOptions, type CompactionPreparation, type CompactionPreparationOptions, type CompactionSettings, type CompactResult, calculateContextTokens, compact, compactLegacy, DEFAULT_COMPACTION_SETTINGS, estimateContextTokens, estimateTokens, findCutPoint, findTurnStartIndex, generateSummary, generateSummaryWithUsage, getLastAssistantUsage, type LegacyCompactionPreparation, type LegacyCompactResult, prepareCompaction, prepareLegacyCompaction, serializeConversation, shouldCompact, } from "./harness/compaction/compaction.ts";
9
9
  export * from "./harness/context.ts";
10
10
  export * from "./harness/legacy-session.ts";
11
11
  export * from "./harness/messages.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { uuidv7 } from \"@earendil-works/pi-ai\";\nexport type {\n\tAttributeValue,\n\tExactTelemetryAttributes,\n\tInferEventAttributes,\n\tInferOptionalAttributes,\n\tInferRequiredAndOptionalAttributes,\n\tInferStartAttributes,\n\tRecordedTelemetryEvent,\n\tRecordedTelemetrySpan,\n\tSchemaTelemetrySpan,\n\tSpanAttributes,\n\tSpanAttributes as TelemetrySpanAttributes,\n\tSpanOptions,\n\tSpanStatus,\n\tTelemetryAttributeDefinition,\n\tTelemetryAttributeMetadata,\n\tTelemetryAttributeType,\n\tTelemetryContext,\n\tTelemetryEventAttributeDefinition,\n\tTelemetryEventDefinition,\n\tTelemetryParentDefinition,\n\tTelemetrySchemaDefinition,\n\tTelemetrySchemaSpanEndAttributes,\n\tTelemetrySchemaSpanEventAttributes,\n\tTelemetrySchemaSpanEventName,\n\tTelemetrySchemaSpanName,\n\tTelemetrySchemaSpanStartAttributes,\n\tTelemetrySchemaSpanUnion,\n\tTelemetrySpan,\n\tTelemetrySpanDefinition,\n\tTelemetryStartAttributeDefinition,\n\tTypedSpanStarter,\n} from \"@earendil-works/pi-telemetry\";\nexport {\n\tcreateTypedSpanStarter,\n\tdefineTelemetrySchema,\n\tInMemoryTelemetryContext,\n\tNOOP_TELEMETRY_CONTEXT,\n} from \"@earendil-works/pi-telemetry\";\nexport * from \"./agent.ts\";\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype BranchSummaryResult,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\ttype FileOperations,\n\ttype GenerateBranchSummaryOptions,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\ttype CompactionPreparation,\n\ttype CompactionPreparationOptions,\n\ttype CompactionSettings,\n\ttype CompactResult,\n\tcalculateContextTokens,\n\tcompact,\n\tcompactLegacy,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgenerateSummaryWithUsage,\n\tgetLastAssistantUsage,\n\ttype LegacyCompactionPreparation,\n\ttype LegacyCompactResult,\n\tprepareCompaction,\n\tprepareLegacyCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/context.ts\";\nexport * from \"./harness/legacy-session.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/result.ts\";\nexport { type LaneSnapshotReduction, reduceLaneSnapshot } from \"./harness/runtime/reducer.ts\";\nexport * from \"./harness/session/index.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\nexport type {\n\tAiSpan,\n\tAiSpanAttributes,\n\tAiSpanEndAttributes,\n\tAiSpanEventAttributes,\n\tAiSpanEventName,\n\tAiSpanName,\n\tAiSpanStartAttributes,\n\tAiTelemetrySpan,\n\tHarnessSpan,\n\tHarnessSpanAttributes,\n\tHarnessSpanEndAttributes,\n\tHarnessSpanEventAttributes,\n\tHarnessSpanEventName,\n\tHarnessSpanName,\n\tHarnessSpanStartAttributes,\n\tHarnessTelemetrySpan,\n} from \"./harness/telemetry.ts\";\nexport {\n\tAGENT_TELEMETRY_SCHEMAS,\n\tAI_TELEMETRY_SCHEMA,\n\tHARNESS_TELEMETRY_SCHEMA,\n\tstartAiSpan,\n\tstartHarnessSpan,\n} from \"./harness/telemetry.ts\";\nexport * from \"./harness/tools/index.ts\";\nexport {\n\ttype AgentHarnessResources,\n\ttype AgentHarnessStreamOptions,\n\ttype AgentHarnessStreamOptionsPatch,\n\ttype AgentHarnessTool,\n\ttype AgentHarnessToolContextSource,\n\ttype AgentHarnessToolInvocation,\n\ttype AgentHarnessToolUpdateCallback,\n\ttype AgentHarnessToolUpdateOptions,\n\tBranchSummaryError,\n\ttype BranchSummaryErrorCode,\n\tCompactionError,\n\ttype CompactionErrorCode,\n\ttype ExecutionEnv,\n\tExecutionError,\n\ttype ExecutionErrorCode,\n\terr,\n\tFileError,\n\ttype FileErrorCode,\n\ttype FileInfo,\n\ttype FileKind,\n\ttype FileSystem,\n\tgetOrThrow,\n\tgetOrUndefined,\n\tok,\n\ttype PromptTemplate,\n\ttype Shell,\n\ttype ShellExecOptions,\n\ttype ShellExecResult,\n\ttype ShellOutputCaptureOptions,\n\ttype ShellOutputLimits,\n\ttype ShellOutputMetadata,\n\ttype ShellOutputRetention,\n\ttype ShellOutputTruncation,\n\ttype ShellOutputUpdate,\n\ttype ShellOutputView,\n\ttype Skill,\n\ttoError,\n} from \"./harness/types.ts\";\nexport { applyShellOutputUpdate } from \"./harness/utils/output-capture.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\nexport * from \"./proxy.ts\";\nexport * from \"./search/index.ts\";\nexport { setDefaultStreamFn } from \"./stream-fn.ts\";\nexport * from \"./types.ts\";\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["export { uuidv7 } from \"@earendil-works/pi-ai\";\nexport type {\n\tAttributeValue,\n\tExactTelemetryAttributes,\n\tInferEventAttributes,\n\tInferOptionalAttributes,\n\tInferRequiredAndOptionalAttributes,\n\tInferStartAttributes,\n\tRecordedTelemetryEvent,\n\tRecordedTelemetrySpan,\n\tSchemaTelemetrySpan,\n\tSpanAttributes,\n\tSpanAttributes as TelemetrySpanAttributes,\n\tSpanOptions,\n\tSpanStatus,\n\tTelemetryAttributeDefinition,\n\tTelemetryAttributeMetadata,\n\tTelemetryAttributeType,\n\tTelemetryContext,\n\tTelemetryEventAttributeDefinition,\n\tTelemetryEventDefinition,\n\tTelemetryParentDefinition,\n\tTelemetrySchemaDefinition,\n\tTelemetrySchemaSpanEndAttributes,\n\tTelemetrySchemaSpanEventAttributes,\n\tTelemetrySchemaSpanEventName,\n\tTelemetrySchemaSpanName,\n\tTelemetrySchemaSpanStartAttributes,\n\tTelemetrySchemaSpanUnion,\n\tTelemetrySpan,\n\tTelemetrySpanDefinition,\n\tTelemetryStartAttributeDefinition,\n\tTypedSpanStarter,\n} from \"@earendil-works/pi-telemetry\";\nexport {\n\tcreateTypedSpanStarter,\n\tdefineTelemetrySchema,\n\tInMemoryTelemetryContext,\n\tNOOP_TELEMETRY_CONTEXT,\n} from \"@earendil-works/pi-telemetry\";\nexport * from \"./agent.ts\";\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype BranchSummaryResult,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\ttype FileOperations,\n\ttype GenerateBranchSummaryOptions,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\ttype CompactionCacheRequestOptions,\n\ttype CompactionPreparation,\n\ttype CompactionPreparationOptions,\n\ttype CompactionSettings,\n\ttype CompactResult,\n\tcalculateContextTokens,\n\tcompact,\n\tcompactLegacy,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgenerateSummaryWithUsage,\n\tgetLastAssistantUsage,\n\ttype LegacyCompactionPreparation,\n\ttype LegacyCompactResult,\n\tprepareCompaction,\n\tprepareLegacyCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/context.ts\";\nexport * from \"./harness/legacy-session.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/result.ts\";\nexport { type LaneSnapshotReduction, reduceLaneSnapshot } from \"./harness/runtime/reducer.ts\";\nexport * from \"./harness/session/index.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\nexport type {\n\tAiSpan,\n\tAiSpanAttributes,\n\tAiSpanEndAttributes,\n\tAiSpanEventAttributes,\n\tAiSpanEventName,\n\tAiSpanName,\n\tAiSpanStartAttributes,\n\tAiTelemetrySpan,\n\tHarnessSpan,\n\tHarnessSpanAttributes,\n\tHarnessSpanEndAttributes,\n\tHarnessSpanEventAttributes,\n\tHarnessSpanEventName,\n\tHarnessSpanName,\n\tHarnessSpanStartAttributes,\n\tHarnessTelemetrySpan,\n} from \"./harness/telemetry.ts\";\nexport {\n\tAGENT_TELEMETRY_SCHEMAS,\n\tAI_TELEMETRY_SCHEMA,\n\tHARNESS_TELEMETRY_SCHEMA,\n\tstartAiSpan,\n\tstartHarnessSpan,\n} from \"./harness/telemetry.ts\";\nexport * from \"./harness/tools/index.ts\";\nexport {\n\ttype AgentHarnessResources,\n\ttype AgentHarnessStreamOptions,\n\ttype AgentHarnessStreamOptionsPatch,\n\ttype AgentHarnessTool,\n\ttype AgentHarnessToolContextSource,\n\ttype AgentHarnessToolInvocation,\n\ttype AgentHarnessToolUpdateCallback,\n\ttype AgentHarnessToolUpdateOptions,\n\tBranchSummaryError,\n\ttype BranchSummaryErrorCode,\n\tCompactionError,\n\ttype CompactionErrorCode,\n\ttype ExecutionEnv,\n\tExecutionError,\n\ttype ExecutionErrorCode,\n\terr,\n\tFileError,\n\ttype FileErrorCode,\n\ttype FileInfo,\n\ttype FileKind,\n\ttype FileSystem,\n\tgetOrThrow,\n\tgetOrUndefined,\n\tok,\n\ttype PromptTemplate,\n\ttype Shell,\n\ttype ShellExecOptions,\n\ttype ShellExecResult,\n\ttype ShellOutputCaptureOptions,\n\ttype ShellOutputLimits,\n\ttype ShellOutputMetadata,\n\ttype ShellOutputRetention,\n\ttype ShellOutputTruncation,\n\ttype ShellOutputUpdate,\n\ttype ShellOutputView,\n\ttype Skill,\n\ttoError,\n} from \"./harness/types.ts\";\nexport { applyShellOutputUpdate } from \"./harness/utils/output-capture.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\nexport * from \"./proxy.ts\";\nexport * from \"./search/index.ts\";\nexport { setDefaultStreamFn } from \"./stream-fn.ts\";\nexport * from \"./types.ts\";\n"]}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAkC/C,OAAO,EACN,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,GACtB,MAAM,8BAA8B,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAKN,8BAA8B,EAG9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAKN,sBAAsB,EACtB,OAAO,EACP,aAAa,EACb,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,wBAAwB,EACxB,qBAAqB,EAGrB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAA8B,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAC9F,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAmB3C,OAAO,EACN,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,gBAAgB,GAChB,MAAM,wBAAwB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EASN,kBAAkB,EAElB,eAAe,EAGf,cAAc,EAEd,GAAG,EACH,SAAS,EAKT,UAAU,EACV,cAAc,EACd,EAAE,EAaF,OAAO,GACP,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,cAAc,YAAY,CAAC","sourcesContent":["export { uuidv7 } from \"@earendil-works/pi-ai\";\nexport type {\n\tAttributeValue,\n\tExactTelemetryAttributes,\n\tInferEventAttributes,\n\tInferOptionalAttributes,\n\tInferRequiredAndOptionalAttributes,\n\tInferStartAttributes,\n\tRecordedTelemetryEvent,\n\tRecordedTelemetrySpan,\n\tSchemaTelemetrySpan,\n\tSpanAttributes,\n\tSpanAttributes as TelemetrySpanAttributes,\n\tSpanOptions,\n\tSpanStatus,\n\tTelemetryAttributeDefinition,\n\tTelemetryAttributeMetadata,\n\tTelemetryAttributeType,\n\tTelemetryContext,\n\tTelemetryEventAttributeDefinition,\n\tTelemetryEventDefinition,\n\tTelemetryParentDefinition,\n\tTelemetrySchemaDefinition,\n\tTelemetrySchemaSpanEndAttributes,\n\tTelemetrySchemaSpanEventAttributes,\n\tTelemetrySchemaSpanEventName,\n\tTelemetrySchemaSpanName,\n\tTelemetrySchemaSpanStartAttributes,\n\tTelemetrySchemaSpanUnion,\n\tTelemetrySpan,\n\tTelemetrySpanDefinition,\n\tTelemetryStartAttributeDefinition,\n\tTypedSpanStarter,\n} from \"@earendil-works/pi-telemetry\";\nexport {\n\tcreateTypedSpanStarter,\n\tdefineTelemetrySchema,\n\tInMemoryTelemetryContext,\n\tNOOP_TELEMETRY_CONTEXT,\n} from \"@earendil-works/pi-telemetry\";\nexport * from \"./agent.ts\";\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype BranchSummaryResult,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\ttype FileOperations,\n\ttype GenerateBranchSummaryOptions,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\ttype CompactionPreparation,\n\ttype CompactionPreparationOptions,\n\ttype CompactionSettings,\n\ttype CompactResult,\n\tcalculateContextTokens,\n\tcompact,\n\tcompactLegacy,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgenerateSummaryWithUsage,\n\tgetLastAssistantUsage,\n\ttype LegacyCompactionPreparation,\n\ttype LegacyCompactResult,\n\tprepareCompaction,\n\tprepareLegacyCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/context.ts\";\nexport * from \"./harness/legacy-session.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/result.ts\";\nexport { type LaneSnapshotReduction, reduceLaneSnapshot } from \"./harness/runtime/reducer.ts\";\nexport * from \"./harness/session/index.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\nexport type {\n\tAiSpan,\n\tAiSpanAttributes,\n\tAiSpanEndAttributes,\n\tAiSpanEventAttributes,\n\tAiSpanEventName,\n\tAiSpanName,\n\tAiSpanStartAttributes,\n\tAiTelemetrySpan,\n\tHarnessSpan,\n\tHarnessSpanAttributes,\n\tHarnessSpanEndAttributes,\n\tHarnessSpanEventAttributes,\n\tHarnessSpanEventName,\n\tHarnessSpanName,\n\tHarnessSpanStartAttributes,\n\tHarnessTelemetrySpan,\n} from \"./harness/telemetry.ts\";\nexport {\n\tAGENT_TELEMETRY_SCHEMAS,\n\tAI_TELEMETRY_SCHEMA,\n\tHARNESS_TELEMETRY_SCHEMA,\n\tstartAiSpan,\n\tstartHarnessSpan,\n} from \"./harness/telemetry.ts\";\nexport * from \"./harness/tools/index.ts\";\nexport {\n\ttype AgentHarnessResources,\n\ttype AgentHarnessStreamOptions,\n\ttype AgentHarnessStreamOptionsPatch,\n\ttype AgentHarnessTool,\n\ttype AgentHarnessToolContextSource,\n\ttype AgentHarnessToolInvocation,\n\ttype AgentHarnessToolUpdateCallback,\n\ttype AgentHarnessToolUpdateOptions,\n\tBranchSummaryError,\n\ttype BranchSummaryErrorCode,\n\tCompactionError,\n\ttype CompactionErrorCode,\n\ttype ExecutionEnv,\n\tExecutionError,\n\ttype ExecutionErrorCode,\n\terr,\n\tFileError,\n\ttype FileErrorCode,\n\ttype FileInfo,\n\ttype FileKind,\n\ttype FileSystem,\n\tgetOrThrow,\n\tgetOrUndefined,\n\tok,\n\ttype PromptTemplate,\n\ttype Shell,\n\ttype ShellExecOptions,\n\ttype ShellExecResult,\n\ttype ShellOutputCaptureOptions,\n\ttype ShellOutputLimits,\n\ttype ShellOutputMetadata,\n\ttype ShellOutputRetention,\n\ttype ShellOutputTruncation,\n\ttype ShellOutputUpdate,\n\ttype ShellOutputView,\n\ttype Skill,\n\ttoError,\n} from \"./harness/types.ts\";\nexport { applyShellOutputUpdate } from \"./harness/utils/output-capture.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\nexport * from \"./proxy.ts\";\nexport * from \"./search/index.ts\";\nexport { setDefaultStreamFn } from \"./stream-fn.ts\";\nexport * from \"./types.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAkC/C,OAAO,EACN,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,GACtB,MAAM,8BAA8B,CAAC;AACtC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,OAAO,EAKN,8BAA8B,EAG9B,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EAMN,sBAAsB,EACtB,OAAO,EACP,aAAa,EACb,2BAA2B,EAC3B,qBAAqB,EACrB,cAAc,EACd,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,wBAAwB,EACxB,qBAAqB,EAGrB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,aAAa,GACb,MAAM,oCAAoC,CAAC;AAC5C,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAA8B,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAC9F,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,4BAA4B,CAAC;AAmB3C,OAAO,EACN,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,EACxB,WAAW,EACX,gBAAgB,GAChB,MAAM,wBAAwB,CAAC;AAChC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EASN,kBAAkB,EAElB,eAAe,EAGf,cAAc,EAEd,GAAG,EACH,SAAS,EAKT,UAAU,EACV,cAAc,EACd,EAAE,EAaF,OAAO,GACP,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,cAAc,iCAAiC,CAAC;AAChD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,YAAY,CAAC;AAC3B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,cAAc,YAAY,CAAC","sourcesContent":["export { uuidv7 } from \"@earendil-works/pi-ai\";\nexport type {\n\tAttributeValue,\n\tExactTelemetryAttributes,\n\tInferEventAttributes,\n\tInferOptionalAttributes,\n\tInferRequiredAndOptionalAttributes,\n\tInferStartAttributes,\n\tRecordedTelemetryEvent,\n\tRecordedTelemetrySpan,\n\tSchemaTelemetrySpan,\n\tSpanAttributes,\n\tSpanAttributes as TelemetrySpanAttributes,\n\tSpanOptions,\n\tSpanStatus,\n\tTelemetryAttributeDefinition,\n\tTelemetryAttributeMetadata,\n\tTelemetryAttributeType,\n\tTelemetryContext,\n\tTelemetryEventAttributeDefinition,\n\tTelemetryEventDefinition,\n\tTelemetryParentDefinition,\n\tTelemetrySchemaDefinition,\n\tTelemetrySchemaSpanEndAttributes,\n\tTelemetrySchemaSpanEventAttributes,\n\tTelemetrySchemaSpanEventName,\n\tTelemetrySchemaSpanName,\n\tTelemetrySchemaSpanStartAttributes,\n\tTelemetrySchemaSpanUnion,\n\tTelemetrySpan,\n\tTelemetrySpanDefinition,\n\tTelemetryStartAttributeDefinition,\n\tTypedSpanStarter,\n} from \"@earendil-works/pi-telemetry\";\nexport {\n\tcreateTypedSpanStarter,\n\tdefineTelemetrySchema,\n\tInMemoryTelemetryContext,\n\tNOOP_TELEMETRY_CONTEXT,\n} from \"@earendil-works/pi-telemetry\";\nexport * from \"./agent.ts\";\nexport * from \"./agent-loop.ts\";\nexport * from \"./harness/agent-harness.ts\";\nexport {\n\ttype BranchPreparation,\n\ttype BranchSummaryDetails,\n\ttype BranchSummaryResult,\n\ttype CollectEntriesResult,\n\tcollectEntriesForBranchSummary,\n\ttype FileOperations,\n\ttype GenerateBranchSummaryOptions,\n\tgenerateBranchSummary,\n\tprepareBranchEntries,\n} from \"./harness/compaction/branch-summarization.ts\";\nexport {\n\ttype CompactionCacheRequestOptions,\n\ttype CompactionPreparation,\n\ttype CompactionPreparationOptions,\n\ttype CompactionSettings,\n\ttype CompactResult,\n\tcalculateContextTokens,\n\tcompact,\n\tcompactLegacy,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tfindCutPoint,\n\tfindTurnStartIndex,\n\tgenerateSummary,\n\tgenerateSummaryWithUsage,\n\tgetLastAssistantUsage,\n\ttype LegacyCompactionPreparation,\n\ttype LegacyCompactResult,\n\tprepareCompaction,\n\tprepareLegacyCompaction,\n\tserializeConversation,\n\tshouldCompact,\n} from \"./harness/compaction/compaction.ts\";\nexport * from \"./harness/context.ts\";\nexport * from \"./harness/legacy-session.ts\";\nexport * from \"./harness/messages.ts\";\nexport * from \"./harness/prompt-templates.ts\";\nexport * from \"./harness/result.ts\";\nexport { type LaneSnapshotReduction, reduceLaneSnapshot } from \"./harness/runtime/reducer.ts\";\nexport * from \"./harness/session/index.ts\";\nexport * from \"./harness/skills.ts\";\nexport * from \"./harness/system-prompt.ts\";\nexport type {\n\tAiSpan,\n\tAiSpanAttributes,\n\tAiSpanEndAttributes,\n\tAiSpanEventAttributes,\n\tAiSpanEventName,\n\tAiSpanName,\n\tAiSpanStartAttributes,\n\tAiTelemetrySpan,\n\tHarnessSpan,\n\tHarnessSpanAttributes,\n\tHarnessSpanEndAttributes,\n\tHarnessSpanEventAttributes,\n\tHarnessSpanEventName,\n\tHarnessSpanName,\n\tHarnessSpanStartAttributes,\n\tHarnessTelemetrySpan,\n} from \"./harness/telemetry.ts\";\nexport {\n\tAGENT_TELEMETRY_SCHEMAS,\n\tAI_TELEMETRY_SCHEMA,\n\tHARNESS_TELEMETRY_SCHEMA,\n\tstartAiSpan,\n\tstartHarnessSpan,\n} from \"./harness/telemetry.ts\";\nexport * from \"./harness/tools/index.ts\";\nexport {\n\ttype AgentHarnessResources,\n\ttype AgentHarnessStreamOptions,\n\ttype AgentHarnessStreamOptionsPatch,\n\ttype AgentHarnessTool,\n\ttype AgentHarnessToolContextSource,\n\ttype AgentHarnessToolInvocation,\n\ttype AgentHarnessToolUpdateCallback,\n\ttype AgentHarnessToolUpdateOptions,\n\tBranchSummaryError,\n\ttype BranchSummaryErrorCode,\n\tCompactionError,\n\ttype CompactionErrorCode,\n\ttype ExecutionEnv,\n\tExecutionError,\n\ttype ExecutionErrorCode,\n\terr,\n\tFileError,\n\ttype FileErrorCode,\n\ttype FileInfo,\n\ttype FileKind,\n\ttype FileSystem,\n\tgetOrThrow,\n\tgetOrUndefined,\n\tok,\n\ttype PromptTemplate,\n\ttype Shell,\n\ttype ShellExecOptions,\n\ttype ShellExecResult,\n\ttype ShellOutputCaptureOptions,\n\ttype ShellOutputLimits,\n\ttype ShellOutputMetadata,\n\ttype ShellOutputRetention,\n\ttype ShellOutputTruncation,\n\ttype ShellOutputUpdate,\n\ttype ShellOutputView,\n\ttype Skill,\n\ttoError,\n} from \"./harness/types.ts\";\nexport { applyShellOutputUpdate } from \"./harness/utils/output-capture.ts\";\nexport * from \"./harness/utils/shell-output.ts\";\nexport * from \"./harness/utils/truncate.ts\";\nexport * from \"./proxy.ts\";\nexport * from \"./search/index.ts\";\nexport { setDefaultStreamFn } from \"./stream-fn.ts\";\nexport * from \"./types.ts\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@averyyy/pi-agent-core",
3
- "version": "0.87.1-piclient.1",
3
+ "version": "0.87.1-piclient.2",
4
4
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,7 +60,7 @@
60
60
  },
61
61
  "dependencies": {
62
62
  "@earendil-works/chord": "^0.87.1",
63
- "@earendil-works/pi-ai": "npm:@averyyy/pi-ai@0.87.1-piclient.1",
63
+ "@earendil-works/pi-ai": "npm:@averyyy/pi-ai@0.87.1-piclient.2",
64
64
  "@earendil-works/pi-telemetry": "^0.87.1",
65
65
  "diff": "8.0.4",
66
66
  "ignore": "7.0.8",