/** * context-compaction.ts * * Context compaction engine for the GoodVibes platform runtime. * * Architecture: * - Deterministic structure: fixed sections assembled in order * - Targeted LLM calls for: substance filter, tool relevance, resolved problems, * older agent summary * - Rule-based sections: handoff, memories, current task, running agents, * agent activity table, plan progress, session lineage * - Post-compaction validation: sanity-checks required sections * - Context-window-aware thresholds * * Public API: * estimateConversationTokens(messages) , rough token count for a message array * estimateTokens(text) , rough token count for a string * shouldAutoCompact(opts) , check if configured usage threshold or safety buffer is exceeded * compactSmallWindow(messages, keepRecent), simplified compaction for small context windows * compactMessages(ctx, registry) , structured compaction entry point * checkAndCompact(autoOpts, ctx) , check and compact if threshold exceeded * getCompactionEvents() , return compaction event log * getLastCompactionEvent() , return most recent compaction event */ import type { ProviderMessage } from '../providers/interface.js'; import type { ProviderRegistry } from '../providers/registry.js'; import type { CompactionContext, CompactionResult, CompactionEvent } from './compaction-types.js'; export type { CompactionEvent, CompactionResult, CompactionContext } from './compaction-types.js'; export interface AutoCompactOptions { /** Current input token count from last LLM response. */ currentTokens: number; /** Maximum context window for the current model. */ contextWindow: number; /** Whether auto-compact is already in progress (prevent re-entry). */ isCompacting: boolean; /** * Usage percentage that triggers compaction. Defaults to 80. Set to 0 to disable * the percentage trigger; the safety buffer still applies as an independent backstop. */ thresholdPercent?: number | undefined; /** Remaining-token safety buffer that also triggers compaction. Defaults to 15000. */ minRemainingTokens?: number | undefined; } export interface AutoCompactDecision { readonly shouldCompact: boolean; readonly reason: 'threshold' | 'safety-buffer' | null; readonly currentTokens: number; readonly contextWindow: number; readonly usagePct: number; readonly thresholdPercent: number; readonly thresholdTokens: number; readonly remainingTokens: number; readonly safetyBufferTokens: number; } /** * Default remaining-token safety buffer for auto-compaction. Acts as a backstop: * compaction triggers when the remaining context drops below this buffer. 15k gives * room for the ~6.5k compaction output + LLM extraction calls on large windows. * The effective buffer is capped at SAFETY_BUFFER_MAX_WINDOW_FRACTION of the context * window (see getAutoCompactDecision) so it scales down on small/medium windows instead * of forcing near-constant compaction, while remaining an independent backstop on large windows. */ export declare const COMPACTION_BUFFER_TOKENS = 15000; /** * The remaining-token safety buffer is capped at this fraction of the context * window. A fixed token buffer (COMPACTION_BUFFER_TOKENS) must not reserve an * outsized share of small/medium windows, so the effective buffer is the lesser * of the configured buffer and this fraction of the window. On a 128k window the * full buffer applies (128k * 0.125 = 16k >= 15k); on smaller windows it scales * down so the backstop fires near the window edge rather than on near-empty * conversations, while still firing independently of high percentage thresholds. */ export declare const SAFETY_BUFFER_MAX_WINDOW_FRACTION = 0.125; export declare const DEFAULT_AUTO_COMPACT_THRESHOLD_PERCENT = 80; /** * Context windows smaller than this use simplified compaction (summarize last N messages) * instead of the full structured output, since there isn't enough room for extraction calls. */ export declare const SMALL_WINDOW_THRESHOLD = 12000; export declare function getCompactionEvents(): readonly CompactionEvent[]; export declare function getLastCompactionEvent(): CompactionEvent | null; /** Rough token estimate: 4 chars ≈ 1 token. Used for threshold checks. */ export declare function estimateConversationTokens(messages: ProviderMessage[]): number; export { estimateTokens } from './compaction-types.js'; export declare function getAutoCompactDecision(opts: AutoCompactOptions): AutoCompactDecision; /** * Returns true when context usage reaches the configured percentage threshold * or the remaining-token safety buffer is exhausted, unless compaction is * already active. */ export declare function shouldAutoCompact(opts: AutoCompactOptions): boolean; /** * Simplified compaction for context windows smaller than SMALL_WINDOW_THRESHOLD (12k). * There isn't enough room for LLM extraction calls, so we just keep the last * `keepRecent` messages and add a brief summary note. * * @param messages - Full conversation message array * @param keepRecent - Number of recent messages to keep verbatim (default: 10) * @returns Truncated message array with a summary pair prepended */ export declare function compactSmallWindow(messages: ProviderMessage[], keepRecent?: number): ProviderMessage[]; /** * resolveLineageOriginalTask, decide what text (if any) to show as * "Original task" in the session-lineage section. * * The lastUserMsg fallback is only valid for the very first compaction of a * session (compactionCount === 0): a genuine edge case where originalTask was * never recorded upstream. Past that point, falling back to the current * last-user-message would silently mislabel the CURRENT task as "Original * task" once real lineage exists, so the fallback is gated to * compactionCount === 0 only. See the matching `validateCompaction` warning * for compactionCount > 0 with a missing originalTask. */ export declare function resolveLineageOriginalTask(originalTask: string | undefined, lastUserMsg: string | null, compactionCount: number): string | undefined; /** * compactMessages, structured compaction entry point. */ export declare function compactMessages(ctx: CompactionContext, registry: ProviderRegistry): Promise; /** * checkAndCompact, Check if context usage exceeds threshold and compact if so. * Returns the compaction result if compaction was performed, null otherwise. * */ export declare function checkAndCompact(autoOpts: AutoCompactOptions, ctx: CompactionContext, registry: ProviderRegistry): Promise; //# sourceMappingURL=context-compaction.d.ts.map