Provides the SSE (Server-Sent Events) transport adapter for the unified chat surface, implementing `UnifiedChatState` for Guide mode. Serves as the canonical replacement for the legacy `useEmbeddedChat` hook following the unified-chat refactor. ## Key Components ### Exported Types - **`DocSource`** — Opaque string identifier for a chat source (registry lookup handled server-side) - **`ChatSource`** — Structured source metadata including document type, navigation paths, grouped chip items, and platform targeting - **`DocChatMessage`** — Chat message shape with structured `segments`, `sources`, `chatRefs`, and `scrollAnchor` support - **`ChatTurnMeta`** — Per-turn metadata extracted from the streamed metadata frame (model, token counts, cache hit rate, routing decisions) - **`StreamingPhase`** — Re-exported from `unified-chat-state.types` for backward-compatible imports - **`UseSseChatAdapterOptions`** — DI options; notably `tableIdForDocumentType` for RAG table lookups - **`UseSseChatAdapterRuntimeOptions`** — Runtime gate (`active`) to suppress background slash-command fetches in inactive modes ### Internal Helpers - **`createEmptyTurnMeta()`** — Factory for a zeroed `ChatTurnMeta` object - **`escapeThinkingTags(text)`** — Escapes `<` to `<` so Claude's thinking-block XML tokens don't break `rehypeRaw` rendering - **`createDocStreamFn(...)`** — Factory that produces a per-call async generator handling SSE stream consumption, approval-action routing, and message history filtering (hidden messages excluded from wire format) ## Usage Example ```typescript import { useSseChatAdapter } from './use-sse-chat-adapter' import type { UseSseChatAdapterOptions } from './use-sse-chat-adapter' // Optional: override the default RAG table lookup for per-tenant types const options: UseSseChatAdapterOptions = { tableIdForDocumentType: (docType) => myTenantRegistry.tableIdFor(docType) ?? null, } const chatState = useSseChatAdapter(options, { active: true }) ``` **Key behavioral contracts:** - `source` is read from runtime context, never sent on the wire — the hub resolves it server-side via `currentPlatform()` - `tableIdForDocumentType` defaults to `defaultTableIdForDocumentType` (lib-baked map), so Ask / Display buttons work in embedders without any wiring - The SSE decoder/buffer lives inside the per-call closure to prevent cross-stream buffer corruption on rapid send-stop-send sequences ## Source [`use-sse-chat-adapter.ts`](https://github.com/flamingo-stack/openframe-oss-lib/blob/main/use-sse-chat-adapter.ts)