/** * Background memory extraction via a sub-agent loop. * * Inspired by hermes-agent's `background_review`: every N turns, a background * Agent (from pi-agent-core) is spawned with access to the memory tools. It * reads the current memory state, analyzes recent conversation, and * autonomously adds/replaces/removes entries — handling capacity management * that a single-shot LLM call cannot. * * Key design choices: * - Full agent loop (not a single `complete()` call) so the sub-agent can * react to tool results (e.g., capacity errors) and retry with replace. * - Reuses `createMemoryTools(store)` from tools.ts — same tool definitions * the main agent uses, cast to AgentTool (structurally compatible). * - Fire-and-forget: extraction runs async, never blocks the main agent. * - Mutual exclusion: skips if the main agent already wrote memory this turn. * - Bounded: max 8 turns per extraction run (abort via subscriber). */ import type { MemoryStore } from './store.js'; export interface ExtractionModelConfig { provider: string; model: string; } export interface ExtractionRunnerOptions { store: MemoryStore; modelConfig: ExtractionModelConfig; /** How many user turns between extraction runs. */ interval: number; /** Model registry for resolving provider/model. Falls back to the default ModelRuntime if omitted. */ modelRegistry?: { find(provider: string, model: string): unknown; getApiKeyAndHeaders(model: unknown): Promise<{ ok: boolean; apiKey?: string; headers?: Record; error?: string; }>; }; /** Callback for user-visible notifications. */ onNotify?: (message: string, level: 'info' | 'warning') => void; } export interface ExtractionRunner { /** Called on every turn_end event from the extension. Manages cadence internally. */ onTurnEnd(event: TurnEndEvent): void; /** Signal that the session is ending — abort any in-flight extraction. */ shutdown(): void; } export interface TurnEndEvent { turnIndex: number; message: AgentMessage; toolResults: ToolResultMessage[]; } interface AgentMessage { role: string; content?: unknown; timestamp?: number; } interface ToolResultMessage { toolName: string; isError: boolean; content?: unknown; } /** * Creates a background extraction runner that periodically spawns a sub-agent * to review recent conversation and write to the memory store. * * The runner is stateful: it counts turns, buffers messages, and manages * the in-flight state of the background agent. */ export declare function createExtractionRunner(opts: ExtractionRunnerOptions): ExtractionRunner; /** Check if main agent successfully wrote memory this turn. */ export declare function mainAgentWroteMemory(toolResults: ToolResultMessage[]): boolean; /** Extract plain text from a message content (string or content-block array). */ export declare function extractTextFromMessage(msg: AgentMessage): string; /** * Serialize messages into a compact text format for the sub-agent, capped at * MAX_CONTEXT_CHARS. Works backwards from newest to preserve the most recent context. */ export declare function serializeMessages(messages: Array<{ role: string; text: string; }>): string; /** * Count successful memory write actions in the sub-agent's transcript. * Looks for toolResult messages with success:true for add/replace/remove tools. */ export declare function countMemoryActions(messages: unknown[]): number; export {}; //# sourceMappingURL=background-extraction.d.ts.map