@invergent/website-widget 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts","../src/errors.ts","../src/protocol.ts","../src/translator.ts","../src/agent.ts"],"names":["EventType"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Wire-protocol and SDK-version constants.\n *\n * ``PROTOCOL_VERSION`` is the integer the SDK sends to the server so\n * future breaking protocol changes can be negotiated or hard-failed at\n * bootstrap instead of silently corrupting running embeds.\n *\n * ``SDK_VERSION`` travels in an ``X-Surogates-Widget-Version`` header on\n * every request so server logs can correlate a buggy client build with\n * its error surface. Kept in sync with ``package.json`` manually; the\n * build pipeline can replace it at bundle time in a later phase.\n */\n\nexport const PROTOCOL_VERSION = 1;\n\nexport const SDK_VERSION = '0.1.0';\n\n// Header names we read/write. Lifted to constants so tests, the client,\n// and the protocol layer can't drift from each other.\nexport const CSRF_HEADER = 'X-CSRF-Token';\nexport const VERSION_HEADER = 'X-Surogates-Widget-Version';\n\n// URL segments of the website-channel API, relative to ``apiUrl``.\nexport const PATH_BOOTSTRAP = '/v1/website/sessions';\nexport const PATH_MESSAGES = (sessionId: string) =>\n `/v1/website/sessions/${sessionId}/messages`;\nexport const PATH_EVENTS = (sessionId: string, after: number) =>\n `/v1/website/sessions/${sessionId}/events?after=${after}`;\nexport const PATH_END = (sessionId: string) =>\n `/v1/website/sessions/${sessionId}/end`;\n\n// Surogates native event type strings the SSE stream carries. Source\n// of truth: ``surogates/session/events.py``. Duplicated here so the\n// translator can switch on them without a network of string literals\n// scattered through the code.\nexport const SURG_EVENT = {\n USER_MESSAGE: 'user.message',\n LLM_REQUEST: 'llm.request',\n LLM_RESPONSE: 'llm.response',\n LLM_THINKING: 'llm.thinking',\n LLM_DELTA: 'llm.delta',\n TOOL_CALL: 'tool.call',\n TOOL_RESULT: 'tool.result',\n SANDBOX_PROVISION: 'sandbox.provision',\n SANDBOX_EXECUTE: 'sandbox.execute',\n SANDBOX_RESULT: 'sandbox.result',\n SANDBOX_DESTROY: 'sandbox.destroy',\n SESSION_START: 'session.start',\n SESSION_PAUSE: 'session.pause',\n SESSION_RESUME: 'session.resume',\n SESSION_COMPLETE: 'session.complete',\n SESSION_FAIL: 'session.fail',\n SESSION_DONE: 'session.done',\n CONTEXT_COMPACT: 'context.compact',\n MEMORY_UPDATE: 'memory.update',\n EXPERT_DELEGATION: 'expert.delegation',\n EXPERT_RESULT: 'expert.result',\n EXPERT_FAILURE: 'expert.failure',\n POLICY_DENIED: 'policy.denied',\n POLICY_ALLOWED: 'policy.allowed',\n HARNESS_CRASH: 'harness.crash',\n} as const;\n","/**\n * Error taxonomy for the website-widget SDK.\n *\n * Consumers should not have to parse strings to tell \"the key is wrong\"\n * apart from \"the network blinked\" -- different remediations apply.\n * Every error thrown or emitted by the SDK derives from\n * :class:`SurogatesError` so a single ``instanceof`` catch is always\n * safe; the subclasses encode the specific failure mode.\n */\n\nexport class SurogatesError extends Error {\n /** HTTP status code when the error originated from a server response. */\n readonly status?: number;\n /** Raw server detail string, if any. */\n readonly detail?: string;\n\n constructor(message: string, opts?: { status?: number; detail?: string; cause?: unknown }) {\n super(message);\n this.name = 'SurogatesError';\n if (opts?.status !== undefined) this.status = opts.status;\n if (opts?.detail !== undefined) this.detail = opts.detail;\n if (opts?.cause !== undefined) (this as { cause?: unknown }).cause = opts.cause;\n }\n}\n\n/**\n * The publishable key is invalid, expired, or the request Origin is not\n * in the agent's allow-list. Non-retryable: the embed is misconfigured\n * and no amount of backoff will help.\n */\nexport class SurogatesAuthError extends SurogatesError {\n constructor(message: string, opts?: { status?: number; detail?: string }) {\n super(message, opts);\n this.name = 'SurogatesAuthError';\n }\n}\n\n/**\n * Rate-limited (HTTP 429) or the per-session message/token cap has\n * been reached. Retryable after a backoff; the SDK exposes this as a\n * distinct type so consumers can show a \"slow down\" indicator instead\n * of a generic failure.\n */\nexport class SurogatesRateLimitError extends SurogatesError {\n /** Seconds the server asked us to wait, if it included a Retry-After header. */\n readonly retryAfter?: number;\n\n constructor(message: string, opts?: { status?: number; retryAfter?: number; detail?: string }) {\n super(message, opts);\n this.name = 'SurogatesRateLimitError';\n if (opts?.retryAfter !== undefined) this.retryAfter = opts.retryAfter;\n }\n}\n\n/**\n * The protocol itself is the problem -- the SDK received a response it\n * can't interpret, or a cookie/CSRF invariant was violated. Indicates\n * an SDK-server version mismatch or a corrupt response; raises the\n * priority of whatever error reporting channel the host app has.\n */\nexport class SurogatesProtocolError extends SurogatesError {\n constructor(message: string, opts?: { status?: number; detail?: string; cause?: unknown }) {\n super(message, opts);\n this.name = 'SurogatesProtocolError';\n }\n}\n\n/**\n * Transport-level failure: network drop, CORS preflight refusal, DNS,\n * browser offline, 5xx from an ingress/load balancer. Retryable by\n * design; the SDK does not auto-retry today -- the caller should back\n * off and re-issue the operation (typically by re-invoking\n * ``runAgent``). A future revision may add internal exponential\n * backoff; consumers should continue to surface these errors to the\n * user rather than assume they'll be swallowed.\n */\nexport class SurogatesNetworkError extends SurogatesError {\n constructor(message: string, opts?: { cause?: unknown }) {\n super(message, opts);\n this.name = 'SurogatesNetworkError';\n }\n}\n","/**\n * HTTP + SSE wire layer.\n *\n * Pure functions that talk to the website channel's three endpoints,\n * isolated here so :class:`WebsiteAgentClient` can stay focused on\n * state-machine orchestration. All fetches use ``credentials:\n * 'include'`` so the browser sends the HttpOnly session cookie that\n * ``bootstrap`` set -- without it the message/SSE/end routes return\n * 401 and the whole channel falls apart.\n *\n * SSE is handled by the native ``EventSource`` rather than a custom\n * fetch-based parser because the native implementation is zero bytes,\n * auto-reconnects on network drops, and respects browser-internal\n * backoff heuristics. The one thing it can't do is resume with a\n * server-side cursor, so we manage the ``?after=N`` reopen logic\n * explicitly in :class:`WebsiteAgentClient`.\n */\n\nimport {\n CSRF_HEADER,\n PATH_BOOTSTRAP,\n PATH_END,\n PATH_EVENTS,\n PATH_MESSAGES,\n VERSION_HEADER,\n SDK_VERSION,\n} from './constants.js';\nimport {\n SurogatesAuthError,\n SurogatesNetworkError,\n SurogatesProtocolError,\n SurogatesRateLimitError,\n} from './errors.js';\n\nexport interface BootstrapResult {\n sessionId: string;\n csrfToken: string;\n expiresAt: number;\n agentName: string;\n}\n\n/**\n * Shape the website channel returns from ``POST /v1/website/sessions``.\n * Mirrors the pydantic ``BootstrapResponse`` server-side; kept separate\n * from :class:`BootstrapResult` (camelCase) so future protocol drift\n * only needs to move here, not through every consumer.\n */\ninterface RawBootstrapBody {\n session_id: string;\n csrf_token: string;\n expires_at: number;\n agent_name: string;\n}\n\n/** Fetch wrapper that normalises every HTTP failure into a typed error. */\nasync function doFetch(\n url: string,\n init: RequestInit & { headers?: Record<string, string> },\n): Promise<Response> {\n let response: Response;\n try {\n response = await fetch(url, {\n ...init,\n credentials: 'include',\n headers: {\n ...init.headers,\n [VERSION_HEADER]: SDK_VERSION,\n },\n });\n } catch (cause) {\n // ``fetch`` only rejects on true network failure / CORS preflight\n // refusal. HTTP error responses resolve.\n throw new SurogatesNetworkError('Network request failed', { cause });\n }\n return response;\n}\n\n/** Pull the ``detail`` string out of the server's error body, best-effort. */\nasync function extractDetail(response: Response): Promise<string | undefined> {\n try {\n const body = (await response.json()) as { detail?: unknown };\n return typeof body.detail === 'string' ? body.detail : undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function raiseForStatus(response: Response, action: string): Promise<never> {\n const detail = await extractDetail(response);\n if (response.status === 401 || response.status === 403) {\n throw new SurogatesAuthError(`${action} rejected (${response.status})`, {\n status: response.status,\n ...(detail !== undefined && { detail }),\n });\n }\n if (response.status === 429) {\n const retryAfterHeader = response.headers.get('Retry-After');\n const retryAfter = retryAfterHeader ? Number(retryAfterHeader) : undefined;\n throw new SurogatesRateLimitError(`${action} rate-limited`, {\n status: response.status,\n ...(retryAfter !== undefined && Number.isFinite(retryAfter) && { retryAfter }),\n ...(detail !== undefined && { detail }),\n });\n }\n // 5xx responses are transport-layer hiccups -- an ingress, a load\n // balancer, or a restarting worker -- not SDK/server protocol\n // drift. Surface them as :class:`SurogatesNetworkError` so\n // consumers treat them as retryable (matching the documented\n // semantics of that class) and don't escalate them as priority-1\n // diagnostics the way a genuine ``SurogatesProtocolError`` warrants.\n if (response.status >= 500) {\n throw new SurogatesNetworkError(\n `${action} failed (${response.status}${detail ? `: ${detail}` : ''})`,\n );\n }\n throw new SurogatesProtocolError(`${action} failed (${response.status})`, {\n status: response.status,\n ...(detail !== undefined && { detail }),\n });\n}\n\n/** ``POST /v1/website/sessions`` with a publishable key. */\nexport async function bootstrap(\n apiUrl: string,\n publishableKey: string,\n): Promise<BootstrapResult> {\n const response = await doFetch(apiUrl + PATH_BOOTSTRAP, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${publishableKey}`,\n 'Content-Type': 'application/json',\n },\n });\n // Accept any 2xx -- the route currently declares 201, but a future\n // server change to 200 (or a proxy that strips the status to 200)\n // must not silently break the SDK. Non-2xx still funnels through\n // ``raiseForStatus`` to get the right typed error back.\n if (!response.ok) {\n await raiseForStatus(response, 'Bootstrap');\n }\n let body: RawBootstrapBody;\n try {\n body = (await response.json()) as RawBootstrapBody;\n } catch (cause) {\n throw new SurogatesProtocolError('Bootstrap returned non-JSON body', { cause });\n }\n if (!body || typeof body.session_id !== 'string' || typeof body.csrf_token !== 'string') {\n throw new SurogatesProtocolError('Bootstrap response missing required fields');\n }\n return {\n sessionId: body.session_id,\n csrfToken: body.csrf_token,\n expiresAt: Number(body.expires_at) || 0,\n agentName: body.agent_name ?? '',\n };\n}\n\n/** ``POST /v1/website/sessions/{id}/messages`` with cookie + CSRF. */\nexport async function sendMessage(\n apiUrl: string,\n sessionId: string,\n csrfToken: string,\n content: string,\n): Promise<{ eventId: number }> {\n const response = await doFetch(apiUrl + PATH_MESSAGES(sessionId), {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n [CSRF_HEADER]: csrfToken,\n },\n body: JSON.stringify({ content }),\n });\n // Any 2xx is a successful enqueue; the route declares 202 today\n // but we don't want to break if it's ever relaxed to 200.\n if (!response.ok) {\n await raiseForStatus(response, 'Send message');\n }\n const body = (await response.json().catch(() => ({}))) as { event_id?: number };\n return { eventId: Number(body.event_id ?? 0) };\n}\n\n/** ``POST /v1/website/sessions/{id}/end``. Best-effort; swallows errors. */\nexport async function endSession(\n apiUrl: string,\n sessionId: string,\n csrfToken: string,\n): Promise<void> {\n try {\n await doFetch(apiUrl + PATH_END(sessionId), {\n method: 'POST',\n headers: { [CSRF_HEADER]: csrfToken },\n });\n } catch {\n // The local cookie/state is always cleared by the caller regardless.\n // A failed end() is not worth surfacing -- the session will idle out.\n }\n}\n\n/** Open an SSE connection at ``?after=<cursor>``. Caller owns the close. */\nexport function openEventStream(\n apiUrl: string,\n sessionId: string,\n cursor: number,\n): EventSource {\n const url = apiUrl + PATH_EVENTS(sessionId, cursor);\n // ``withCredentials`` is the non-obvious flag that makes EventSource\n // send the session cookie cross-origin. Without it the server sees\n // an unauthenticated request and returns 401, and the EventSource\n // quietly goes into reconnect loops without surfacing the reason.\n return new EventSource(url, { withCredentials: true });\n}\n","/**\n * Pure event translation: Surogates wire events → AG-UI ``BaseEvent``\\ s.\n *\n * The SSE stream delivered by ``/v1/website/sessions/{id}/events`` carries\n * event types defined in ``surogates/session/events.py``\n * (``user.message``, ``llm.delta``, ``llm.response``, ``tool.call``, ...).\n * AG-UI consumers expect a different, standardised vocabulary\n * (``TEXT_MESSAGE_START`` / ``CONTENT`` / ``END`` triads, ``TOOL_CALL_*``,\n * ``RUN_STARTED`` / ``RUN_FINISHED``, ``STATE_SNAPSHOT``, etc.). This\n * module is the contract.\n *\n * Design notes\n * ------------\n * * **Pure and state-carried.** ``Translator`` is a class only because\n * a few decisions need a tiny bit of memory (have we emitted the\n * running ``TextMessageStart`` yet? how many tool calls are\n * outstanding? did the last ``llm.response`` signal end-of-turn?).\n * It does not touch the network or any globals; every instance is a\n * single run's translation state and discardable after\n * ``RUN_FINISHED``.\n *\n * * **Chunks over triads.** AG-UI provides\n * ``TEXT_MESSAGE_CHUNK`` / ``TOOL_CALL_CHUNK`` convenience events\n * that expand to the START / CONTENT / END triad automatically via\n * the client-side ``transformChunks`` pipeline. Surogates already\n * streams in chunks (``llm.delta``, full-payload ``tool.call``), so\n * emitting chunk events keeps the translator short and matches the\n * data we actually have.\n *\n * * **Unknown → CUSTOM.** Platform-specific events we cannot map to\n * first-class AG-UI events (memory updates, saga step transitions,\n * session resets, context compaction) are emitted as AG-UI ``CUSTOM``\n * events with ``name`` set to the Surogates event type and ``value``\n * set to the raw payload. Consumers that care can match on\n * ``name``; consumers that don't simply ignore CUSTOM.\n *\n * * **End-of-turn heuristic.** Our server does not emit a\n * ``turn.complete`` event. Per-turn completion is inferred: an\n * ``llm.response`` whose payload indicates the model is done (no\n * pending tool calls, ``finish_reason`` of ``stop`` / ``end_turn``)\n * flips ``isTurnComplete`` to ``true``. The caller emits\n * ``RUN_FINISHED`` and closes the stream. A ``session.done`` SSE\n * sentinel also completes the turn.\n */\n\nimport type { BaseEvent } from '@ag-ui/client';\nimport { EventType } from '@ag-ui/client';\n\nimport { SURG_EVENT } from './constants.js';\n\n/** Minimal shape of a single SSE frame we read from the server. */\nexport interface SurogatesFrame {\n /** Monotonic server-side event id (cursor for reconnect). */\n id: number;\n /** Surogates event type (``user.message``, ``llm.delta``, etc.). */\n type: string;\n /** Parsed JSON payload from the ``data:`` line. */\n data: unknown;\n}\n\n/** Payload keys we pull off ``llm.response`` events to detect end-of-turn. */\ninterface LlmResponsePayload {\n content?: string;\n tool_calls?: unknown[];\n finish_reason?: string;\n stop_reason?: string;\n message_id?: string;\n id?: string;\n}\n\n/** Payload keys for ``llm.delta`` events. */\ninterface LlmDeltaPayload {\n delta?: string;\n content?: string;\n message_id?: string;\n}\n\n/** Payload keys for ``tool.call`` events. */\ninterface ToolCallPayload {\n tool_call_id?: string;\n name?: string;\n arguments?: unknown;\n}\n\n/** Payload keys for ``tool.result`` events. */\ninterface ToolResultPayload {\n tool_call_id?: string;\n name?: string;\n content?: string;\n}\n\n/** Payload keys for ``llm.thinking`` events. */\ninterface LlmThinkingPayload {\n delta?: string;\n content?: string;\n message_id?: string;\n}\n\n/** Payload keys for ``policy.denied`` events. */\ninterface PolicyDeniedPayload {\n tool?: string;\n reason?: string;\n}\n\n/** Payload keys for expert delegation events. */\ninterface ExpertDelegationPayload {\n expert_name?: string;\n task?: string;\n}\n\ninterface ExpertResultPayload {\n expert_name?: string;\n result?: unknown;\n}\n\nconst END_OF_TURN_FINISH_REASONS = new Set(['stop', 'end_turn', 'length']);\n\n/**\n * Finish reasons that explicitly signal \"more work is coming\" --\n * currently just OpenAI-style ``tool_calls``. Treated as an\n * affirmative negation of end-of-turn even if the provider happens\n * to emit an empty ``tool_calls`` array alongside it (some adapters\n * do). Kept as a set so future provider quirks can be added without\n * touching the detection logic.\n */\nconst CONTINUATION_FINISH_REASONS = new Set(['tool_calls', 'function_call', 'tool_use']);\n\n/**\n * Stateful translator for one run.\n *\n * The caller is expected to build a fresh instance per ``runAgent`` turn\n * and discard it after the run finishes; every method is idempotent and\n * thread-safe only in the single-SSE-consumer sense (JavaScript events\n * are single-threaded).\n */\nexport class Translator {\n /**\n * Running message id for the current streaming assistant message.\n * Re-used across ``llm.delta`` frames so every chunk targets the\n * same AG-UI message -- that's what makes the client-side\n * ``transformChunks`` stitch them into one logical message.\n */\n private currentMessageId: string | undefined;\n\n /**\n * Running message id for the current reasoning stream, if any.\n * Kept separate from ``currentMessageId`` so reasoning deltas never\n * accidentally merge into the assistant content stream.\n */\n private currentReasoningId: string | undefined;\n\n /**\n * Tool calls that have been announced (``TOOL_CALL_CHUNK`` emitted)\n * but have not yet received a matching ``tool.result``. Non-empty\n * means the turn is mid-execution even if an ``llm.response`` looks\n * final.\n */\n private pendingToolCalls = new Set<string>();\n\n /** Set once we've seen an end-of-turn signal. */\n private _turnComplete = false;\n\n get isTurnComplete(): boolean {\n return this._turnComplete;\n }\n\n /**\n * Translate one SSE frame into zero or more AG-UI events.\n *\n * Returns an empty array when the frame carries no user-visible\n * information (internal bookkeeping events like ``harness.wake``).\n * Returns multiple events when a single Surogates event corresponds\n * to a chunk triad that the AG-UI client can't reconstruct on its\n * own -- though we try to use chunk events to keep this to one\n * output event per input in the common path.\n */\n translate(frame: SurogatesFrame): BaseEvent[] {\n switch (frame.type) {\n case SURG_EVENT.LLM_DELTA:\n return this.handleLlmDelta(frame);\n\n case SURG_EVENT.LLM_RESPONSE:\n return this.handleLlmResponse(frame);\n\n case SURG_EVENT.LLM_THINKING:\n return this.handleLlmThinking(frame);\n\n case SURG_EVENT.TOOL_CALL:\n return this.handleToolCall(frame);\n\n case SURG_EVENT.TOOL_RESULT:\n return this.handleToolResult(frame);\n\n case SURG_EVENT.POLICY_DENIED:\n return this.handlePolicyDenied(frame);\n\n case SURG_EVENT.EXPERT_DELEGATION:\n return this.handleExpertDelegation(frame);\n\n case SURG_EVENT.EXPERT_RESULT:\n return this.handleExpertResult(frame);\n\n case SURG_EVENT.EXPERT_FAILURE:\n return this.asCustom(frame);\n\n case SURG_EVENT.SESSION_FAIL:\n case SURG_EVENT.HARNESS_CRASH:\n return this.handleTerminalFailure(frame);\n\n case SURG_EVENT.SESSION_DONE:\n case SURG_EVENT.SESSION_COMPLETE:\n this._turnComplete = true;\n return [];\n\n // Frames we do not surface to AG-UI consumers: internal\n // orchestration (``user.message`` is already in the consumer's\n // own ``agent.messages``; ``llm.request``, ``session.start``,\n // ``sandbox.*``, ``harness.wake`` are implementation details).\n case SURG_EVENT.USER_MESSAGE:\n case SURG_EVENT.LLM_REQUEST:\n case SURG_EVENT.SESSION_START:\n case SURG_EVENT.SESSION_PAUSE:\n case SURG_EVENT.SESSION_RESUME:\n case SURG_EVENT.SANDBOX_PROVISION:\n case SURG_EVENT.SANDBOX_EXECUTE:\n case SURG_EVENT.SANDBOX_RESULT:\n case SURG_EVENT.SANDBOX_DESTROY:\n case SURG_EVENT.POLICY_ALLOWED:\n return [];\n\n // Everything else (``memory.update``, ``context.compact``,\n // saga events, future server additions) is forwarded as CUSTOM\n // so advanced consumers that want that visibility can still\n // subscribe -- without us pre-committing to a particular AG-UI\n // shape for a Surogates-specific event that might evolve.\n default:\n return this.asCustom(frame);\n }\n }\n\n // ------------------------------------------------------------------\n // Individual handlers\n // ------------------------------------------------------------------\n\n private handleLlmDelta(frame: SurogatesFrame): BaseEvent[] {\n const payload = (frame.data ?? {}) as LlmDeltaPayload;\n const delta = payload.delta ?? payload.content ?? '';\n if (!delta) return [];\n\n // Chunks must carry a stable messageId on the FIRST chunk so\n // transformChunks can open the TextMessageStart; later chunks can\n // reuse the same id. Surogates streams multiple assistant turns\n // in one session, so we mint a new id whenever we've closed one\n // (set back to undefined in handleLlmResponse).\n const messageId = this.currentMessageId ?? payload.message_id ?? this.mintMessageId(frame.id);\n this.currentMessageId = messageId;\n\n return [\n {\n type: EventType.TEXT_MESSAGE_CHUNK,\n messageId,\n role: 'assistant',\n delta,\n } as BaseEvent,\n ];\n }\n\n private handleLlmResponse(frame: SurogatesFrame): BaseEvent[] {\n const payload = (frame.data ?? {}) as LlmResponsePayload;\n const events: BaseEvent[] = [];\n\n // Close any open assistant message by resetting the current id.\n // transformChunks will emit TEXT_MESSAGE_END when the next chunk\n // targets a new messageId (or the stream completes). If no delta\n // was seen but the response carries content, emit a single chunk\n // so downstream consumers get something to render.\n if (!this.currentMessageId && payload.content) {\n const messageId = payload.message_id ?? payload.id ?? this.mintMessageId(frame.id);\n events.push({\n type: EventType.TEXT_MESSAGE_CHUNK,\n messageId,\n role: 'assistant',\n delta: payload.content,\n } as BaseEvent);\n }\n this.currentMessageId = undefined;\n\n // End-of-turn detection is the conjunction of three guards:\n // 1. ``finish_reason`` does NOT say \"more work is coming\". Some\n // provider adapters emit a bare ``llm.response`` with\n // ``finish_reason: 'tool_calls'`` and an empty ``tool_calls``\n // array when they stream the \"I'll use a tool now\" sentinel\n // separately from the tool definitions. Treating this as\n // end-of-turn would flip us done before the tool calls even\n // arrive. The positive check on ``CONTINUATION_FINISH_REASONS``\n // rules that out first.\n // 2. The ``tool_calls`` array is empty. If the response carries\n // any tool calls at all, more frames follow.\n // 3. No tool calls that were already announced are still pending\n // a ``tool.result``. Belt-and-suspenders: if the server sends\n // ``llm.response`` before all tool results drain, we keep the\n // stream open until they do.\n const toolCalls = Array.isArray(payload.tool_calls) ? payload.tool_calls : [];\n const finish = payload.finish_reason ?? payload.stop_reason ?? '';\n if (CONTINUATION_FINISH_REASONS.has(finish)) {\n return events;\n }\n const modelDone =\n toolCalls.length === 0 && (finish === '' || END_OF_TURN_FINISH_REASONS.has(finish));\n if (modelDone && this.pendingToolCalls.size === 0) {\n this._turnComplete = true;\n }\n\n return events;\n }\n\n private handleLlmThinking(frame: SurogatesFrame): BaseEvent[] {\n const payload = (frame.data ?? {}) as LlmThinkingPayload;\n const delta = payload.delta ?? payload.content ?? '';\n if (!delta) return [];\n\n const messageId = this.currentReasoningId ?? payload.message_id ?? this.mintMessageId(frame.id);\n const isNew = this.currentReasoningId !== messageId;\n this.currentReasoningId = messageId;\n\n const events: BaseEvent[] = [];\n if (isNew) {\n events.push({\n type: EventType.REASONING_START,\n messageId,\n } as BaseEvent);\n events.push({\n type: EventType.REASONING_MESSAGE_START,\n messageId,\n role: 'reasoning',\n } as BaseEvent);\n }\n events.push({\n type: EventType.REASONING_MESSAGE_CONTENT,\n messageId,\n delta,\n } as BaseEvent);\n return events;\n }\n\n private handleToolCall(frame: SurogatesFrame): BaseEvent[] {\n const payload = (frame.data ?? {}) as ToolCallPayload;\n const toolCallId = payload.tool_call_id ?? `tc-${frame.id}`;\n const toolCallName = payload.name ?? 'unknown_tool';\n\n // Close any running reasoning/text message first so the tool call\n // slots in cleanly between them. We don't emit explicit END\n // events because transformChunks handles that when messageId\n // switches to undefined; we just clear our running ids.\n this.currentMessageId = undefined;\n this.currentReasoningId = undefined;\n\n this.pendingToolCalls.add(toolCallId);\n\n // Surogates gives us the FULL arguments in one frame; emit as a\n // single TOOL_CALL_CHUNK which the AG-UI client expands into\n // START + ARGS + END.\n const args =\n typeof payload.arguments === 'string'\n ? payload.arguments\n : JSON.stringify(payload.arguments ?? {});\n\n return [\n {\n type: EventType.TOOL_CALL_CHUNK,\n toolCallId,\n toolCallName,\n delta: args,\n } as BaseEvent,\n ];\n }\n\n private handleToolResult(frame: SurogatesFrame): BaseEvent[] {\n const payload = (frame.data ?? {}) as ToolResultPayload;\n const toolCallId = payload.tool_call_id ?? `tc-${frame.id}`;\n const content = payload.content ?? '';\n\n this.pendingToolCalls.delete(toolCallId);\n\n // AG-UI's TOOL_CALL_RESULT needs a ``messageId`` on the tool\n // message it lands on in the assistant history; we synthesise a\n // per-call id so the AG-UI message reducer can link result to\n // call. Consumers that need stable message ids across reconnects\n // can pull them from ``frame.id``.\n return [\n {\n type: EventType.TOOL_CALL_RESULT,\n messageId: `tr-${frame.id}`,\n toolCallId,\n content,\n role: 'tool',\n } as BaseEvent,\n ];\n }\n\n private handlePolicyDenied(frame: SurogatesFrame): BaseEvent[] {\n const payload = (frame.data ?? {}) as PolicyDeniedPayload;\n // Policy denials are informational -- the LLM still continues and\n // the next ``llm.response`` will explain the refusal in natural\n // language. Surface as CUSTOM so UIs can render a \"blocked\" badge\n // without hijacking the run lifecycle.\n return [\n {\n type: EventType.CUSTOM,\n name: SURG_EVENT.POLICY_DENIED,\n value: { tool: payload.tool, reason: payload.reason },\n } as BaseEvent,\n ];\n }\n\n private handleExpertDelegation(frame: SurogatesFrame): BaseEvent[] {\n const payload = (frame.data ?? {}) as ExpertDelegationPayload;\n const name = payload.expert_name ?? 'expert';\n // Expert delegation is a natural fit for STEP_STARTED -- it's a\n // bounded sub-task the host can render as a progress row. Kept\n // paired with STEP_FINISHED in ``handleExpertResult``.\n return [\n {\n type: EventType.STEP_STARTED,\n stepName: `expert:${name}`,\n } as BaseEvent,\n ];\n }\n\n private handleExpertResult(frame: SurogatesFrame): BaseEvent[] {\n const payload = (frame.data ?? {}) as ExpertResultPayload;\n const name = payload.expert_name ?? 'expert';\n return [\n {\n type: EventType.STEP_FINISHED,\n stepName: `expert:${name}`,\n } as BaseEvent,\n ];\n }\n\n private handleTerminalFailure(frame: SurogatesFrame): BaseEvent[] {\n this._turnComplete = true;\n const payload = (frame.data ?? {}) as { error?: string; message?: string };\n const message = payload.error ?? payload.message ?? `${frame.type} fired`;\n return [\n {\n type: EventType.RUN_ERROR,\n message,\n code: frame.type,\n } as BaseEvent,\n ];\n }\n\n private asCustom(frame: SurogatesFrame): BaseEvent[] {\n return [\n {\n type: EventType.CUSTOM,\n name: frame.type,\n value: frame.data,\n } as BaseEvent,\n ];\n }\n\n /**\n * Generate a stable message id derived from the triggering frame's\n * event id. The event id is globally unique per session, so using\n * it as a suffix guarantees uniqueness without pulling in ``uuid``.\n */\n private mintMessageId(frameId: number): string {\n return `msg-${frameId}`;\n }\n}\n","/**\n * AG-UI ``AbstractAgent`` implementation for the Surogates public-website channel.\n *\n * A ``WebsiteAgent`` bridges the channel-specific HTTP protocol\n * (publishable-key bootstrap, HttpOnly cookie, CSRF double-submit,\n * ``/v1/website/sessions/{id}/events`` SSE) onto AG-UI's standard\n * ``run()`` contract so any AG-UI-aware host app -- CopilotKit,\n * custom chat UIs, LangGraph-style clients -- can talk to a Surogates\n * backend with no custom glue beyond instantiation.\n *\n * Responsibilities\n * ----------------\n * * **Lazy bootstrap.** The first ``runAgent`` call POSTs to\n * ``/v1/website/sessions`` to exchange the publishable key for a\n * session cookie + CSRF token; subsequent calls reuse them. A cookie\n * expiry (HTTP 401) triggers a transparent re-bootstrap so the host\n * app never has to manage auth state.\n *\n * * **Message → POST.** On each ``runAgent`` call the agent finds the\n * latest user message in ``input.messages`` and posts its content to\n * ``/v1/website/sessions/{id}/messages`` with the CSRF header.\n *\n * * **SSE → AG-UI.** The channel's native event stream is converted\n * to AG-UI events by :class:`Translator` frame-by-frame. The agent\n * opens a fresh EventSource per run (with ``?after=<cursor>`` to\n * skip already-processed frames) and closes it after a short grace\n * drain on turn completion so trailing server frames (late\n * ``memory.update``, ``session.done``) advance the cursor rather\n * than replaying on the next run.\n *\n * * **RUN lifecycle.** AG-UI requires every run to be bracketed by\n * ``RUN_STARTED`` and exactly one of ``RUN_FINISHED`` / ``RUN_ERROR``.\n * Surogates has no such sentinel on the wire, so the agent emits\n * them itself; a per-run ``terminated`` flag guarantees at most one\n * terminal event even under concurrent SSE ``onerror`` + translator\n * end-of-turn detection.\n */\n\nimport type {\n AgentConfig,\n BaseEvent,\n Message,\n RunAgentInput,\n} from '@ag-ui/client';\nimport { AbstractAgent, AGUIError, EventType } from '@ag-ui/client';\nimport type { Subscriber } from 'rxjs';\nimport { Observable } from 'rxjs';\n\nimport {\n type BootstrapResult,\n bootstrap,\n endSession,\n openEventStream,\n sendMessage,\n} from './protocol.js';\nimport { type SurogatesFrame, Translator } from './translator.js';\nimport { SurogatesAuthError } from './errors.js';\nimport { SURG_EVENT } from './constants.js';\n\n/**\n * Constructor config for :class:`WebsiteAgent`. Extends AG-UI's\n * base ``AgentConfig`` with the two Surogates-specific fields the\n * bootstrap needs; everything else (``agentId``, ``threadId``,\n * ``initialMessages``, ``initialState``, ``debug``) is inherited\n * unchanged so consumers reuse the AG-UI patterns they already know.\n */\nexport interface WebsiteAgentConfig extends AgentConfig {\n /** Base URL of the Surogates API, e.g. ``https://agent.acme.com``. */\n apiUrl: string;\n /** Publishable key issued by ops (``surg_wk_...``). */\n publishableKey: string;\n}\n\n/** Set of Surogates SSE event names the agent subscribes to by default. */\nconst SURG_EVENT_NAMES: readonly string[] = Object.values(SURG_EVENT);\n\n/**\n * How long to keep the EventSource open after the translator flags\n * end-of-turn, giving the server a window to deliver trailing frames\n * (late ``memory.update``, ``session.done``, etc.) that belong to the\n * closing run rather than the next one. During this window we still\n * advance ``this.cursor`` but no longer emit to the subscriber, which\n * preserves AG-UI's \"one terminal event per run\" contract while also\n * preventing replay of those frames as spurious ``CUSTOM`` events on\n * the next run.\n */\nconst DRAIN_WINDOW_MS = 250;\n\nexport class WebsiteAgent extends AbstractAgent {\n readonly apiUrl: string;\n readonly publishableKey: string;\n\n /** Cached bootstrap result. ``undefined`` until the first ``run()``. */\n private bootstrapResult: BootstrapResult | undefined;\n /** Monotonic cursor across runs. Passed to the SSE ``?after=`` param. */\n private cursor = 0;\n\n constructor(config: WebsiteAgentConfig) {\n super(config);\n if (!config.apiUrl) {\n throw new AGUIError('WebsiteAgent: \"apiUrl\" is required.');\n }\n if (!config.publishableKey) {\n throw new AGUIError('WebsiteAgent: \"publishableKey\" is required.');\n }\n // Strip a trailing slash so ``${apiUrl}/v1/...`` never double-slashes.\n this.apiUrl = config.apiUrl.replace(/\\/+$/, '');\n this.publishableKey = config.publishableKey;\n }\n\n /**\n * Ensure we have a live session cookie + CSRF token.\n *\n * Idempotent; returns the cached result when one already exists.\n * ``bootstrap()`` is the only call that requires the publishable\n * key to travel in an Authorization header, so callers that want\n * to eagerly validate their configuration (e.g. to surface a\n * setup error at widget-load time) can invoke this directly.\n */\n async ensureBootstrapped(): Promise<BootstrapResult> {\n if (this.bootstrapResult) return this.bootstrapResult;\n this.bootstrapResult = await bootstrap(this.apiUrl, this.publishableKey);\n return this.bootstrapResult;\n }\n\n /**\n * Close the current session on the server side and drop local state.\n *\n * Callers should invoke this when the visitor closes the chat UI\n * so the server can mark the session complete instead of waiting\n * for the idle-reset timer. Safe to call when no session has been\n * bootstrapped yet.\n */\n async end(): Promise<void> {\n const current = this.bootstrapResult;\n if (!current) return;\n this.bootstrapResult = undefined;\n this.cursor = 0;\n await endSession(this.apiUrl, current.sessionId, current.csrfToken);\n }\n\n /**\n * Implementation of the AG-UI ``run()`` contract.\n *\n * Returns a cold observable: one subscription per run. AG-UI's\n * ``runAgent`` pipeline pipes this through chunk transformation,\n * verification, and subscriber notifications before updating\n * ``this.messages``.\n */\n run(input: RunAgentInput): Observable<BaseEvent> {\n return new Observable<BaseEvent>((subscriber) => {\n // Per-run mutable state owned by the factory closure. The\n // async ``driveRun`` populates ``ctx.source`` once the SSE is\n // open; the teardown at the bottom accesses whichever source\n // is current (swapped on cookie-recovery) and closes it.\n const ctx: RunContext = {\n terminated: false,\n source: undefined,\n drainTimer: undefined,\n };\n\n void this.driveRun(input, subscriber, ctx).catch((err) => {\n // Any rejection from driveRun that wasn't already turned into\n // a RUN_ERROR is a genuine bug; surface it through the RxJS\n // error channel rather than swallow.\n if (!ctx.terminated) {\n ctx.terminated = true;\n subscriber.error(err);\n }\n });\n\n return () => {\n // RxJS invokes this teardown on ``subscriber.complete()``,\n // ``subscriber.error()``, and on external ``unsubscribe()``\n // (whichever fires first). Distinguishing them matters\n // because ``finish()`` wants the EventSource to stay OPEN\n // for the drain window -- cursor advancement relies on\n // trailing frames still arriving through the listeners.\n //\n // Rule: if there's a drain timer pending, leave the source\n // alone; the timer will close it. Otherwise (error, abort)\n // close immediately. Either way, mark terminated so any\n // in-flight frame callbacks skip subscriber emission.\n ctx.terminated = true;\n if (ctx.drainTimer !== undefined) return;\n closeEventSource(ctx.source);\n ctx.source = undefined;\n };\n });\n }\n\n /**\n * Async body of the observable factory.\n *\n * Emits ``RUN_STARTED`` up front so every downstream failure is\n * well-bracketed by the AG-UI lifecycle. ``RUN_FINISHED`` is\n * emitted by the SSE listeners when the translator detects end-of-\n * turn; ``RUN_ERROR`` is emitted from the catch below when bootstrap\n * or message-send fails before the SSE has any chance to close out.\n *\n * The ``ctx.terminated`` guard is the single enforcement point for\n * AG-UI's \"exactly one terminal event\" invariant. Every emission\n * site checks it before calling ``subscriber.next`` with RUN_FINISHED\n * or RUN_ERROR, and every terminal call sets it to true first.\n */\n private async driveRun(\n input: RunAgentInput,\n subscriber: Subscriber<BaseEvent>,\n ctx: RunContext,\n ): Promise<void> {\n if (ctx.terminated) return;\n subscriber.next({\n type: EventType.RUN_STARTED,\n threadId: input.threadId,\n runId: input.runId,\n } as BaseEvent);\n\n try {\n const userText = this.extractUserText(input.messages);\n const boot = await this.ensureBootstrapped();\n\n // Open SSE BEFORE sending the message so no events race past us.\n // Browsers drop Authorization headers on EventSource, but the\n // session cookie rides along automatically (the route\n // authenticates off the cookie + the Origin re-check, not off\n // Bearer headers).\n this.replaceStreamSource(\n ctx, boot.sessionId, this.cursor, new Translator(), subscriber, input,\n );\n\n // POST the visitor's message. One retry on 401 (cookie expiry)\n // via a re-bootstrap; on retry the SSE stream is no longer tied\n // to the right session so we reopen it against the freshly\n // minted session id. A **fresh ``Translator``** is handed to\n // the replacement stream -- the old instance may have absorbed\n // previous-session trailing frames on the now-doomed SSE\n // between SSE-open and the send failing, and its internal\n // ``_turnComplete`` / ``pendingToolCalls`` state belongs to a\n // session that no longer exists. Reusing it would risk\n // flipping end-of-turn on the first frame of the new stream.\n await this.sendWithCookieRecovery(boot, userText, (fresh) => {\n this.replaceStreamSource(\n ctx, fresh.sessionId, 0, new Translator(), subscriber, input,\n );\n });\n } catch (err) {\n if (ctx.terminated) return;\n ctx.terminated = true;\n const message = err instanceof Error ? err.message : String(err);\n const code = err instanceof SurogatesAuthError ? 'auth' : 'error';\n subscriber.next({\n type: EventType.RUN_ERROR,\n message,\n code,\n } as BaseEvent);\n closeEventSource(ctx.source);\n ctx.source = undefined;\n subscriber.complete();\n }\n }\n\n /**\n * Tear down whatever EventSource is currently live on ``ctx`` and\n * open a fresh one against *sessionId* starting at *after*. Called\n * both for the initial stream and after cookie recovery. Always\n * clears the stale ``onerror`` first so the old source can't race\n * a ``RUN_ERROR`` into the subscriber after it's been replaced.\n */\n private replaceStreamSource(\n ctx: RunContext,\n sessionId: string,\n after: number,\n translator: Translator,\n subscriber: Subscriber<BaseEvent>,\n input: RunAgentInput,\n ): void {\n closeEventSource(ctx.source);\n const source = openEventStream(this.apiUrl, sessionId, after);\n ctx.source = source;\n this.attachStreamListeners(source, translator, subscriber, input, ctx);\n }\n\n /**\n * Try ``sendMessage``; on auth failure re-bootstrap once and retry.\n *\n * The re-bootstrap mints a new session id, so the caller passes an\n * ``onRebootstrap`` callback that reopens the SSE stream against the\n * fresh session before the retry. Visitor continuity across\n * bootstraps is a deliberate non-feature for v1; the new session\n * starts empty. Only frames emitted on the OLD session between\n * SSE-open and send-failure are lost -- and those are always\n * previous-turn events, since the current turn's ``sendMessage`` is\n * what 401-ed.\n */\n private async sendWithCookieRecovery(\n boot: BootstrapResult,\n content: string,\n onRebootstrap: (fresh: BootstrapResult) => void,\n ): Promise<void> {\n try {\n await sendMessage(this.apiUrl, boot.sessionId, boot.csrfToken, content);\n return;\n } catch (err) {\n if (!(err instanceof SurogatesAuthError)) throw err;\n this.bootstrapResult = undefined;\n this.cursor = 0;\n const fresh = await this.ensureBootstrapped();\n onRebootstrap(fresh);\n await sendMessage(this.apiUrl, fresh.sessionId, fresh.csrfToken, content);\n }\n }\n\n /**\n * Wire up the EventSource to translate and forward every frame,\n * and terminate the observable when the translator flags\n * end-of-turn or a transport failure occurs.\n *\n * After the translator flips end-of-turn we emit ``RUN_FINISHED``\n * immediately, then keep the stream open for ``DRAIN_WINDOW_MS``\n * so trailing frames (late ``memory.update``, the sentinel\n * ``session.done``) advance ``this.cursor`` rather than arriving\n * on the next run. The ``ctx.terminated`` gate stops additional\n * subscriber emissions during the drain.\n */\n private attachStreamListeners(\n source: EventSource,\n translator: Translator,\n subscriber: Subscriber<BaseEvent>,\n input: RunAgentInput,\n ctx: RunContext,\n ): void {\n const scheduleDrainClose = () => {\n // ``globalThis`` so the SDK works in both browser (returns\n // number) and Node (returns Timeout) without a type cast.\n if (ctx.drainTimer !== undefined) globalThis.clearTimeout(ctx.drainTimer);\n ctx.drainTimer = globalThis.setTimeout(() => {\n // Null the timer ref BEFORE closing the source so a\n // simultaneous ``replaceStreamSource`` (from cookie recovery)\n // doesn't see a stale timer belonging to the old stream.\n ctx.drainTimer = undefined;\n closeEventSource(source);\n }, DRAIN_WINDOW_MS);\n };\n\n const finish = () => {\n if (ctx.terminated) return;\n ctx.terminated = true;\n subscriber.next({\n type: EventType.RUN_FINISHED,\n threadId: input.threadId,\n runId: input.runId,\n } as BaseEvent);\n // Schedule the drain BEFORE ``subscriber.complete()`` so the\n // teardown invoked by RxJS sees ``ctx.drainTimer`` set and\n // leaves the source alone. Reverse the order and the teardown\n // runs with ``drainTimer === undefined``, closes the source\n // immediately, and the subsequently-scheduled timer finds\n // nothing to close -- turning the drain into a no-op and\n // breaking the cursor-advancement guarantee this whole dance\n // exists to provide.\n scheduleDrainClose();\n subscriber.complete();\n };\n\n const handleFrame = (name: string, data: string, lastEventId: string) => {\n let parsed: unknown;\n try {\n parsed = JSON.parse(data);\n } catch {\n parsed = data;\n }\n const frame: SurogatesFrame = {\n id: Number(lastEventId) || 0,\n type: name,\n data: parsed,\n };\n // Cursor advancement happens BEFORE the termination guard so\n // frames arriving during the drain window still push the\n // cursor past them. This is the whole point of the drain:\n // absorb trailing server frames so the next run's ``?after=``\n // starts beyond them.\n if (frame.id > this.cursor) this.cursor = frame.id;\n if (ctx.terminated) return;\n\n const events = translator.translate(frame);\n for (const e of events) subscriber.next(e);\n if (translator.isTurnComplete) finish();\n };\n\n // Subscribe to every Surogates event type by name. ``EventSource``\n // default ``onmessage`` only fires for frames without an ``event:``\n // line, but the server always sets one.\n for (const name of SURG_EVENT_NAMES) {\n source.addEventListener(name, (ev: MessageEvent) => {\n handleFrame(name, ev.data, ev.lastEventId);\n });\n }\n\n // Transport-level failures. The native EventSource reconnects\n // on network blips automatically (``readyState === 0``); a\n // ``readyState === 2`` is terminal. ``ctx.terminated`` stops\n // this from firing a second RUN_ERROR after finish() / the\n // driveRun catch have already terminated.\n source.onerror = () => {\n if (source.readyState !== 2 /* CLOSED */) return;\n if (ctx.terminated) return;\n ctx.terminated = true;\n subscriber.next({\n type: EventType.RUN_ERROR,\n message: 'SSE connection closed',\n code: 'sse_closed',\n } as BaseEvent);\n subscriber.complete();\n };\n }\n\n /**\n * Find the last user-authored message body to post. AG-UI supports\n * multimodal content arrays; this v1 only handles string content\n * (the website channel's ``POST /messages`` endpoint accepts plain\n * text). Multimodal support lands once the server grows a media\n * upload path.\n */\n private extractUserText(messages: Message[]): string {\n for (let i = messages.length - 1; i >= 0; i--) {\n const m = messages[i];\n if (!m || m.role !== 'user') continue;\n const content = (m as { content?: unknown }).content;\n if (typeof content === 'string' && content.trim().length > 0) {\n return content;\n }\n }\n throw new AGUIError(\n 'WebsiteAgent: no user message with string content found in input.messages.',\n );\n }\n}\n\n/** Per-run mutable state, scoped to the Observable factory closure. */\ninterface RunContext {\n terminated: boolean;\n source: EventSource | undefined;\n drainTimer: ReturnType<typeof setTimeout> | undefined;\n}\n\n/**\n * Detach the ``onerror`` listener BEFORE ``close()`` so the old\n * EventSource can't race a terminal error into the subscriber after\n * it's been swapped for a replacement (cookie recovery) or the run\n * has otherwise terminated. Safe to call on undefined.\n */\nfunction closeEventSource(source: EventSource | undefined): void {\n if (!source) return;\n try {\n source.onerror = null;\n } catch {\n /* Older EventSource implementations disallow null; ignore. */\n }\n source.close();\n}\n"]}