/** * Web chat adapter — serves the standalone /chat page and embeddable widget, * handles WebSocket connections for bidirectional streaming. * * Thread naming: web-{sessionId} (session ID generated client-side, stored in localStorage) */ import * as http from 'http'; import { type MessagePipelineOptions } from '../../lib/gateway.js'; import type { NamespaceConfig } from '../config.js'; export interface WebChatAdapterConfig { /** The HTTP server to attach WebSocket upgrade handler to */ server: http.Server; /** Valid API keys for authentication */ apiKeys: string[]; /** Thread namespaces — prefix-scoped list visibility for app/test threads (task 097 P2). */ namespaces?: NamespaceConfig[]; /** Lucky Draw licence key (task 127) — absent = demo mode, namespaces capped. */ licenseKey?: string; /** Gateway pipeline options (basePath, claudePath, sharedMcpPort) */ pipelineOpts?: WebChatPipelineOpts; } /** * What the webchat adapter forwards to the message pipeline, plus the gateway-wide settings * it resolves per turn. Named once (task 152): the same Pick union was written out at four * sites, so a new field had to be added to all four before it could reach a spawn — the * shape of the task 113 defect. The daemon shares ONE such object by reference, so a live * PUT /api/config takes effect here with no restart (task 104). */ export type WebChatPipelineOpts = Partial> & { /** Gateway-wide voice-mode model id (task 152). Not a pipeline option — the adapter * resolves it to a per-turn `modelOverride` only when the turn is a voice turn. */ voiceModel?: string; /** Gateway-wide background-worker model id (task 179). Not a pipeline option either — * a worker is not a turn; the adapter hands it to `runWorker`. */ workerModel?: string; }; export interface WebChatAdapterHandle { stop: () => Promise; /** Broadcast a message event to all WebSocket clients watching a specific thread */ broadcastToThread: (threadName: string, event: Record) => void; /** Get all thread names that have at least one connected WebSocket client */ getConnectedThreadNames: () => string[]; } /** * Content hash (first 8 hex of sha1) for a static asset, or undefined if the * file cannot be read. Cached and invalidated on mtime+size change, so a rebuild * is picked up without a gateway restart. */ export declare function assetVersion(assetPath: string): string | undefined; /** * Append `?v=` to same-origin .js URLs in served HTML — both `src` * attributes and import-map values. * * Only `.js`/`.mjs` are stamped — chat.html's CSS is inline, so there is nothing * else to version. Assets already carrying a query string are left alone. * * Import maps need their own pass (task 132): the module URL lives in JSON inside * a `