import type { AgentMessage } from "@mariozechner/pi-agent-core"; // Result types export type AssembleResult = { /** Ordered messages to use as model context */ messages: AgentMessage[]; /** Estimated total tokens in assembled context */ estimatedTokens: number; /** Optional context-engine-provided instructions prepended to the runtime system prompt */ systemPromptAddition?: string; }; export type CompactResult = { ok: boolean; compacted: boolean; reason?: string; result?: { summary?: string; firstKeptEntryId?: string; tokensBefore: number; tokensAfter?: number; details?: unknown; }; }; export type IngestResult = { /** Whether the message was ingested (false if duplicate or no-op) */ ingested: boolean; }; export type IngestBatchResult = { /** Number of messages ingested from the supplied batch */ ingestedCount: number; }; export type BootstrapResult = { /** Whether bootstrap ran and initialized the engine's store */ bootstrapped: boolean; /** Number of historical messages imported (if applicable) */ importedMessages?: number; /** Optional reason when bootstrap was skipped */ reason?: string; }; export type ContextEngineInfo = { id: string; name: string; version?: string; /** True when the engine manages its own compaction lifecycle. */ ownsCompaction?: boolean; }; export type SubagentSpawnPreparation = { /** Roll back pre-spawn setup when subagent launch fails. */ rollback: () => void | Promise; }; export type SubagentEndReason = "deleted" | "completed" | "swept" | "released"; export type TranscriptRewriteReplacement = { /** Existing transcript entry id to replace on the active branch. */ entryId: string; /** Replacement message content for that entry. */ message: AgentMessage; }; export type TranscriptRewriteRequest = { /** Message entry replacements to apply in one branch-and-reappend pass. */ replacements: TranscriptRewriteReplacement[]; }; export type TranscriptRewriteResult = { /** Whether the active branch changed. */ changed: boolean; /** Estimated bytes removed from the active branch message payloads. */ bytesFreed: number; /** Number of transcript message entries rewritten. */ rewrittenEntries: number; /** Optional reason when no rewrite occurred. */ reason?: string; }; export type ContextEngineMaintenanceResult = TranscriptRewriteResult; export type ContextEngineRuntimeContext = Record & { /** * Safe transcript rewrite helper implemented by the runtime. * * Engines decide what is safe to rewrite; the runtime owns how the session * DAG is updated on disk. */ rewriteTranscriptEntries?: ( request: TranscriptRewriteRequest, ) => Promise; }; /** * ContextEngine defines the pluggable contract for context management. * * Required methods define a generic lifecycle; optional methods allow engines * to provide additional capabilities (retrieval, lineage, etc.). */ export interface ContextEngine { /** Engine identifier and metadata */ readonly info: ContextEngineInfo; /** * Initialize engine state for a session, optionally importing historical context. */ bootstrap?(params: { sessionId: string; sessionKey?: string; sessionFile: string; }): Promise; /** * Run transcript maintenance after bootstrap, successful turns, or compaction. * * Engines can use runtimeContext.rewriteTranscriptEntries() to request safe * branch-and-reappend transcript rewrites without depending on Pi internals. */ maintain?(params: { sessionId: string; sessionKey?: string; sessionFile: string; runtimeContext?: ContextEngineRuntimeContext; }): Promise; /** * Ingest a single message into the engine's store. */ ingest(params: { sessionId: string; sessionKey?: string; message: AgentMessage; /** True when the message belongs to a heartbeat run. */ isHeartbeat?: boolean; }): Promise; /** * Ingest a completed turn batch as a single unit. */ ingestBatch?(params: { sessionId: string; sessionKey?: string; messages: AgentMessage[]; /** True when the batch belongs to a heartbeat run. */ isHeartbeat?: boolean; }): Promise; /** * Execute optional post-turn lifecycle work after a run attempt completes. * Engines can use this to persist canonical context and trigger background * compaction decisions. */ afterTurn?(params: { sessionId: string; sessionKey?: string; sessionFile: string; messages: AgentMessage[]; /** Number of messages that existed before the prompt was sent. */ prePromptMessageCount: number; /** Optional auto-compaction summary emitted by the runtime. */ autoCompactionSummary?: string; /** True when this turn belongs to a heartbeat run. */ isHeartbeat?: boolean; /** Optional model context token budget for proactive compaction. */ tokenBudget?: number; /** Optional runtime-owned context for engines that need caller state. */ runtimeContext?: ContextEngineRuntimeContext; }): Promise; /** * Assemble model context under a token budget. * Returns an ordered set of messages ready for the model. */ assemble(params: { sessionId: string; sessionKey?: string; messages: AgentMessage[]; tokenBudget?: number; /** Current model identifier (e.g. "claude-opus-4", "gpt-4o", "qwen2.5-7b"). * Allows context engine plugins to adapt formatting per model. */ model?: string; /** The incoming user prompt for this turn (useful for retrieval-oriented engines). */ prompt?: string; }): Promise; /** * Compact context to reduce token usage. * May create summaries, prune old turns, etc. */ compact(params: { sessionId: string; sessionKey?: string; sessionFile: string; tokenBudget?: number; /** Force compaction even below the default trigger threshold. */ force?: boolean; /** Optional live token estimate from the caller's active context. */ currentTokenCount?: number; /** Controls convergence target; defaults to budget. */ compactionTarget?: "budget" | "threshold"; customInstructions?: string; /** Optional runtime-owned context for engines that need caller state. */ runtimeContext?: ContextEngineRuntimeContext; }): Promise; /** * Prepare context-engine-managed subagent state before the child run starts. * * Implementations can return a rollback handle that is invoked when spawn * fails after preparation succeeds. */ prepareSubagentSpawn?(params: { parentSessionKey: string; childSessionKey: string; ttlMs?: number; }): Promise; /** * Notify the context engine that a subagent lifecycle ended. */ onSubagentEnded?(params: { childSessionKey: string; reason: SubagentEndReason }): Promise; /** * Dispose of any resources held by the engine. */ dispose?(): Promise; }