/** * ContextManager - Manages agent context windows * * Handles token tracking, compaction, summarization, and filtering * to keep agent context within limits while preserving important information. * * @example * ```typescript * const contextManager = new ContextManager({ * provider, * maxContextTokens: 200000, * }); * * // Check if action needed * if (contextManager.needsSummarization()) { * await contextManager.summarize(messages); * } * ``` */ import type { Message, LLMProvider } from '../providers/types.js'; import type { ContextConfig, ContextStats, CompactionResult, SummarizationResult, ContextEventHandler, ContextCategory, CategoryBudgetInfo, BudgetAllocation, PreflightResult, VerbosityLevel, CategorizedMessages, SmartCompactOptions, SmartCompactionResult } from './types.js'; import type { FileAccessTracker } from './file-tracker.js'; /** * Default budget allocation */ export declare const DEFAULT_BUDGET_ALLOCATION: BudgetAllocation; /** * Default context configuration */ export declare const DEFAULT_CONTEXT_CONFIG: ContextConfig; /** * Options for creating a ContextManager */ export interface ContextManagerOptions { /** * LLM provider (for token counting) */ provider: LLMProvider; /** * Configuration overrides */ config?: Partial; /** * Event handler for context events */ onEvent?: ContextEventHandler; /** * File access tracker for context restoration hints. * When provided, compaction/summarization will inject hints * about previously accessed files. */ fileTracker?: FileAccessTracker; } /** * Manages the agent's context window — tracks token usage, triggers * compaction when the conversation grows too large, and ensures the * agent never exceeds the model's context limit. * * The context window is divided into budgets: * - **System prompt** (~15%) — always present, never compacted * - **Anchors/pins** (~10%) — critical info that survives compaction * - **Conversation history** (~75%) — compacted when budget exceeded * * When conversation history exceeds its budget, the manager triggers * smart windowing (3-zone compaction): recent messages preserved, * middle messages summarized, old messages dropped. * * @example * ```typescript * const agent = new Agent({ * provider, * contextManager: new ContextManager({ * maxTokens: 100000, * budgets: { system: 0.15, anchors: 0.10, conversation: 0.75 }, * }), * }); * ``` */ export declare class ContextManager { private readonly provider; private readonly config; private readonly onEvent?; private readonly fileTracker?; private cachedTokenCount; private turnCount; private compactionCount; private summarizationCount; private lastCompactionTurn; private categoryUsage; constructor(options: ContextManagerOptions); /** * Merge partial config with defaults */ private mergeConfig; /** * Emit a context event */ private emit; /** * Count tokens in messages using the provider */ countTokens(messages: Message[]): Promise; /** * Update token count for messages */ updateTokenCount(messages: Message[]): Promise; /** * Get current token count (cached) */ getTokenCount(): number; /** * Get context utilization (0.0 - 1.0) */ getUtilization(): number; /** * Get maximum context tokens */ getMaxTokens(): number; /** * Increment turn count (call after each assistant response) */ incrementTurn(): void; /** * Get the current turn count */ getTurnCount(): number; /** * Set the turn count (for restoring from saved state) */ setTurnCount(count: number): void; /** * Check if compaction is needed */ needsCompaction(): boolean; /** * Check if summarization is needed (more aggressive than compaction) */ needsSummarization(): boolean; /** * Check if content should be filtered before adding */ shouldFilter(tokenCount: number): boolean; /** * Get context statistics */ getStats(messageCount: number): ContextStats; /** * Get the current configuration */ getConfig(): ContextConfig; /** * Get the file access tracker (if configured) */ getFileTracker(): FileAccessTracker | undefined; /** * Format context restoration hints based on current verbosity level. * Returns empty string if no file tracker is configured or no files have been accessed. */ formatRestorationHints(): string; /** * Create a system message with context restoration hints. * Returns undefined if no hints are available. * * The caller (Agent) is responsible for injecting this message * after compaction or summarization. */ createRestorationHintMessage(): Message | undefined; /** * Get budget information for a specific category */ getCategoryBudget(category: ContextCategory): CategoryBudgetInfo; /** * Get budget information for all categories */ getAllBudgets(): Record; /** * Update token usage for a category */ updateCategoryUsage(category: ContextCategory, tokens: number): void; /** * Add tokens to a category */ addToCategory(category: ContextCategory, tokens: number): void; /** * Check if a specific category needs compaction */ categoryNeedsCompaction(category: ContextCategory): boolean; /** * Compact only a specific category * * This is more targeted than full compaction - only affects messages * in the specified category, leaving others untouched. */ compactCategory(messages: Message[], category: ContextCategory, saveToFile: (content: string, index: number) => Promise): Promise<{ messages: Message[]; result: CompactionResult; }>; /** * Determine which category a message belongs to */ private categorizeMessage; /** * Categorize all messages by type for smart compaction * * This method: * 1. Identifies system messages * 2. Separates recent messages (last N turns) that should never be compacted * 3. Identifies tool results in older messages * 4. Classifies remaining older messages as history * * @param messages All messages to categorize * @param preserveRecentTurns Number of recent turns to preserve (default: config value) */ categorizeMessages(messages: Message[], preserveRecentTurns?: number): Promise; /** * Find which categories are over their budget allocation * * @param categorized Categorized messages from categorizeMessages() * @returns Array of categories that exceed their budget, sorted by how much they exceed */ findOverBudgetCategories(categorized: CategorizedMessages): ContextCategory[]; /** * Smart compaction that respects category budgets * * Strategy: * 1. System messages: Never compacted (critical for agent behavior) * 2. Recent messages: Never compacted (needed for conversation continuity) * 3. Tool results: Save large results to files, replace with references * 4. History: Summarize with LLM * * The method compacts categories in order of how much they exceed their budget. */ smartCompact(messages: Message[], options: SmartCompactOptions): Promise<{ messages: Message[]; result: SmartCompactionResult; }>; /** * Compact tool results by saving large ones to files */ private compactToolResults; /** * Calculate utilization given a token count */ private calculateUtilization; /** * Estimate tokens for a string content */ estimateTokens(content: string): number; /** * Check if content can be added to a category * * Returns a pre-flight result with recommendations for action. */ canAddContent(estimatedTokens: number, category: ContextCategory): PreflightResult; /** * Get current verbosity level based on context utilization * * Tools should adapt their output based on this level. */ getVerbosityLevel(): VerbosityLevel; /** * Check if we're in minimal mode (critical context pressure) */ isMinimalMode(): boolean; /** * Check if emergency summarization is needed */ needsEmergencySummarization(): boolean; /** * Filter large content before adding to context * * Returns the filtered content and metadata about what was done. * The caller is responsible for saving to file if needed. */ filterContent(content: string, type: 'tool_result' | 'file' | 'error'): { content: string; filtered: boolean; originalLength: number; }; /** * Compact old messages by replacing large content with file references * * This is a placeholder - actual implementation requires file system access * which will be provided by the Agent or CLI layer. */ compact(messages: Message[], saveToFile: (content: string, index: number) => Promise): Promise<{ messages: Message[]; result: CompactionResult; }>; /** * Summarize conversation history * * This is a placeholder - actual implementation requires LLM call * which will be orchestrated by the Agent layer. */ summarize(messages: Message[], generateSummary: (messages: Message[]) => Promise): Promise<{ messages: Message[]; result: SummarizationResult; }>; /** * Summarize with support for multiple rounds and emergency mode * * Will perform multiple summarization rounds if needed to reach target utilization. * Throws ContextOverflowError if unable to reduce context sufficiently. */ summarizeWithRetry(messages: Message[], generateSummary: (messages: Message[]) => Promise, options?: { emergency?: boolean; maxRounds?: number; targetUtilization?: number; }): Promise<{ messages: Message[]; result: SummarizationResult; }>; /** * Check context and emit warning if needed */ checkAndWarn(): void; /** * Reset context manager state (for new conversations) */ reset(): void; }