import { type Message, type Provider, type ContentPart } from "@kenkaiiii/gg-ai"; /** Max retries for empty LLM responses during summarization. */ export declare const MAX_SUMMARY_RETRIES = 2; /** * Output-token band for the summary response. A flat 4096 under-served large * summary models (the sections at the bottom of the structure were the ones * that got cut) and over-served small ones. Scale with the summary model's own * window instead, clamped so a tiny window still gets a usable summary and a * 1M-token window does not buy an essay that just re-inflates the context. */ export declare const MIN_SUMMARY_OUTPUT_TOKENS = 4096; export declare const MAX_SUMMARY_OUTPUT_TOKENS = 8192; /** Resolve the summary output ceiling for a given summary-model context window. */ export declare function resolveSummaryOutputTokens(contextWindow: number): number; /** * Local INACTIVITY deadline for each compaction summary LLM attempt: the timer * resets on every stream event, so it only fires after this long with no sign * of life from the provider. A hard total deadline here used to kill every * large summary mid-generation (a multi-hundred-K-token input can stream for * well over 30s) — ~90% of summary attempts were falling back to the * low-quality extractive summary. Hung requests still fail fast: no first * token within the window aborts the attempt. */ export declare const SUMMARY_ATTEMPT_TIMEOUT_MS = 30000; export type CompactionReductionStatus = "material" | "insufficient_reduction" | "above_target" | "not_attempted"; export interface CompactionContextSelection { strategy: "query_aware" | "fallback"; selectedMessages: number; selectedTokens: number; droppedMessages: number; queryTerms: number; fallbackReason?: string; } export interface CompactionResult { /** Whether messages were actually reduced below the configured trigger target. */ compacted: boolean; /** Why compaction was skipped (only set when compacted is false). */ reason?: string; originalCount: number; newCount: number; /** Number of non-system source messages folded into the summary. */ summarizedCount: number; /** Number of original messages retained verbatim after the summary block. */ retainedCount: number; tokensBeforeEstimate: number; tokensAfterEstimate: number; targetTokens: number; reductionStatus: CompactionReductionStatus; /** Retrieval/compression diagnostics for the summarizer input. */ contextSelection?: CompactionContextSelection; /** How the collapse shifted message positions, so callers can move transcript * anchors (Ken turns, autopilot verdicts, app markers) onto the rewritten * message list instead of leaving them pointing at pre-compaction indices. * Only set when `compacted` is true. */ anchorRemap?: CompactionAnchorRemap; } /** * Position bookkeeping for a compaction: the leading `summarizedCount` * non-system messages were replaced by `prefixCount` non-system messages (the * summary, plus the assistant acknowledgement when one is emitted). Everything * after the collapsed region is kept verbatim, so it merely shifts. */ export interface CompactionAnchorRemap { /** Non-system messages that were folded into the summary. */ summarizedCount: number; /** Non-system messages the summary block occupies in the new list. */ prefixCount: number; /** Non-system messages in the FINAL compacted list. A hard ceiling for * remapped anchors: tool-pairing repair and the trailing-assistant pop can * shorten the retained tail after the collapse is decided. */ newNonSystemCount: number; } /** * @deprecated Compaction now uses only the configured context-window percentage. * Retained for source compatibility until the next major release. */ export declare const COMPACTION_RESERVE_TOKENS = 16384; /** @deprecated Retained for source compatibility until the next major release. */ export declare const COMPACTION_OVERHEAD_RESERVE_TOKENS = 5000; /** * @deprecated Compaction no longer reserves output tokens when choosing its boundary. * Retained for source compatibility until the next major release. */ export declare function getCompactionReserveTokens(maxTokens: number): number; /** * Check if compaction should be triggered. * * The boundary is the first whole token at or above the configured percentage * of the active transport's context window. Output-token ceilings do not move it. */ export declare function shouldCompact(messages: Message[], contextWindow: number, threshold?: number, /** Actual API-reported token count — preferred over char-based estimate when available. */ actualTokens?: number, /** @deprecated Output-token reserves no longer affect compaction decisions. */ _reserveTokens?: number): boolean; /** * Find the index where recent messages should start, given a token budget. * Walks backward from the end, accumulating token estimates, and returns the * first index that fits within the budget. Never cuts at index 0 (system message). * Avoids splitting tool_call / tool_result pairs. */ export declare function findRecentCutPoint(messages: Message[], tokenBudget: number): number; /** Maximum retained characters for each string argument in a completed tool call. */ export declare const HISTORICAL_TOOL_ARG_MAX_CHARS = 8000; /** * Clone assistant tool-call messages and cap large completed arguments. * IDs, tool names, and short arguments remain byte-for-byte unchanged. * `shouldCompact` lets the live pruner preserve the newest provider batches. */ export declare function compactHistoricalToolCallArgs(messages: Message[], shouldCompact?: (toolCallId: string) => boolean): Message[]; /** * Extract file paths from tool calls in assistant messages for tracking. * * `read` counts ONLY the `read` tool. `grep`/`find` take a directory as their * path argument, so folding them in produced a "files read" list full of * directories the agent never opened. */ export declare function extractFileOperations(messages: Message[]): { read: Set; modified: Set; }; /** * Prepare conversation messages for the summarizer by converting tool_call and * tool_result blocks to plain text, stripping thinking blocks, and truncating * large content. Converting tool blocks to text eliminates the tool_use/tool_result * pairing constraint entirely — the summarizer sees only user/assistant text messages. * Returns lightweight copies — the originals are not mutated. */ export declare function prepareMessagesForSummary(msgs: Message[]): Message[]; /** A previous compaction summary, separated from fresh conversation evidence. */ interface PreviousSummary { index: number; text: string; } export declare function findLatestPreviousSummary(messages: Message[]): PreviousSummary | undefined; /** * Upper bound on carried modified-file paths. A long session can edit hundreds * of files; the tail is what the agent is actually still working on. */ export declare const MAX_TRACKED_MODIFIED_FILES = 60; /** * Split a previous summary into prose, its tracked modified-file paths, and the * number of paths earlier generations already dropped. * * The tracking block is machine-appended after the LLM prose, so re-feeding it * as prose made each compaction restate the prior file list *and* append a * freshly computed one. Extracting it lets the caller emit exactly one merged * block, and lets paths from before the last collapse survive even though the * tool calls that produced them are long gone. */ export declare function splitTrackedModifiedFiles(summaryText: string): { text: string; files: string[]; omitted: number; }; /** * Render the single merged modified-file block appended to a summary. * * `priorOmitted` is the count recovered from the previous summary's note, so the * reported total stays truthful across generations instead of resetting to just * this round's overflow. */ export declare function buildModifiedFilesSection(paths: readonly string[], priorOmitted?: number): string; /** * Convert provenance into explicit summarizer attribution and remove low-value * runtime control traffic. Legacy messages remain available for old sessions. */ export declare function classifyMessagesForSummary(messages: Message[]): Message[]; /** * Select whole summarizer units by pinning prior memory (or the earliest human * request), then spending the remaining budget from newest to oldest. */ export declare function selectMessagesInBudget(msgs: Message[], tokenBudget: number): Message[]; /** * Build a fallback summary from file operations and message roles when the * LLM summary call fails or returns empty. */ export declare function buildFallbackSummary(middleMessages: Message[], fileOps: { read: Set; modified: Set; }): string; /** * Extract summary text from an LLM response. */ export declare function extractSummaryText(content: string | ContentPart[]): string; /** * Compact a conversation by summarizing older messages via LLM. * * Follows the pattern used by Continue and Nao: sends the actual conversation * messages to the summarizer (not a serialized string), bookended by a system * prompt and a "summarize this" user prompt. This lets the LLM see the real * message structure — roles, tool calls, tool results — and produce a much * better summary. * * - Keeps the system message (index 0) intact. * - Keeps the most recent ~8K tokens of conversation intact. * - Summarizes everything in between using an appropriate model. * - Tool results are truncated and thinking blocks stripped in the summary call. * - Messages are token-budgeted to avoid overflowing the summarizer's context. * - Retries on empty responses, falls back to extractive summary if all fail. */ export declare function compact(messages: Message[], options: { provider: Provider; model: string; apiKey?: string; accountId?: string; projectId?: string; baseUrl?: string; contextWindow: number; /** The active-context trigger this rewrite must land below. */ targetTokens?: number; signal?: AbortSignal; approvedPlanPath?: string; }): Promise<{ messages: Message[]; result: CompactionResult; }>; export {}; //# sourceMappingURL=compactor.d.ts.map