/** * ObservationalMemoryEngine: core orchestrator for the observational memory * system. * * Ties together the observer, reflector, and buffering coordinator. Manages * the observation slot, handles activation and reflection, and exposes the * state management API. * * The engine runs inside CompactionManager's transformContext hook. It does * NOT directly call ContextManager.setSlot(); instead, it manages the slot * content string and the integration layer handles writing it to the slot. * * References: * - observational-memory-architecture.md * - compaction-strategy.md * - context-manager.md */ import type { CompleteFn } from '../compaction.js'; import type { AgentMessage, AgentContext } from '../../context-manager.js'; import type { ObservationalMemoryConfig, ObservationalMemoryState, ObservationEvent, ReflectionEvent, RecallConfig } from './types.js'; export { BufferingCoordinator } from './buffering.js'; export { runObserver } from './observer.js'; export { runReflector, computeEffectiveReflectionThreshold } from './reflector.js'; export { createRecallTool } from './recall-tool.js'; export type { ObservationalMemoryConfig, ObservationalMemoryState, ObservationChunk, ObservationEvent, ReflectionEvent, ContinuationHint, RecallConfig, RecallResult, ObserverOutput, ReflectorOutput, BufferState, } from './types.js'; /** * Core orchestrator for the observational memory system. * * Coordinates the observer, reflector, and buffering coordinator to maintain * a compressed observation log of the conversation. Called from * CompactionManager during transformContext. */ export declare class ObservationalMemoryEngine { private config; private buffering; private completeFn; private observations; private continuationHint; private observationTokenCount; private generationCount; private contextWindow; private utilityModelContextWindow; private slotIndex; private logger; private observationHandlers; private reflectionHandlers; constructor(config: Partial, slotIndex: number); /** * Set the LLM completion function (wired to utilityComplete on CortexAgent). */ setCompleteFn(fn: CompleteFn): void; /** * Update the context window size. */ setContextWindow(contextWindow: number): void; /** * Update the utility model context window (for clamps). */ setUtilityModelContextWindow(utilityModelContextWindow: number): void; /** * Set the logger. */ setLogger(logger: { warn: (msg: string) => void; info: (msg: string) => void; }): void; /** * Register an observation event handler. */ onObservation(handler: (event: ObservationEvent) => void): void; /** * Register a reflection event handler. */ onReflection(handler: (event: ReflectionEvent) => void): void; /** * Core method called from CompactionManager during transformContext. * * Handles observation activation and reflection when context utilization * exceeds the activation threshold. Updates the observation slot and * trims observed messages from history. * * @param context - The AgentContext from transformContext * @param utilization - Current total context utilization (0-1) * @param slotCount - Number of slot messages at the start of the array * @param getHistory - Get conversation history from the context (post-slot) * @param setHistory - Set conversation history in the context (post-slot) * @param getSourceHistory - Get the original transcript history (agent.state.messages post-slot) * @param setSourceHistory - Replace the original transcript history * @returns Modified context with updated observations and trimmed history */ applyInTransformContext(context: AgentContext, utilization: number, slotCount: number, getHistory: (ctx: AgentContext) => AgentMessage[], setHistory: (ctx: AgentContext, history: AgentMessage[]) => AgentContext, getSourceHistory: () => AgentMessage[], setSourceHistory: (history: AgentMessage[]) => void): Promise; /** * Called at each turn_end event. Handles async buffer triggering. * * Computes the dynamic buffer interval and launches an async observer * if enough unobserved tokens have accumulated. * * @param totalTokens - Total tokens from the last LLM response * @param contextWindow - Current context window size * @param messages - Current conversation messages (post-slot) * @param slotCount - Number of slot messages */ onTurnEnd(totalTokens: number, contextWindow: number, messages: AgentMessage[], slotCount: number): void; /** * Build the full observation slot content. * * Assembles the preamble, optional recall instructions, observation block, * and optional continuation hints into a single string. */ buildSlotContent(): string; /** * Estimate the full slot content size for a given observation text. * * Used by the post-chunk utilization estimate to account for slot * overhead (preamble, XML wrappers, continuation hints) rather than * just the raw observation text. */ private buildSlotContentForEstimate; /** * Force a synchronous observation cycle. * * Used by consumers after critical corrections to ensure the observation * log captures the correction immediately. * * @param messages - The full message array (may include slot messages) * @param slotCount - Number of slot messages to skip */ triggerObservation(messages: AgentMessage[], slotCount: number): Promise; /** * Returns the current state for session persistence. */ getState(): ObservationalMemoryState; /** * Restore state from a previous session. * * Sets observations, continuation hint, token count, and generation count, * then restores the buffer (completed chunks + watermark) so the observer * work done in the previous session is not recomputed on resume. * * The watermark indexes into post-slot conversation history. Since * `restoreConversationHistory()` runs before this and splices the same * messages back at the same positions, the watermark aligns: the restored * chunks observe `messages[0:watermark]`, and the next activation trims * exactly those messages when it merges the chunk observations (no * duplication). No observer is launched on restore; the genuinely * unobserved remainder after the watermark is observed lazily on the next * `onTurnEnd` once it crosses the dynamic buffer interval. * * @param state - the persisted observational memory state * @param historyLength - length of the restored post-slot conversation * history. Used to clamp a watermark that drifted ahead of the saved * history (possible only on a hard crash; graceful save keeps them in * sync). Defaults to the saved watermark (no clamp) when omitted. */ restoreState(state: ObservationalMemoryState, historyLength?: number): void; /** * Returns the current slot content string. */ getSlotContent(): string; /** * Returns just the observation text. */ getObservations(): string; /** * Token count of activated observations only. */ getObservationTokenCount(): number; /** * Whether the observer or reflector is currently running in the background. */ isProcessing(): boolean; /** * Whether the observer specifically is in-flight. */ isObserverInFlight(): boolean; /** * Whether the reflector specifically is in-flight. */ isReflectorInFlight(): boolean; /** * Abort all in-flight operations. Delegates to buffering.abort(). */ abort(): void; /** * Whether recall is configured. */ hasRecall(): boolean; /** * Get the recall config if provided. */ getRecallConfig(): RecallConfig | undefined; /** * Check and handle reflection after observation activation. * * Determines whether reflection should run (sync, async, or none) based * on the current observation token count relative to the effective * reflection threshold. */ private handleReflection; /** * Build the observer config object without assigning undefined to optional * properties (exactOptionalPropertyTypes is enabled). */ private buildObserverConfig; /** * Build the reflector config object without assigning undefined to optional * properties (exactOptionalPropertyTypes is enabled). */ private buildReflectorConfig; /** * Merge buffered observation chunks into a single observation text. * * Concatenates all chunk observation texts with double newlines. Uses * the latest chunk's currentTask and suggestedResponse (latest wins). */ private mergeChunks; /** * Fire all observation handlers. Each handler is individually try/catch * wrapped to prevent one handler from breaking others. */ private fireObservationEvent; /** * Fire all reflection handlers. Each handler is individually try/catch * wrapped to prevent one handler from breaking others. */ private fireReflectionEvent; } //# sourceMappingURL=index.d.ts.map