/** The SERVER half of ai-SDK stream resume — blueprint §4.1 item 5, §4.2. * * The client half already ships in `ai@6`: `ChatTransport.reconnectToStream` * (what `useChat`'s `resumeStream()` calls) issues * * GET {api}/{chatId}/stream * * and expects either `204` — nothing to resume, go back to ready — or an SSE * body it parses with the SAME reducer as the original turn. That request * carries NO cursor, so the only protocol the contract allows is * REPLAY-FROM-THE-START-OF-THE-TURN: the server cannot know what the client * missed, so it hands back everything the turn has emitted and then keeps * following it live. (This is also how the SDK's own resumable-stream design * works. We are matching it, not inventing.) * * Why a turn survives its reader vanishing: `recordResumableTurn` tees the turn * response — the same tee-plus-detached-drain seam the harness runtime already * uses to checkpoint parked turns (`packages/vendo/src/harnesses/runtime.ts`). The recording * branch is drained by us, not by the client, so a client that stops reading * (recycled isolate, dropped socket, closed tab on `next dev`) does not stall * the turn. A client that genuinely ABORTS the fetch still kills the turn * through `request.signal` — the AGENT-3 fast path is untouched, and a resume * then replays as far as the turn actually got. * * State lifetime: per-turn, in memory, gone `RESUME_GRACE_MS` after the turn * settles. That is deliberately not a store table — there is nothing here worth * surviving a restart (a restart ends the turn), and the persisted transcript is * already the durable record. Frames are also capped: an in-memory buffer with * no ceiling is a memory footgun, and a turn past the cap simply becomes * unresumable (204) rather than unbounded. * * The registry lives on globalThis (Symbol.for) for the same reason * `turn-liveness.ts`'s does: HMR copies of this module under a dev server must * share one view of the in-flight turns. */ /** Wrap a streaming turn response so a dropped client can replay it. Returns the * response to hand the client; the recording branch drains itself. */ export declare function recordResumableTurn(response: Response, key: { threadId: string; subject: string; }): Response; /** The turn's stream from the beginning, or null when there is nothing to resume. * Principal-scoped: a foreign or unknown thread id is indistinguishable from an * idle one — no oracle, exactly like `touchActiveTurn`. */ export declare function resumableTurnStream(key: { threadId: string; subject: string; }): ReadableStream | null;