import type { ConversationStreamStore } from "./conversation-stream.js"; import type { SessionData, SessionEntry, SessionStore } from "./types.js"; /** * Wrap a {@link SessionStore} so active-path appends are mirrored into an * append-only {@link ConversationStreamStore} projection (v2 A4). * * The SessionEntry DAG stays the single source of truth; the stream gives * clients offset-based catch-up + live tail. Two rules keep them coherent: * * 1. **Idempotent by entryId** — a crash between the DAG write and the * stream write is repaired on the next append: the projector diffs the * stream tail against the active path and re-emits anything missing. * 2. **Truncation is explicit** — the DAG can branch (fork/replay/ * checkpoint-restore rewrite `leafId`); the stream cannot. When `save()` * rewinds the active path, the projector appends a `truncated` record * and re-acquires the producer (epoch bump), so tailing clients see the * branch switch instead of silently reading a stale path. * * Projection failures are logged and swallowed — the conversation stream is * an observability surface and must never fail the session write itself; * the diff-repair on the next append restores consistency. */ export declare function withConversationProjection(store: SessionStore, streams: ConversationStreamStore, options?: { producerId?: string; onError?: (error: unknown) => void; }): SessionStore; export declare class ConversationProjector { private readonly streams; private readonly producerId; private readonly onError; private readonly producers; constructor(streams: ConversationStreamStore, options?: { producerId?: string; onError?: (error: unknown) => void; }); /** Mirror one appended entry, repairing any missed backlog first. */ projectAppend(store: SessionStore, sessionId: string, entry: SessionEntry): Promise; /** Handle whole-document saves (fork/replay/truncation rewrite the path). */ projectSave(data: SessionData): Promise; deleteStream(sessionId: string): Promise; private ensureProducer; /** Fold the stream into the currently-projected entry ids (truncations rewind). */ private readProjectedRecords; /** * Diff the projected tail against the current active path. A pure * extension appends the missing suffix; a divergence appends a * `truncated` record (with a fresh producer epoch) then the new suffix. */ private reproject; private appendRecords; } //# sourceMappingURL=conversation-projection.d.ts.map