/** * Cortex session checkpoint — debounced `POST /sessions/ingest` at turn * settlement + `POST /log` lifecycle events (D-P2-3, scope §3). * * The local JSONL tree is the source of truth; Cortex ingests a snapshot so * the memory layer can reason over the run. Checkpoints are debounced and * idempotent: the payload carries `session_uuid` (the OpenKai session id) and * `source_path` so the Cortex dedup-by-session applies. We only checkpoint at * turn settlement (after `turn_end`/`session_end`), never mid-stream. * * Failure semantics (ren review): pending entries are only spliced and * `lastFlushHash` only advanced AFTER a successful POST — a failed flush * leaves the queue intact so the next settlement re-sends it. An explicit * `flushNow()` retries with bounded backoff (1s/2s/4s) before giving up. * `record()` dedups by seq watermark: the transport re-reads the whole JSONL * file each turn, and only entries newer than the last recorded seq are * appended, so recording stays O(new) instead of O(n²) over the session. * * Lifecycle events (`POST /log`) mark `started`/`stopped` so the run is * visible on the team_events feed (`openkai events --print`). */ import { CortexClient } from "../cortex/client.js"; import type { Entry } from "./session-store.js"; /** A message in the Cortex SessionIngest payload shape. */ export interface SessionIngestMessage { role: string; content: string; ts?: string | null; metadata?: Record; } /** The `POST /sessions/ingest` payload (matches the Cortex `SessionIngest` schema). */ export interface SessionIngestPayload { session_uuid: string; agent: string; task: string; source_path: string; provider: string; cwd: string; git_branch?: string; source_kind: string; metadata: Record; messages: SessionIngestMessage[]; } /** The `POST /log` payload (matches the Cortex `LogRequest` schema). */ export interface LogPayload { event_type: string; summary: string; category?: string; importance?: number; metadata?: Record; } /** Options for the checkpoint writer. */ export interface CortexCheckpointOptions { client: CortexClient; /** Agent name for the run (e.g. "bob"). */ agent: string; /** OpenKai session id (becomes `session_uuid`). */ sessionId: string; /** Absolute path to the local JSONL file. */ sourcePath: string; /** Provider id (e.g. "openrouter"). */ provider: string; /** Model id used for the run. */ modelId: string; /** Working directory of the run. */ cwd: string; /** Task/prompt description. */ task: string; /** Debounce window in ms (default 1500). */ debounceMs?: number; } /** * Debounced, idempotent Cortex session checkpoint writer. Collects settled * entries and flushes them to `POST /sessions/ingest` after a debounce window * at turn settlement. */ export declare class CortexCheckpoint { private readonly options; private pendingEntries; private pendingMessages; private timer; private lastFlushHash; /** Seq watermark: entries at or below this were already recorded. */ private lastRecordedSeq; constructor(options: CortexCheckpointOptions); /** * Record settled entries (called by the transport loop after a turn ends). * The caller re-reads the whole session file each turn, so only entries * newer than the seq watermark are appended — re-recording the full tree * every turn would be O(n²) over the session. */ record(entries: Entry[]): void; /** Emit a lifecycle `POST /log` event (started/stopped). */ logLifecycle(eventType: "started" | "stopped", summary: string): Promise; /** Flush the checkpoint now (debounce-bypass, bounded retry on failure). */ flushNow(): Promise; /** * Flush pending entries. State only advances on success: the pending queue * is spliced and `lastFlushHash` set AFTER the POST lands, so a failure * leaves everything queued for the next settlement. An explicit flush * (`withRetry`) retries with 1s/2s/4s backoff before giving up; a debounced * flush fails once and relies on the next `record()` to re-send. */ private flush; /** Advance state after a successful POST: drop the delivered prefix. */ private commitFlush; /** Schedule a debounced flush. */ private schedule; } /** The `POST /sessions/ingest` response shape. */ export interface SessionIngestResult { messages_inserted?: number; [key: string]: unknown; } /** Build the absolute source path for a session JSONL file. */ export declare function sessionSourcePath(root: string, sessionId: string): string; //# sourceMappingURL=cortex-checkpoint.d.ts.map