/** The SERVER→CLIENT half of the wire's keepalive (blueprint §4.1 item 5, §4.2). * * Not to be confused with `heartbeat.ts`, which points the other way: * `withTurnHeartbeat` is the CLIENT beating `POST /threads/:id/heartbeat` so the * server can idle-abort an abandoned turn. This file is transport framing — * bytes the server puts on an SSE response so the connection stays visibly * alive while nothing interesting is happening. * * Two problems, one policy: * * 1. **Time to first byte.** A turn's first real chunk waits on a provider call. * Until then the response head may be sitting in a proxy buffer and the * client has nothing at all. * 2. **Long silent gaps.** A slow tool call streams nothing for its whole * duration; proxies and browsers drop connections that go quiet. * * The policy: emit a comment frame NOW, then one per `intervalMs` of silence. * SSE comments are ignored by every spec-compliant parser (the `eventsource-parser` * the ai-SDK's `DefaultChatTransport` uses treats a leading `:` as a comment and * emits nothing), so a keepalive is invisible to the client's message sequence. * It is deliberately NOT a `HarnessEvent` and NOT a `data-vendo-*` part: a * keepalive is not something that happened, it is the wire saying it is still there. */ /** The frame itself. An SSE comment — no event, no data, ~14 bytes. */ export declare const SSE_KEEPALIVE_FRAME = ": heartbeat\n\n"; /** Well inside the 30–60s idle windows proxies and load balancers default to. */ export declare const DEFAULT_SSE_KEEPALIVE_INTERVAL_MS = 15000; export interface SseKeepaliveOptions { /** Cadence of silence-filling frames. Defaults to 15s. */ intervalMs?: number; } /** Wrap an SSE `Response` so its first frame leaves at once and silence is * punctuated. * * Backpressure and ordering are preserved by construction: each pull races the * in-flight source read against the keepalive deadline, and the read that loses * is KEPT for the next pull — so a real chunk is never buffered, never delayed, * and never dropped. No timer outlives the stream either: the deadline is a * per-pull timeout, cleared on every path, and a closed or cancelled stream is * never pulled again. */ export declare function withSseKeepalive(response: Response, options?: SseKeepaliveOptions): Response;