Provides the NATS/Mingo-mode transport adapter for the unified chat surface, implementing the `UnifiedChatState` contract so the `useChat({ mode })` dispatcher can switch between NATS and SSE adapters without shell-side branching. ## Key Components ### `UseNatsChatAdapterConfig` Consumer-supplied configuration interface covering: - `dialogId` — active conversation identifier - `getNatsWsUrl` — factory returning the NATS WebSocket URL - `publishUserMessage` — consumer-owned send callback (HTTP POST or NATS publish) - `fetchChunks` — optional historical chunk fetcher for catchup - `clientConfig` — optional NATS auth credentials - `enableThinking` / `batchApprovalsEnabled` — processor feature flags ### `UseNatsChatAdapterOptions` - `active` — gates the live subscription; keeps message state alive while the mode is hidden ### `useNatsChatAdapter(config, options)` Main hook. Composes three internal hooks: ```text useNatsDialogSubscription → live NATS event tail ↓ decodeNatsChunk + reducer → chunk → ChatStreamEvent → state ↓ useChunkCatchup → back-fills missed chunks on reconnect/activation ``` Returns a full `UnifiedChatState` object including `messages`, `isLoading`, `streamingPhase`, `sendMessage`, `stopMessage`, and `clearMessages`. ## Usage Example ```typescript const chatState = useNatsChatAdapter( { dialogId: 'dialog-abc123', getNatsWsUrl: () => `wss://nats.example.com`, publishUserMessage: async (text, { dialogId }) => { await fetch('/api/chat', { method: 'POST', body: JSON.stringify({ text, dialogId }), }) }, fetchChunks: ({ dialogId, after }) => fetch(`/api/chunks?dialogId=${dialogId}&after=${after}`).then(r => r.json()), batchApprovalsEnabled: true, }, { active: isNatsModeVisible }, ) ``` > **Note:** `publishUserMessage` is intentionally consumer-owned — the adapter only handles optimistic UI updates and phase transitions; the actual transport is wired externally.