/** * In-memory stream buffer + turn ledger for SSE reconnect support. * * Stores raw SSE bytes keyed by an arbitrary string (typically a * `chatSessionId`) so that a reconnecting client can replay buffered * events and continue receiving live events. Every buffered chunk is * tagged with a monotonically increasing `seq` so a client can resume * from the last frame it has already seen via `?fromSeq=N` style * resume. * * Each server process (agent-runtime pod, API server, custom user * service) creates its own `StreamBufferStore` singleton — no shared * state between processes. For cross-process durability a higher * layer (e.g. a Postgres-backed turn ledger) would wrap this store; * this in-memory variant is the hot cache. * * Lifted into the SDK from `@shogo/shared-runtime` (was AGPL) under MIT. */ type TurnStatus = 'active' | 'completed' | 'aborted' | 'failed'; interface TurnTerminal { reason?: string; error?: string; } interface StreamBufferWriter { /** Append a raw byte chunk and return the seq assigned to it. */ append(chunk: Uint8Array): number; /** Mark the turn as cleanly completed. Optional terminal reason. */ complete(reason?: string): void; /** * Mark the turn as failed (still keeps the buffer around for the grace * window so a reconnecting client can see the terminal state). */ fail(error: string): void; /** The turnId this writer is bound to. */ readonly turnId: string; /** Last seq written so far (0 if nothing has been appended). */ readonly lastSeq: number; } interface ReplayOptions { /** * Skip frames with seq <= fromSeq. Use 0 (or omit) to replay from the start. */ fromSeq?: number; } interface TurnSnapshot { turnId: string; status: TurnStatus; lastSeq: number; terminal: TurnTerminal | null; createdAt: number; completedAt: number | null; lastEventAt: number; } declare class StreamBufferStore { private buffers; private cleanupTimer; constructor(); /** * Create (or replace) a buffer for the given key. Any existing active * buffer is completed and discarded. Returns a writer bound to this * specific buffer instance, including the new `turnId`. */ create(key: string, opts?: { turnId?: string; }): StreamBufferWriter; /** * Append a chunk by key (loose, untyped writer). Returns the seq assigned, * or -1 if the buffer is unknown/inactive. */ append(key: string, chunk: Uint8Array): number; /** Mark a buffer as completed by key. Optional terminal reason. */ complete(key: string, reason?: string): void; /** * Abort a stream: complete subscribers and remove the buffer entirely. * Future resume/replay requests for this key will return null (→ 204). */ abort(key: string): void; has(key: string): boolean; /** Read-only metadata about a buffered turn. Useful for resume responses. */ snapshot(key: string): TurnSnapshot | null; /** * Create a ReadableStream that first replays all buffered chunks past * `opts.fromSeq` (default: 0 → replay everything), then subscribes for * any further live chunks until the stream completes. * * Returns null if no buffer exists for the key. */ createReplayStream(key: string, opts?: ReplayOptions): ReadableStream | null; cleanup(): void; dispose(): void; private completeBuffer; private failBuffer; } /** * TransformStream that copies every chunk into a StreamBufferStore while * passing it through unchanged. On flush/cancel, completes the buffer. * * Note: this convenience helper does NOT propagate seq numbers back to the * caller. Use `store.create(key)` directly if you need the writer's seq. */ declare function createBufferingTransform(store: StreamBufferStore, key: string): TransformStream; export { type ReplayOptions, StreamBufferStore, type StreamBufferWriter, type TurnSnapshot, type TurnStatus, type TurnTerminal, createBufferingTransform };