/** * Context compaction for long sessions. * * Pure functions for compaction logic. The session manager handles I/O, * and after compaction the session is reloaded. */ import type { AgentMessage, ThinkingLevel } from "@earendil-works/pi-agent-core"; import type { Model, Usage } from "@earendil-works/pi-ai"; import { type SessionEntry } from "../session-manager.js"; import { type FileOperations } from "./utils.js"; /** Details stored in CompactionEntry.details for file tracking */ export interface CompactionDetails { readFiles: string[]; modifiedFiles: string[]; } /** Result from compact() - SessionManager adds uuid/parentUuid when saving */ export interface CompactionResult { summary: string; firstKeptEntryId: string; tokensBefore: number; /** Extension-specific data (e.g., ArtifactIndex, version markers for structured compaction) */ details?: T; } export interface CompactionSettings { enabled: boolean; reserveTokens: number; keepRecentTokens: number; } export declare const DEFAULT_COMPACTION_SETTINGS: CompactionSettings; /** * Calculate total context tokens from usage. * Uses the native totalTokens field when available, falls back to computing from components. */ export declare function calculateContextTokens(usage: Usage): number; /** * Find the last non-aborted assistant message usage from session entries. */ export declare function getLastAssistantUsage(entries: SessionEntry[]): Usage | undefined; export interface ContextUsageEstimate { tokens: number; usageTokens: number; trailingTokens: number; lastUsageIndex: number | null; } /** * Estimate context tokens from messages, using the last assistant usage when available. * If there are messages after the last usage, estimate their tokens with estimateTokens. */ export declare function estimateContextTokens(messages: AgentMessage[]): ContextUsageEstimate; /** * Check if compaction should trigger based on context usage. */ export declare function shouldCompact(contextTokens: number, contextWindow: number, settings: CompactionSettings): boolean; /** * Estimate token count for a message using chars/4 heuristic. * This is conservative (overestimates tokens). */ export declare function estimateTokens(message: AgentMessage): number; /** * Find the user message (or bashExecution) that starts the turn containing the given entry index. * Returns -1 if no turn start found before the index. * BashExecutionMessage is treated like a user message for turn boundaries. */ export declare function findTurnStartIndex(entries: SessionEntry[], entryIndex: number, startIndex: number): number; export interface CutPointResult { /** Index of first entry to keep */ firstKeptEntryIndex: number; /** Index of user message that starts the turn being split, or -1 if not splitting */ turnStartIndex: number; /** Whether this cut splits a turn (cut point is not a user message) */ isSplitTurn: boolean; } /** * Find the cut point in session entries that keeps approximately `keepRecentTokens`. * * Algorithm: Walk backwards from newest, accumulating estimated message sizes. * Stop when we've accumulated >= keepRecentTokens. Cut at that point. * * Can cut at user OR assistant messages (never tool results). When cutting at an * assistant message with tool calls, its tool results come after and will be kept. * * Returns CutPointResult with: * - firstKeptEntryIndex: the entry index to start keeping from * - turnStartIndex: if cutting mid-turn, the user message that started that turn * - isSplitTurn: whether we're cutting in the middle of a turn * * Only considers entries between `startIndex` and `endIndex` (exclusive). */ export declare function findCutPoint(entries: SessionEntry[], startIndex: number, endIndex: number, keepRecentTokens: number): CutPointResult; /** * Generate a summary of the conversation using the LLM. * If previousSummary is provided, uses the update prompt to merge. */ export declare function generateSummary(currentMessages: AgentMessage[], model: Model, reserveTokens: number, apiKey: string, headers?: Record, signal?: AbortSignal, customInstructions?: string, previousSummary?: string, thinkingLevel?: ThinkingLevel): Promise; export interface CompactionPreparation { /** UUID of first entry to keep */ firstKeptEntryId: string; /** Messages that will be summarized and discarded */ messagesToSummarize: AgentMessage[]; /** Messages that will be turned into turn prefix summary (if splitting) */ turnPrefixMessages: AgentMessage[]; /** Whether this is a split turn (cut point in middle of turn) */ isSplitTurn: boolean; tokensBefore: number; /** Summary from previous compaction, for iterative update */ previousSummary?: string; /** File operations extracted from messagesToSummarize */ fileOps: FileOperations; /** Compaction settions from settings.jsonl */ settings: CompactionSettings; } export declare function prepareCompaction(pathEntries: SessionEntry[], settings: CompactionSettings): CompactionPreparation | undefined; /** * Generate summaries for compaction using prepared data. * Returns CompactionResult - SessionManager adds uuid/parentUuid when saving. * * @param preparation - Pre-calculated preparation from prepareCompaction() * @param customInstructions - Optional custom focus for the summary */ export declare function compact(preparation: CompactionPreparation, model: Model, apiKey: string, headers?: Record, customInstructions?: string, signal?: AbortSignal, thinkingLevel?: ThinkingLevel): Promise; //# sourceMappingURL=compaction.d.ts.map