/** * Server-Sent Events implementation of BaseConnection. * * Unlike the classic GET + EventSource pattern, this server streams events * back as the response body of a POST to /chat. The request body is the * same OutgoingSocketMessage envelope used over the WebSocket, so * MessageManager parsing is shared. * * Wire shape: * POST {serverUrl}/med-assist/session/{sessionId}/chat * Headers: Content-Type: application/json * Accept: text/event-stream * sess-token: * x-agent-id: * Body: JSON-encoded OutgoingSocketMessage * Response: text/event-stream with `data: \n\n` frames whose payloads * match the IncomingSocketMessage shape. */ import { BaseConnection } from "../internal/connection/BaseConnection"; import { type OnOpenCallback, type SessionConfig } from "../internal/connection/types"; import { type OutgoingSocketMessage } from "../events/Events"; export interface SSEConnectionConfig extends SessionConfig { serverUrl: string; auth: { sessionToken: string; sessionId: string; }; } export declare class SSEConnection extends BaseConnection { readonly conversationId: string; private config; private connected; private activeStreamController; constructor(config: SSEConnectionConfig); /** * "Open" the SSE channel. There is no persistent socket — the connection * is considered ready as soon as the session/agent identifiers are set. * Each outgoing message opens its own short-lived streaming response. * * The open callback is deferred to a macrotask so it fires AFTER * `Synapse.startSession()` resolves and the consumer (e.g. widget's * `setUpEventListeners`) has had a chance to register the CONNECTED * listener. With WebSocket the real socket open is naturally async; we * have to simulate that here, otherwise the CONNECTED event is emitted * before anyone is listening for it. */ private connect; /** * Fire the open callback if the connection is already up by the time * the listener registers. Mirrors the queued-disconnect pattern in * BaseConnection so late-registering consumers don't miss the open * event. Deferred via setTimeout for the same reason as connect(). */ onOpen(callback: OnOpenCallback): void; private buildChatUrl; /** * Send an outgoing message. POSTs the same envelope used over the * WebSocket and streams the response back as SSE-encoded events. */ sendMessage(message: OutgoingSocketMessage): void; private streamChat; /** * Walk the buffer and dispatch every complete top-level JSON object it * contains, returning any trailing partial-object bytes that still need * more data. The server streams back-to-back objects (`{…}{…}{…}`) with * no separator, so we track brace depth (respecting strings/escapes) * to find each object boundary. Any whitespace or stray SSE prefixes * between objects is skipped automatically since we anchor on `{`. */ private extractJsonObjects; /** * Return the index of the matching closing brace for the `{` at `start`, * or -1 if the buffer ends before the object closes. String contents * and escape sequences are skipped so braces inside strings don't * affect the depth count. */ private findObjectEnd; close(): void; isConnected(): boolean; handleConnected(): void; }