@nimblebrain/synapse 0.17.1 → 0.18.0

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/internals.ts","../src/result-parser.ts","../src/task-handle.ts","../src/content-parser.ts","../src/event-map.ts","../src/keyboard.ts","../src/resize.ts","../src/transport.ts","../src/connect.ts","../src/extensions.ts"],"names":["raw","TOOL_RESULT_METHOD","TOOL_INPUT_METHOD","TOOL_INPUT_PARTIAL_METHOD","TOOL_CANCELLED_METHOD","RESOURCE_TEARDOWN_METHOD","extractTheme","LATEST_PROTOCOL_VERSION","INITIALIZE_METHOD","detectHost","foldFontFaces","applyTheme","HOST_CONTEXT_CHANGED_METHOD","action","INITIALIZED_METHOD","OPEN_LINK_METHOD","MESSAGE_METHOD","fontFacesKey"],"mappings":"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","file":"chunk-FDMRJZKT.cjs","sourcesContent":["/**\n * The plumbing the SDK's own composable helpers reach through — the file\n * picker, `action`, `downloadFile`, `callToolAsTask`.\n *\n * It lives in a module-private `WeakMap` rather than on the `App` object,\n * because those two options are not equivalent. A `_internals` member is still\n * a member: it type-checks, autocompletes, survives `Object.keys`, and hands\n * every consumer a transport the SDK does not model a use for. Underscore and\n * an `@internal` tag are a request, not a boundary, and a request is what the\n * removed `Synapse._request` was — which is exactly how a bridge script ended\n * up hand-rolling its own `tools/call`.\n *\n * So the public type is the protocol surface and nothing else, and the seam is\n * genuinely closed: a caller who needs something the SDK does not expose gets a\n * named method for it, or the SDK is missing a feature.\n */\nimport type { App, AppInternals } from \"./types.js\";\n\nconst INTERNALS = new WeakMap<App, AppInternals>();\n\n/** Called once by `connect()` for each app it builds. */\nexport function registerInternals(app: App, internals: AppInternals): void {\n INTERNALS.set(app, internals);\n}\n\n/**\n * The plumbing behind an app. Throws if `app` did not come from this copy of\n * the SDK — which is what a duplicated install looks like, and is worth failing\n * loudly for rather than as an undefined-property read three frames later.\n */\nexport function internalsFor(app: App): AppInternals {\n const internals = INTERNALS.get(app);\n if (!internals) {\n throw new Error(\n \"This App did not come from this copy of @nimblebrain/synapse. \" +\n \"Two copies of the package are installed (check for a duplicate in your \" +\n \"lockfile, or a bundler resolving the ESM and CJS builds separately).\",\n );\n }\n return internals;\n}\n","import type { ToolCallResult } from \"./types.js\";\n\n/**\n * Normalize a raw tool call response into a consistent `ToolCallResult`.\n *\n * Handles three shapes:\n * 1. MCP `CallToolResult` — has a `content` array with typed blocks.\n * 2. Raw JSON object (NimbleBrain bridge) — used as-is.\n * 3. Null / undefined — returns `{ data: null, isError: false }`.\n *\n * `_meta` on a `CallToolResult` is preserved on the parsed output as a\n * whole-object passthrough — notably `io.modelcontextprotocol/related-task`\n * (`{ taskId }`) for MCP 2025-11-25 task-augmented results, but any other\n * namespaced `_meta` keys propagate for free.\n */\nexport function parseToolResult(raw: unknown): ToolCallResult {\n if (raw == null) {\n return { data: null, isError: false };\n }\n\n if (isCallToolResult(raw)) {\n return parseCallToolResult(raw);\n }\n\n // Raw JSON object — pass through.\n return { data: raw, isError: false };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ninterface McpTextBlock {\n type: \"text\";\n text: string;\n}\n\ninterface McpCallToolResult {\n content: unknown[];\n isError?: boolean;\n _meta?: { [key: string]: unknown };\n}\n\nfunction isCallToolResult(value: unknown): value is McpCallToolResult {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n return Array.isArray((value as Record<string, unknown>).content);\n}\n\nfunction isTextBlock(block: unknown): block is McpTextBlock {\n if (block === null || typeof block !== \"object\" || Array.isArray(block)) {\n return false;\n }\n const obj = block as Record<string, unknown>;\n return obj.type === \"text\" && typeof obj.text === \"string\";\n}\n\n/**\n * Extract `_meta` as a shallow-copied object if present and object-shaped.\n *\n * Key-preserving by design: every `_meta` entry propagates without\n * selective copying, so future spec additions flow through without code\n * changes. Returns `undefined` when the input has no meaningful `_meta`.\n */\nfunction extractMeta(result: McpCallToolResult): { [key: string]: unknown } | undefined {\n const meta = result._meta;\n if (!meta || typeof meta !== \"object\" || Array.isArray(meta)) return undefined;\n // Shallow spread so mutations on either side don't leak. Preserves the\n // full key set including `io.modelcontextprotocol/related-task`.\n return { ...meta };\n}\n\nfunction parseCallToolResult(result: McpCallToolResult): ToolCallResult {\n const isError = result.isError === true;\n const content = result.content;\n const meta = extractMeta(result);\n\n if (content.length === 0) {\n return { data: null, isError, content, ...(meta && { _meta: meta }) };\n }\n\n const firstText = content.find(isTextBlock);\n\n if (!firstText) {\n // No text blocks — return the full content array so callers can inspect it.\n return { data: content, isError, content, ...(meta && { _meta: meta }) };\n }\n\n // Try to parse JSON from the text block.\n try {\n return { data: JSON.parse(firstText.text), isError, content, ...(meta && { _meta: meta }) };\n } catch {\n // Invalid JSON — return the raw string.\n return { data: firstText.text, isError, content, ...(meta && { _meta: meta }) };\n }\n}\n","import type {\n CallToolRequest,\n CancelTaskRequest,\n CancelTaskResult,\n CreateTaskResult,\n GetTaskPayloadRequest,\n GetTaskPayloadResult,\n GetTaskRequest,\n GetTaskResult,\n Task,\n TaskStatus,\n TaskStatusNotification,\n TaskStatusNotificationParams,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { internalsFor } from \"./internals.js\";\nimport { parseToolResult } from \"./result-parser.js\";\nimport type { SynapseTransport } from \"./transport.js\";\nimport type {\n App,\n CallToolAsTaskOptions,\n TaskHandle,\n TaskStatusRouter,\n TaskStatusUpdate,\n ToolCallResult,\n} from \"./types.js\";\n\nexport type { TaskStatusRouter, TaskStatusUpdate };\n\n// -----------------------------------------------------------------------------\n// Spec method constants\n// -----------------------------------------------------------------------------\n//\n// The MCP SDK publishes task-method strings only inside Zod `z.literal(...)`s,\n// not as top-level `*_METHOD` constants. Derive each from its request's\n// `method` type so an upstream rename surfaces here as a compile error\n// (same pattern as `READ_RESOURCE_METHOD` in core.ts / connect.ts).\n//\n// When adding a new method here, also mirror it in `src/_shims/ext-apps.ts`\n// per the IIFE build instructions in CLAUDE.md — the shim must export the\n// same string constants any source file consumes.\n\nexport const TOOLS_CALL_METHOD: CallToolRequest[\"method\"] = \"tools/call\";\nexport const TASKS_GET_METHOD: GetTaskRequest[\"method\"] = \"tasks/get\";\nexport const TASKS_RESULT_METHOD: GetTaskPayloadRequest[\"method\"] = \"tasks/result\";\nexport const TASKS_CANCEL_METHOD: CancelTaskRequest[\"method\"] = \"tasks/cancel\";\nexport const TASKS_STATUS_NOTIFICATION_METHOD: TaskStatusNotification[\"method\"] =\n \"notifications/tasks/status\";\n\n// -----------------------------------------------------------------------------\n// Status router\n// -----------------------------------------------------------------------------\n\nexport function createTaskStatusRouter(transport: SynapseTransport): TaskStatusRouter {\n const listeners = new Map<string, Set<(update: TaskStatusUpdate) => void>>();\n\n // Single transport-level subscription. All per-handle listeners filter\n // in-memory by taskId off this one wire handler.\n const unsub = transport.onMessage(TASKS_STATUS_NOTIFICATION_METHOD, (rawParams) => {\n if (!rawParams) return;\n const params = rawParams as unknown as TaskStatusNotificationParams;\n const taskId = params.taskId;\n if (typeof taskId !== \"string\") return;\n\n const set = listeners.get(taskId);\n if (!set || set.size === 0) return;\n\n // Forward the spec-guaranteed fields verbatim. We deliberately don't\n // fabricate `createdAt`/`lastUpdatedAt`/`ttl` here — the handle merges\n // these from its initial `CreateTaskResult.task` so consumers always\n // see a real Task with no placeholder strings.\n const update: TaskStatusUpdate = {\n taskId: params.taskId,\n status: params.status,\n ...(params.statusMessage !== undefined && { statusMessage: params.statusMessage }),\n };\n\n for (const cb of set) cb(update);\n });\n\n return {\n subscribe(taskId, cb) {\n let set = listeners.get(taskId);\n if (!set) {\n set = new Set();\n listeners.set(taskId, set);\n }\n set.add(cb);\n return () => {\n const s = listeners.get(taskId);\n if (!s) return;\n s.delete(cb);\n if (s.size === 0) listeners.delete(taskId);\n };\n },\n dispose() {\n listeners.clear();\n unsub();\n },\n };\n}\n\n// -----------------------------------------------------------------------------\n// Caller-facing factory\n// -----------------------------------------------------------------------------\n\n/**\n * Task-augment a `tools/call` per the MCP 2025-11-25 tasks utility.\n *\n * A composable helper over {@link App} rather than a method on it: the object\n * `connect()` returns carries the ext-apps surface, and tasks ride alongside.\n * The receiver answers a task-augmented call with a `CreateTaskResult`\n * promptly; the actual `CallToolResult` arrives later via `tasks/result`.\n *\n * ```ts\n * const handle = await callToolAsTask(app, \"deep_research\", { topic });\n * handle.onStatus((t) => setStatus(t.status));\n * const result = await handle.result();\n * ```\n *\n * Throws if the host did not advertise `tasks.requests.tools.call` — per spec\n * a requestor MUST NOT task-augment without matching receiver capability.\n * Fall back to `app.callTool`.\n */\nexport async function callToolAsTask<TOutput = unknown>(\n app: App,\n toolName: string,\n args?: unknown,\n options?: CallToolAsTaskOptions,\n): Promise<TaskHandle<TOutput>> {\n const deps = internalsFor(app);\n const hostTasks = deps.hostTasksCapability;\n if (!hostTasks?.requests?.tools?.call) {\n throw new Error(\n \"callToolAsTask: host did not advertise tasks.requests.tools.call in its capabilities. \" +\n \"Per MCP 2025-11-25 §, requestors MUST NOT task-augment a tools/call without \" +\n \"matching receiver capability. Fall back to `app.callTool`.\",\n );\n }\n\n // Per spec, `task` is an object even when the caller provides no hints —\n // its presence is the signal to the receiver that augmentation is\n // requested. An empty `{}` is valid.\n const taskParam: { ttl?: number } = {};\n if (options?.ttl !== undefined) taskParam.ttl = options.ttl;\n\n // `internal` resolution:\n // - explicit `options.internal === true` → cross-server, add `server`\n // - explicit `options.internal === false` → never add `server`\n // - omitted → inherit from app-level\n // `internal` flag (same\n // semantics as `callTool`)\n const crossServer = options?.internal ?? deps.internalApp;\n\n // Build `tools/call` params. We layer our own shape on the SDK's\n // `CallToolRequest[\"params\"]` via `satisfies` so any rename upstream\n // (`name` → `toolName`, `arguments` → `args`, etc.) trips tsc. The\n // `server` extension is a NimbleBrain bridge convention, not an MCP\n // spec field.\n const callParams = {\n name: toolName,\n arguments: (args as Record<string, unknown> | undefined) ?? {},\n task: taskParam,\n ...(crossServer ? { server: deps.appName } : {}),\n } satisfies CallToolRequest[\"params\"] & { server?: string };\n\n const raw = await deps.request(\n TOOLS_CALL_METHOD,\n callParams as unknown as Record<string, unknown>,\n );\n\n // Spec: task-augmented `tools/call` returns a `CreateTaskResult`. If a\n // receiver that advertised the capability returns a bare\n // `CallToolResult` instead, that's a protocol violation — surface it.\n const createResult = raw as CreateTaskResult | null | undefined;\n const initialTask = createResult?.task;\n if (!initialTask || typeof initialTask !== \"object\" || typeof initialTask.taskId !== \"string\") {\n throw new Error(\n \"callToolAsTask: receiver returned a response without `task` per CreateTaskResult \" +\n \"(expected shape: `{ task: { taskId, status, ... } }`). Receiver may not honor \" +\n \"the advertised tasks capability.\",\n );\n }\n\n const taskId = initialTask.taskId;\n\n // Preserve the Set-semantic dedup contract on `onStatus` (matches\n // `SynapseTransport.onMessage`): registering the same callback twice\n // collapses to one wire subscription, and either returned unsub\n // releases it. Without this, every `onStatus(cb)` would create a\n // fresh wrapper that the router treats as distinct.\n const localCallbacks = new Map<(task: Task) => void, () => void>();\n\n const handle: TaskHandle<TOutput> = {\n task: initialTask,\n\n async result(): Promise<ToolCallResult<TOutput>> {\n const params = { taskId } satisfies GetTaskPayloadRequest[\"params\"];\n const rawResult = await deps.request(\n TASKS_RESULT_METHOD,\n params as unknown as Record<string, unknown>,\n );\n // Per spec §: `tasks/result` returns exactly what the non-task\n // response would return. Parse through the shared tool-result\n // parser so `_meta[\"io.modelcontextprotocol/related-task\"]`\n // propagates unchanged (key-preserving spread).\n //\n // Type note: `GetTaskPayloadResult` is a union of result shapes\n // (one per augmentable request type). For `tools/call` tasks,\n // the runtime shape is `CallToolResult`, which `parseToolResult`\n // already handles.\n const typed = rawResult as GetTaskPayloadResult;\n return parseToolResult(typed) as ToolCallResult<TOutput>;\n },\n\n async refresh(): Promise<Task> {\n const params = { taskId } satisfies GetTaskRequest[\"params\"];\n const raw = await deps.request(\n TASKS_GET_METHOD,\n params as unknown as Record<string, unknown>,\n );\n // Per spec, `tasks/get` returns the task shape FLAT (taskId, status,\n // ttl, createdAt, lastUpdatedAt, ... at the top level) — NOT\n // wrapped in a `{ task }` field (unlike `CreateTaskResult`).\n return projectTask(raw as GetTaskResult);\n },\n\n async cancel(): Promise<Task> {\n const params = { taskId } satisfies CancelTaskRequest[\"params\"];\n const raw = await deps.request(\n TASKS_CANCEL_METHOD,\n params as unknown as Record<string, unknown>,\n );\n // `CancelTaskResult` is flat like `GetTaskResult`.\n return projectTask(raw as CancelTaskResult);\n },\n\n onStatus(cb) {\n // Idempotent-in-callback: if the same `cb` is already subscribed,\n // return the existing unsub.\n const existing = localCallbacks.get(cb);\n if (existing) return existing;\n\n // Merge the notification's spec-guaranteed fields (taskId, status,\n // statusMessage) with the handle's initial `CreateTaskResult.task`\n // so the consumer always sees a full valid `Task`. `lastUpdatedAt`\n // is stamped at SDK-receive time (an approximation of the host's\n // update time — the spec doesn't wire the host's timestamp through\n // the notification, so this is the closest signal we have).\n // `createdAt`, `ttl`, `pollInterval` come from the initial task\n // because they don't change over a task's lifetime.\n const wireUnsub = deps.taskRouter.subscribe(taskId, (update) => {\n const merged: Task = {\n taskId: update.taskId,\n status: update.status,\n ttl: initialTask.ttl,\n createdAt: initialTask.createdAt,\n lastUpdatedAt: new Date().toISOString(),\n ...(initialTask.pollInterval !== undefined && {\n pollInterval: initialTask.pollInterval,\n }),\n ...(update.statusMessage !== undefined && { statusMessage: update.statusMessage }),\n };\n cb(merged);\n });\n\n const unsub = () => {\n localCallbacks.delete(cb);\n wireUnsub();\n };\n localCallbacks.set(cb, unsub);\n return unsub;\n },\n };\n\n return handle;\n}\n\n// -----------------------------------------------------------------------------\n// Internal helpers\n// -----------------------------------------------------------------------------\n\n/**\n * Project a `GetTaskResult` / `CancelTaskResult` down to the canonical\n * `Task` shape. Both result types are structurally `Task` with an\n * optional `_meta` field on top; we project explicitly so consumers\n * don't see protocol-level `_meta` leaking onto the task state they\n * get back from `refresh()` / `cancel()`.\n *\n * Asymmetry note: `parseToolResult` (for `tools/call` / `tasks/result`\n * payloads) is key-preserving — `_meta` flows through end-to-end, which\n * matters for `io.modelcontextprotocol/related-task` correlation. Here\n * we drop `_meta` because no downstream consumer reads it on `Task` state\n * today. If a host starts stamping useful keys on `tasks/get`/`tasks/cancel`\n * responses, switch to a key-preserving projection.\n */\nfunction projectTask(raw: GetTaskResult | CancelTaskResult): Task {\n return {\n taskId: raw.taskId,\n status: raw.status,\n ttl: raw.ttl,\n createdAt: raw.createdAt,\n lastUpdatedAt: raw.lastUpdatedAt,\n ...(raw.pollInterval !== undefined && { pollInterval: raw.pollInterval }),\n ...(raw.statusMessage !== undefined && { statusMessage: raw.statusMessage }),\n };\n}\n","import type { ToolResultData } from \"./types.js\";\n\nexport type { ToolResultData };\n\n/**\n * Parse inbound `ui/notifications/tool-result` notification params into\n * a consistent `ToolResultData` shape.\n *\n * Implements the 5-step parsing algorithm from the RFC:\n * 1. If `params.structuredContent` exists → use it as content.\n * 2. Else if `params.content` is an array of `{type:\"text\", text}` blocks →\n * join the text values and try JSON.parse.\n * 3. Else if `params.content` is a string → try JSON.parse.\n * 4. If JSON.parse fails in steps 2 or 3 → deliver the raw string.\n * 5. Return `{ content, structuredContent, raw }`.\n */\nexport function parseToolResultParams(params: Record<string, unknown> | undefined): ToolResultData {\n const raw = params ?? {};\n const structuredContent = raw.structuredContent ?? null;\n\n // Step 1: If structuredContent exists, use it as content\n if (structuredContent != null) {\n return { content: structuredContent, structuredContent, raw };\n }\n\n const rawContent = raw.content;\n\n // Step 2: If content is array of {type:\"text\", text} blocks, join texts and try JSON.parse\n if (Array.isArray(rawContent)) {\n const texts = rawContent\n .filter(\n (block: unknown) =>\n block != null &&\n typeof block === \"object\" &&\n (block as Record<string, unknown>).type === \"text\" &&\n typeof (block as Record<string, unknown>).text === \"string\",\n )\n .map((block: unknown) => (block as Record<string, unknown>).text as string);\n\n if (texts.length > 0) {\n const joined = texts.join(\"\");\n try {\n return { content: JSON.parse(joined), structuredContent: null, raw };\n } catch {\n return { content: joined, structuredContent: null, raw };\n }\n }\n\n // No text blocks — return raw content array\n return { content: rawContent, structuredContent: null, raw };\n }\n\n // Step 3: If content is string, try JSON.parse\n if (typeof rawContent === \"string\") {\n try {\n return { content: JSON.parse(rawContent), structuredContent: null, raw };\n } catch {\n return { content: rawContent, structuredContent: null, raw };\n }\n }\n\n // Fallback: return content as-is (could be null, object, etc.)\n return { content: rawContent ?? null, structuredContent: null, raw };\n}\n","import {\n HOST_CONTEXT_CHANGED_METHOD,\n RESOURCE_TEARDOWN_METHOD,\n TOOL_CANCELLED_METHOD,\n TOOL_INPUT_METHOD,\n TOOL_INPUT_PARTIAL_METHOD,\n TOOL_RESULT_METHOD,\n} from \"@modelcontextprotocol/ext-apps\";\n\n/**\n * NimbleBrain extension methods. No spec equivalent, so no constant to import\n * — but naming them once here means no source file spells the wire string\n * twice, and the `synapse/` prefix keeps them visibly outside the spec.\n * Hosts that don't implement them simply never send them.\n */\nexport const DATA_CHANGED_METHOD = \"synapse/data-changed\";\nexport const ACTION_METHOD = \"synapse/action\";\nexport const REQUEST_FILE_METHOD = \"synapse/request-file\";\nexport const DOWNLOAD_FILE_METHOD = \"synapse/download-file\";\n\n/**\n * Maps short event names used in App.on() to full MCP method names.\n * Uses canonical constants from @modelcontextprotocol/ext-apps to stay\n * in sync with the spec — if the spec changes a method name, this breaks\n * at compile time, not silently at runtime.\n *\n * `theme-changed`, `host-context-changed`, `data-changed` and `action` are\n * deliberately absent: `connect()` routes each of those itself, because each is\n * a typed *view* over a notification rather than the notification's raw params\n * (and the first two are two views over the same one). Listing them here would\n * be a second table nothing consults — the kind of copy that goes wrong quietly\n * because nothing reads it to notice.\n */\nconst EVENT_MAP: Record<string, string> = {\n \"tool-result\": TOOL_RESULT_METHOD,\n \"tool-input\": TOOL_INPUT_METHOD,\n \"tool-input-partial\": TOOL_INPUT_PARTIAL_METHOD,\n \"tool-cancelled\": TOOL_CANCELLED_METHOD,\n teardown: RESOURCE_TEARDOWN_METHOD,\n};\n\n/**\n * Resolve a short event name to a full MCP method name.\n * Returns the mapped method if found, otherwise passes through as-is.\n */\nexport function resolveEventMethod(name: string): string {\n return EVENT_MAP[name] ?? name;\n}\n\n/** The wire method behind the `theme-changed` / `host-context-changed` events. */\nexport { HOST_CONTEXT_CHANGED_METHOD };\n","import type { SynapseTransport } from \"./transport.js\";\nimport type { KeyForwardConfig } from \"./types.js\";\n\n/**\n * Forward keyboard shortcuts from the iframe document to the host.\n *\n * By default, forwards all Ctrl/Cmd+key combos and Escape.\n * Apps can customize via `forwardKeys` config.\n */\nexport class KeyboardForwarder {\n private listener: (event: KeyboardEvent) => void;\n private destroyed = false;\n\n constructor(transport: SynapseTransport, customKeys?: KeyForwardConfig[]) {\n const config = customKeys ?? null; // null = default behavior\n\n this.listener = (event: KeyboardEvent) => {\n if (this.destroyed) return;\n if (this.shouldForward(event, config)) {\n event.preventDefault();\n transport.send(\"synapse/keydown\", {\n key: event.key,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n });\n }\n };\n\n document.addEventListener(\"keydown\", this.listener);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n document.removeEventListener(\"keydown\", this.listener);\n }\n\n private shouldForward(event: KeyboardEvent, config: KeyForwardConfig[] | null): boolean {\n // Empty array = forwarding disabled\n if (config && config.length === 0) return false;\n\n // Custom config: match exactly\n if (config) {\n return config.some(\n (k) =>\n event.key.toLowerCase() === k.key.toLowerCase() &&\n (k.ctrl === undefined || event.ctrlKey === k.ctrl) &&\n (k.meta === undefined || event.metaKey === k.meta) &&\n (k.shift === undefined || event.shiftKey === k.shift) &&\n (k.alt === undefined || event.altKey === k.alt),\n );\n }\n\n // Default: forward all Ctrl/Cmd combos + Escape,\n // EXCEPT clipboard shortcuts (c, v, x, a) which the browser must handle natively.\n if (event.key === \"Escape\") return true;\n if (event.ctrlKey || event.metaKey) {\n const key = event.key.toLowerCase();\n if (key === \"c\" || key === \"v\" || key === \"x\" || key === \"a\") return false;\n return true;\n }\n return false;\n }\n}\n","type SendFn = (method: string, params: Record<string, unknown>) => void;\n\ninterface Resizer {\n resize(width?: number, height?: number): void;\n measureAndSend(): void;\n destroy(): void;\n}\n\nexport function createResizer(send: SendFn, autoResize: boolean): Resizer {\n let destroyed = false;\n let observer: ResizeObserver | null = null;\n let rafId: number | null = null;\n\n function measureAndSend(): void {\n if (destroyed) return;\n const width = document.body.scrollWidth;\n const height = document.body.scrollHeight;\n send(\"ui/notifications/size-changed\", { width, height });\n }\n\n function resize(width?: number, height?: number): void {\n if (destroyed) return;\n if (width !== undefined && height !== undefined) {\n send(\"ui/notifications/size-changed\", { width, height });\n } else {\n measureAndSend();\n }\n }\n\n // Auto mode: attach ResizeObserver, debounced at 16ms via requestAnimationFrame\n if (autoResize && typeof ResizeObserver !== \"undefined\") {\n observer = new ResizeObserver(() => {\n if (destroyed) return;\n if (rafId !== null) cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(() => {\n rafId = null;\n measureAndSend();\n });\n });\n observer.observe(document.body);\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (rafId !== null) cancelAnimationFrame(rafId);\n observer?.disconnect();\n observer = null;\n }\n\n return { resize, measureAndSend, destroy };\n}\n","import type {\n JsonRpcMessage,\n JsonRpcNotification,\n JsonRpcRequest,\n JsonRpcResponse,\n} from \"./types.js\";\n\ntype PendingEntry = {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n};\n\ntype MessageHandler = (params: Record<string, unknown> | undefined) => void;\n\nexport class SynapseTransport {\n private counter = 0;\n private destroyed = false;\n private pending = new Map<string, PendingEntry>();\n private handlers = new Map<string, Set<MessageHandler>>();\n private listener: (event: MessageEvent) => void;\n\n constructor() {\n this.listener = (event: MessageEvent) => this.handleMessage(event);\n window.addEventListener(\"message\", this.listener);\n }\n\n send(method: string, params?: Record<string, unknown>): void {\n if (this.destroyed) return;\n\n const msg: JsonRpcNotification = {\n jsonrpc: \"2.0\",\n method,\n ...(params !== undefined && { params }),\n };\n window.parent.postMessage(msg, \"*\");\n }\n\n request(method: string, params?: Record<string, unknown>): Promise<unknown> {\n if (this.destroyed) {\n return Promise.reject(new Error(\"Transport destroyed\"));\n }\n\n const id = `syn-${++this.counter}`;\n const msg: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n method,\n id,\n ...(params !== undefined && { params }),\n };\n\n return new Promise<unknown>((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n window.parent.postMessage(msg, \"*\");\n });\n }\n\n onMessage(method: string, callback: MessageHandler): () => void {\n if (!this.handlers.has(method)) {\n this.handlers.set(method, new Set());\n }\n this.handlers.get(method)?.add(callback);\n\n return () => {\n const set = this.handlers.get(method);\n if (set) {\n set.delete(callback);\n if (set.size === 0) {\n this.handlers.delete(method);\n }\n }\n };\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n window.removeEventListener(\"message\", this.listener);\n\n const error = new Error(\"Transport destroyed\");\n for (const entry of this.pending.values()) {\n entry.reject(error);\n }\n this.pending.clear();\n this.handlers.clear();\n }\n\n private handleMessage(event: MessageEvent): void {\n if (this.destroyed) return;\n\n const data = event.data as JsonRpcMessage;\n if (!data || data.jsonrpc !== \"2.0\") return;\n\n // Response to a pending request\n if (\"id\" in data && data.id && !(\"method\" in data)) {\n const response = data as JsonRpcResponse;\n const entry = this.pending.get(response.id);\n if (!entry) return;\n this.pending.delete(response.id);\n\n if (response.error) {\n const err = new Error(response.error.message);\n (err as any).code = response.error.code;\n (err as any).data = response.error.data;\n entry.reject(err);\n } else {\n entry.resolve(response.result);\n }\n return;\n }\n\n // Incoming notification\n if (\"method\" in data && !(\"id\" in data && data.id)) {\n const notification = data as JsonRpcNotification;\n const set = this.handlers.get(notification.method);\n if (set) {\n for (const handler of set) {\n handler(notification.params);\n }\n }\n }\n }\n}\n","import type {\n McpUiHostContext,\n McpUiHostContextChangedNotification,\n McpUiInitializeRequest,\n McpUiInitializeResult,\n McpUiMessageRequest,\n McpUiOpenLinkRequest,\n McpUiUpdateModelContextRequest,\n} from \"@modelcontextprotocol/ext-apps\";\nimport {\n HOST_CONTEXT_CHANGED_METHOD,\n INITIALIZE_METHOD,\n INITIALIZED_METHOD,\n LATEST_PROTOCOL_VERSION,\n MESSAGE_METHOD,\n OPEN_LINK_METHOD,\n TOOL_RESULT_METHOD,\n} from \"@modelcontextprotocol/ext-apps\";\nimport type {\n ReadResourceRequest,\n ReadResourceResult,\n TextContent,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { parseToolResultParams } from \"./content-parser.js\";\nimport { detectHost, extractTheme, foldFontFaces } from \"./detection.js\";\nimport { ACTION_METHOD, DATA_CHANGED_METHOD, resolveEventMethod } from \"./event-map.js\";\nimport { registerInternals } from \"./internals.js\";\nimport { KeyboardForwarder } from \"./keyboard.js\";\nimport { createResizer } from \"./resize.js\";\nimport { parseToolResult } from \"./result-parser.js\";\nimport { createTaskStatusRouter, TOOLS_CALL_METHOD } from \"./task-handle.js\";\nimport { applyTheme, fontFacesKey } from \"./theme-defaults.js\";\nimport { SynapseTransport } from \"./transport.js\";\nimport type {\n AgentAction,\n App,\n CallToolOptions,\n ConnectOptions,\n DataChangedEvent,\n Dimensions,\n FontFaceDescriptor,\n TasksCapability,\n Theme,\n ToolCallResult,\n} from \"./types.js\";\n\n// Derived locally because `@modelcontextprotocol/ext-apps` only exports\n// METHOD constants for ext-apps specific ui/* methods. Typing the literal\n// with the spec's request `method` field still produces a compile error if\n// upstream renames it.\nconst READ_RESOURCE_METHOD: ReadResourceRequest[\"method\"] = \"resources/read\";\nconst UPDATE_MODEL_CONTEXT_METHOD: McpUiUpdateModelContextRequest[\"method\"] =\n \"ui/update-model-context\";\n\n/**\n * Connect to an MCP Apps host.\n *\n * The one entry point: owns the ext-apps handshake, theme injection, content\n * parsing, resize management, and event routing, and resolves to a ready\n * {@link App}.\n *\n * The `App` it returns stays deliberately small. NimbleBrain's own extensions\n * (`action`, the file picker, `downloadFile`) and the MCP tasks utility are\n * composable functions over it — import them from the package root.\n */\nexport async function connect(options: ConnectOptions): Promise<App> {\n const { name, version, autoResize = false, internal = false, forwardKeys } = options;\n\n const transport = new SynapseTransport();\n let destroyed = false;\n\n // --- Mutable state ---\n //\n // The host context is the single source of truth. `theme` is a derived view\n // of it, not a parallel copy.\n let hostContext: McpUiHostContext = {};\n let hostInfo: { name: string; version: string } = { name: \"unknown\", version: \"unknown\" };\n let isNimbleBrainHost = false;\n let toolInfo: { tool: Record<string, unknown> } | null = null;\n let containerDimensions: Dimensions | null = null;\n let hostTasksCapability: TasksCapability | undefined;\n let keyboard: KeyboardForwarder | null = null;\n\n // Font faces are the one derived value that must NOT be recomputed from a\n // replaced context. A `host-context-changed` carries only the fields that\n // changed, so a bare `{ theme: \"dark\" }` toggle would otherwise re-derive\n // \"no fonts\" and unload the host's typeface mid-session — far more visible\n // than the equivalent for a colour token. Sticky here, cleared only by an\n // explicit empty list from the host.\n let fontFaces: FontFaceDescriptor[] | undefined;\n\n /**\n * The theme as reported to consumers: derived from the context, with the\n * sticky faces folded back in. Every public view goes through here — the\n * `theme` getter, the `theme-changed` payload, and its equality filter — so\n * they cannot disagree with each other or with what is actually loaded.\n */\n function resolveTheme(): Theme {\n const theme = extractTheme(hostContext);\n return fontFaces ? { ...theme, fontFaces } : theme;\n }\n\n // --- Event handlers ---\n //\n // Generic wire methods share one registry keyed by method. The four events\n // that are a *view* over a wire message rather than the message itself\n // (theme, host context, data-changed, action) get their own sets, because\n // two of them ride the same notification and hand their subscribers\n // different payloads.\n const handlers = new Map<string, Set<(params: unknown) => void>>();\n const themeCallbacks = new Set<(theme: Theme) => void>();\n const hostContextCallbacks = new Set<(ctx: McpUiHostContext) => void>();\n const dataCallbacks = new Set<(event: DataChangedEvent) => void>();\n const actionCallbacks = new Set<(action: AgentAction) => void>();\n\n // --- Step 1: Set up message listener (handled by SynapseTransport constructor) ---\n\n // --- Step 2: Send initial size ---\n const resizer = createResizer((method, params) => transport.send(method, params), autoResize);\n resizer.measureAndSend();\n\n // --- Steps 3-4: Send ui/initialize and wait for response ---\n //\n // `appCapabilities` is typed as `McpUiAppCapabilities` by the ext-apps spec\n // package, which does not yet model the MCP 2025-11-25 tasks utility. We\n // extend structurally via `TasksCapability` and `satisfies` the extension so\n // the nested objects match the spec literally — empty objects `{}` as\n // presence flags, NOT booleans.\n const appCapabilities = {\n tasks: {\n cancel: {},\n requests: { tools: { call: {} } },\n } satisfies TasksCapability,\n };\n const initParams: McpUiInitializeRequest[\"params\"] = {\n protocolVersion: LATEST_PROTOCOL_VERSION,\n appInfo: { name, version },\n appCapabilities:\n appCapabilities as unknown as McpUiInitializeRequest[\"params\"][\"appCapabilities\"],\n };\n\n const result = (await transport.request(\n INITIALIZE_METHOD,\n initParams as unknown as Record<string, unknown>,\n )) as McpUiInitializeResult | null;\n\n // --- Step 5: Adopt the handshake response ---\n if (result) {\n const detected = detectHost(result);\n isNimbleBrainHost = detected.isNimbleBrain;\n hostInfo = {\n name: result.hostInfo?.name ?? \"unknown\",\n version: result.hostInfo?.version ?? \"unknown\",\n };\n\n // The ext-apps `McpUiHostCapabilities` type lacks a `tasks` field (the\n // SDK extension post-dates it), so read via the result's index signature.\n const rawTasks = (result.hostCapabilities as Record<string, unknown> | undefined)?.tasks;\n hostTasksCapability =\n rawTasks && typeof rawTasks === \"object\" && !Array.isArray(rawTasks)\n ? (rawTasks as TasksCapability)\n : undefined;\n\n const ctx: McpUiHostContext | undefined = result.hostContext;\n if (ctx) {\n hostContext = ctx;\n fontFaces = foldFontFaces(fontFaces, ctx);\n\n if (ctx.toolInfo && typeof ctx.toolInfo === \"object\") {\n toolInfo = { tool: (ctx.toolInfo.tool as unknown as Record<string, unknown>) ?? {} };\n }\n if (ctx.containerDimensions && typeof ctx.containerDimensions === \"object\") {\n containerDimensions = ctx.containerDimensions as Dimensions;\n }\n\n // Inject the theme into the DOM: the host's values go inline, and the\n // neutral defaults for the mode go in a cascade layer, where they back\n // any var nobody declares and lose to every var that is declared. Any\n // host-supplied font faces load alongside — a token names a family, it\n // cannot load one.\n const theme = resolveTheme();\n applyTheme(theme.mode, theme.tokens, theme.fontFaces);\n }\n }\n\n // Keyboard forwarding is a NimbleBrain extension: only a NimbleBrain host\n // consumes `synapse/keydown`. Forwarding elsewhere would `preventDefault` a\n // key for a host that does nothing with it, so the gate is on identity, not\n // just on the option.\n if (forwardKeys && isNimbleBrainHost) {\n keyboard = new KeyboardForwarder(transport, forwardKeys === true ? undefined : forwardKeys);\n }\n\n // --- Route incoming notifications ---\n\n /**\n * Deliver a notification's raw params to anyone who subscribed by wire\n * method name rather than by short event. The three methods below are routed\n * by hand because each also has a typed view, and `ensureTransportSub` skips\n * them for that reason — so the raw fan-out has to happen here or a\n * `on(\"synapse/data-changed\", …)` would silently never fire.\n */\n function fanOutRaw(method: string, params: Record<string, unknown> | undefined): void {\n const set = handlers.get(method);\n if (!set) return;\n for (const handler of set) handler(params);\n }\n\n // `host-context-changed` feeds three different views, so it is handled once\n // here rather than through the generic registry.\n transport.onMessage(HOST_CONTEXT_CHANGED_METHOD, (params) => {\n if (destroyed) return;\n const ctx = (params ?? {}) as Partial<McpUiHostContextChangedNotification[\"params\"]>;\n const prevTheme = resolveTheme();\n\n // The spec types these params as \"a partial context update containing only\n // changed fields\", so the notification is a delta and `hostContext` is the\n // state it updates. Replacing wholesale would make a host that toggles dark\n // mode with a bare `{ theme: \"dark\" }` lose its entire palette and every\n // extension it published — `styles.variables` re-derived as `{}` strips the\n // host's CSS variables from the DOM, and `workspace` reads `undefined`.\n //\n // The merge is SHALLOW on purpose. `styles.variables` is a complete map\n // when the host sends one, so deep-merging it would leave a host no way to\n // remove a variable.\n hostContext = { ...hostContext, ...ctx };\n\n // Fonts keep their own fold even so, because it encodes a rule the merge\n // cannot: a batch whose entries are ALL malformed reads as `undefined` and\n // must leave the loaded faces alone. Deriving from the merged context would\n // instead see the key present, find nothing usable in it, and unload the\n // host's typeface — a far more visible break than the colour equivalent.\n fontFaces = foldFontFaces(fontFaces, ctx);\n const nextTheme = resolveTheme();\n\n applyTheme(nextTheme.mode, nextTheme.tokens, nextTheme.fontFaces);\n\n // Subscribers to the short event get the merged snapshot, because that is\n // what `app.hostContext` means and a delta cannot distinguish an omitted\n // field from a cleared one. A caller who genuinely wants the notification\n // as sent subscribes to the wire method instead, which `fanOutRaw` passes\n // through untouched.\n for (const cb of hostContextCallbacks) cb(hostContext);\n fanOutRaw(HOST_CONTEXT_CHANGED_METHOD, params);\n // Theme subscribers see only real theme movement: a host-context change\n // that leaves the derived theme identical (a workspace switch, say) must\n // not re-render every themed component in the app.\n if (!themesEqual(prevTheme, nextTheme)) {\n for (const cb of themeCallbacks) cb(nextTheme);\n }\n });\n\n transport.onMessage(DATA_CHANGED_METHOD, (params) => {\n if (destroyed) return;\n fanOutRaw(DATA_CHANGED_METHOD, params);\n if (!params) return;\n const event: DataChangedEvent = {\n source: \"agent\",\n server: (params.server as string) ?? \"\",\n tool: (params.tool as string) ?? \"\",\n };\n for (const cb of dataCallbacks) cb(event);\n });\n\n transport.onMessage(ACTION_METHOD, (params) => {\n if (destroyed) return;\n fanOutRaw(ACTION_METHOD, params);\n // The typed view drops an action with no `type` discriminator; a raw\n // subscriber above has already seen it verbatim.\n if (!params || typeof params.type !== \"string\") return;\n const action: AgentAction = {\n type: params.type as string,\n payload: (params.payload as Record<string, unknown>) ?? {},\n requiresConfirmation: params.requiresConfirmation === true,\n label: typeof params.label === \"string\" ? params.label : undefined,\n };\n for (const cb of actionCallbacks) cb(action);\n });\n\n // Helper to ensure a transport subscription exists for a generic method\n const subscribedMethods = new Set<string>([\n HOST_CONTEXT_CHANGED_METHOD,\n DATA_CHANGED_METHOD,\n ACTION_METHOD,\n ]);\n\n function ensureTransportSub(method: string): void {\n if (subscribedMethods.has(method)) return;\n subscribedMethods.add(method);\n\n const isToolResult = method === TOOL_RESULT_METHOD;\n\n transport.onMessage(method, (params) => {\n if (destroyed) return;\n const set = handlers.get(method);\n if (!set) return;\n for (const handler of set) {\n if (isToolResult) {\n handler(parseToolResultParams(params));\n } else {\n handler(params);\n }\n }\n });\n }\n\n /** Register one handler and return its unsubscribe. */\n function subscribe(event: string, handler: (params: any) => void): () => void {\n switch (event) {\n case \"theme-changed\":\n themeCallbacks.add(handler);\n return () => {\n themeCallbacks.delete(handler);\n };\n case \"host-context-changed\":\n hostContextCallbacks.add(handler);\n return () => {\n hostContextCallbacks.delete(handler);\n };\n case \"data-changed\":\n dataCallbacks.add(handler);\n return () => {\n dataCallbacks.delete(handler);\n };\n case \"action\":\n actionCallbacks.add(handler);\n return () => {\n actionCallbacks.delete(handler);\n };\n default: {\n const method = resolveEventMethod(event);\n if (!handlers.has(method)) handlers.set(method, new Set());\n handlers.get(method)?.add(handler);\n ensureTransportSub(method);\n return () => {\n const set = handlers.get(method);\n if (set) {\n set.delete(handler);\n if (set.size === 0) handlers.delete(method);\n }\n };\n }\n }\n }\n\n // --- Step 6: Pre-register handlers from options.on, then send initialized ---\n if (options.on) {\n for (const [event, handler] of Object.entries(options.on)) {\n if (typeof handler === \"function\") subscribe(event, handler);\n }\n }\n transport.send(INITIALIZED_METHOD, {});\n\n // Shared router for `notifications/tasks/status`. Created eagerly so the\n // transport-level listener registers exactly once — every `TaskHandle`\n // filters off this single wire subscription by taskId.\n const taskRouter = createTaskStatusRouter(transport);\n\n // --- Step 7: Build and return the App object ---\n const app: App = {\n get theme() {\n return resolveTheme();\n },\n get hostInfo() {\n return { ...hostInfo };\n },\n get hostContext() {\n return hostContext;\n },\n get isNimbleBrainHost() {\n return isNimbleBrainHost;\n },\n get toolInfo() {\n return toolInfo;\n },\n get containerDimensions() {\n return containerDimensions;\n },\n get destroyed() {\n return destroyed;\n },\n get supportsTasks() {\n return hostTasksCapability?.requests?.tools?.call !== undefined;\n },\n\n on(event: string, handler: (params: any) => void): () => void {\n return subscribe(event, handler);\n },\n\n resize(width?: number, height?: number): void {\n resizer.resize(width, height);\n },\n\n openLink(url: string): void {\n if (destroyed) return;\n const params: McpUiOpenLinkRequest[\"params\"] = { url };\n // Spec: ui/open-link is a request (expects a response), not a notification\n transport\n .request(OPEN_LINK_METHOD, params as unknown as Record<string, unknown>)\n .catch(() => {\n // Fallback: if the host doesn't respond, open directly.\n window.open(url, \"_blank\", \"noopener\");\n });\n },\n\n updateModelContext(state: Record<string, unknown>, summary?: string): void {\n if (destroyed) return;\n const params: McpUiUpdateModelContextRequest[\"params\"] = {\n structuredContent: state,\n ...(summary !== undefined && {\n content: [{ type: \"text\", text: summary } satisfies TextContent],\n }),\n };\n transport.send(UPDATE_MODEL_CONTEXT_METHOD, params as unknown as Record<string, unknown>);\n },\n\n async callTool<TOutput = unknown>(\n toolName: string,\n args?: Record<string, unknown>,\n callOptions?: CallToolOptions,\n ): Promise<ToolCallResult<TOutput>> {\n // `server` is a NimbleBrain bridge convention for cross-server dispatch,\n // not an MCP spec field. An internal app defaults to its own name, which\n // is what makes a plain `callTool` work for one.\n const server = callOptions?.server ?? (internal ? name : undefined);\n const params = {\n name: toolName,\n arguments: args ?? {},\n ...(server !== undefined && { server }),\n };\n const raw = await transport.request(TOOLS_CALL_METHOD, params);\n return parseToolResult(raw) as ToolCallResult<TOutput>;\n },\n\n async readServerResource(params: ReadResourceRequest[\"params\"]): Promise<ReadResourceResult> {\n const raw = await transport.request(\n READ_RESOURCE_METHOD,\n params as unknown as Record<string, unknown>,\n );\n return raw as ReadResourceResult;\n },\n\n sendMessage(text: string, context?: { action?: string; entity?: string }): void {\n if (destroyed) return;\n const textBlock: TextContent = {\n type: \"text\",\n text,\n // `_meta.context` is a NimbleBrain convention; other hosts ignore it,\n // but there is no reason to spend the bytes off one.\n ...(isNimbleBrainHost && context && { _meta: { context } }),\n };\n const params: McpUiMessageRequest[\"params\"] = {\n role: \"user\",\n content: [textBlock],\n };\n transport.send(MESSAGE_METHOD, params as unknown as Record<string, unknown>);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n keyboard?.destroy();\n resizer.destroy();\n taskRouter.dispose();\n handlers.clear();\n themeCallbacks.clear();\n hostContextCallbacks.clear();\n dataCallbacks.clear();\n actionCallbacks.clear();\n transport.destroy();\n },\n };\n\n registerInternals(app, {\n send(method, params) {\n if (destroyed) return;\n transport.send(method, params);\n },\n request(method, params) {\n return transport.request(method, params);\n },\n onMessage(method, handler) {\n return transport.onMessage(method, handler);\n },\n taskRouter,\n get hostTasksCapability() {\n return hostTasksCapability;\n },\n appName: name,\n internalApp: internal,\n });\n\n return app;\n}\n\n/**\n * Shallow equality for `Theme` — used to filter host-context changes that\n * don't actually move the theme (e.g. a workspace switch that leaves\n * theme/styles untouched). Cheap; tokens are ~40 entries. Typography counts:\n * a host can swap typeface without touching mode or tokens, and that must\n * still reach subscribers.\n */\nfunction themesEqual(a: Theme, b: Theme): boolean {\n if (a.mode !== b.mode) return false;\n if (fontFacesKey(a.fontFaces) !== fontFacesKey(b.fontFaces)) return false;\n const aKeys = Object.keys(a.tokens);\n const bKeys = Object.keys(b.tokens);\n if (aKeys.length !== bKeys.length) return false;\n // Iterating only over `a`'s keys is sufficient: under equal length, any key\n // in `a` missing from `b` reads `b[k] === undefined`, which fails the strict\n // inequality check. Symmetric difference is covered.\n for (const k of aKeys) {\n if (a.tokens[k] !== b.tokens[k]) return false;\n }\n return true;\n}\n","/**\n * NimbleBrain host extensions — composable functions over {@link App}.\n *\n * These are not ext-apps spec surface. They ride the `synapse/` method prefix,\n * which `McpUiHostContext`'s open index signature makes legal, and only a\n * NimbleBrain host implements them. They live here rather than on the `App`\n * object so the object stays the spec surface plus the handshake state, and\n * so an app that never picks a file never pulls this code in.\n *\n * Every one of them is gated on the host identity established by the\n * handshake: off a NimbleBrain host, the fire-and-forget ones are no-ops and\n * the ones with a return value throw, because a picker that silently resolves\n * `null` forever is worse than one that says it isn't there.\n */\nimport { ACTION_METHOD, DOWNLOAD_FILE_METHOD, REQUEST_FILE_METHOD } from \"./event-map.js\";\nimport { internalsFor } from \"./internals.js\";\nimport type { App, FileResult, RequestFileOptions } from \"./types.js\";\n\n/** 25 MB — the host's default cap on a single picked file. */\nconst DEFAULT_MAX_FILE_SIZE = 26_214_400;\n\n/**\n * Trigger a host-side action.\n *\n * The inverse direction of the `action` event: this sends a command *to* the\n * host (navigate, open a panel), where `app.on(\"action\", …)` receives the ones\n * a tool emits. No-op off a NimbleBrain host.\n */\nexport function action(app: App, name: string, params?: Record<string, unknown>): void {\n if (!app.isNimbleBrainHost) return;\n // The outbound frame reuses the inbound method name; the host distinguishes\n // direction, not method.\n internalsFor(app).send(ACTION_METHOD, { action: name, ...params });\n}\n\n/**\n * Hand the user a file to save.\n *\n * Precedence for the MIME type: the explicit argument, then the Blob's own\n * type, then `application/octet-stream`. An empty-string argument falls\n * through — a `\"\"` MIME is effectively \"no type\".\n */\nexport function downloadFile(\n app: App,\n filename: string,\n content: string | Blob,\n mimeType?: string,\n): void {\n const resolvedMime =\n mimeType || (content instanceof Blob ? content.type : \"\") || \"application/octet-stream\";\n const blob = content instanceof Blob ? content : new Blob([content], { type: resolvedMime });\n internalsFor(app).send(DOWNLOAD_FILE_METHOD, {\n data: blob,\n filename,\n mimeType: resolvedMime,\n });\n}\n\n/**\n * Request one file from the user via the host's native file picker.\n *\n * Resolves `null` if the user cancels. Throws off a NimbleBrain host.\n */\nexport async function pickFile(app: App, options?: RequestFileOptions): Promise<FileResult | null> {\n if (!app.isNimbleBrainHost) {\n throw new Error(\"pickFile is not supported in this host\");\n }\n const result = await requestFile(app, options, false);\n if (result === null) return null;\n // The host may return an array even for a single pick — take the first\n // entry to preserve the documented `FileResult | null` shape.\n return Array.isArray(result) ? (result[0] ?? null) : result;\n}\n\n/**\n * Request several files from the user.\n *\n * Resolves `[]` if the user cancels. Throws off a NimbleBrain host.\n */\nexport async function pickFiles(app: App, options?: RequestFileOptions): Promise<FileResult[]> {\n if (!app.isNimbleBrainHost) {\n throw new Error(\"pickFiles is not supported in this host\");\n }\n const result = await requestFile(app, options, true);\n if (result === null) return [];\n return Array.isArray(result) ? result : [result];\n}\n\n/**\n * Shared request path for `pickFile` / `pickFiles`. Centralizes:\n *\n * - The wire method name (which is what the NimbleBrain bridge actually\n * handles — earlier SDK versions sent `synapse/pick-file` and the call would\n * silently time out).\n * - Runtime shape validation. Older hosts (pre-`POST /v1/resources`) still\n * respond but return the legacy `{ base64Data, … }` shape. The TS type\n * promises a string `id`; without this guard, consumers would silently get\n * `undefined.id` and fail downstream in confusing ways. Failing loud at the\n * boundary tells the developer exactly which side is mismatched.\n */\nasync function requestFile(\n app: App,\n options: RequestFileOptions | undefined,\n multiple: boolean,\n): Promise<FileResult | FileResult[] | null> {\n const result = await internalsFor(app).request(REQUEST_FILE_METHOD, {\n accept: options?.accept,\n maxSize: options?.maxSize ?? DEFAULT_MAX_FILE_SIZE,\n multiple,\n });\n if (result == null) return null;\n if (Array.isArray(result)) {\n return result.map(validateFileResult);\n }\n return validateFileResult(result);\n}\n\nfunction validateFileResult(value: unknown): FileResult {\n if (\n typeof value !== \"object\" ||\n value === null ||\n typeof (value as { id?: unknown }).id !== \"string\"\n ) {\n throw new Error(\n \"synapse/request-file returned a result without a string `id`. \" +\n \"The host appears to be on a version older than this SDK targets — \" +\n \"@nimblebrain/synapse 0.8.0+ requires a host with POST /v1/resources \" +\n \"(NimbleBrain ≥ the version that ships PR #93).\",\n );\n }\n return value as FileResult;\n}\n"]}
1
+ {"version":3,"sources":["../src/internals.ts","../src/result-parser.ts","../src/task-handle.ts","../src/content-parser.ts","../src/event-map.ts","../src/keyboard.ts","../src/resize.ts","../src/transport.ts","../src/connect.ts","../src/extensions.ts"],"names":["raw","TOOL_RESULT_METHOD","TOOL_INPUT_METHOD","TOOL_INPUT_PARTIAL_METHOD","TOOL_CANCELLED_METHOD","RESOURCE_TEARDOWN_METHOD","extractTheme","LATEST_PROTOCOL_VERSION","INITIALIZE_METHOD","detectHost","foldFontFaces","applyTheme","HOST_CONTEXT_CHANGED_METHOD","action","INITIALIZED_METHOD","OPEN_LINK_METHOD","MESSAGE_METHOD","fontFacesKey"],"mappings":"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","file":"chunk-FB7GPBEM.cjs","sourcesContent":["/**\n * The plumbing the SDK's own composable helpers reach through — the file\n * picker, `action`, `downloadFile`, `callToolAsTask`.\n *\n * It lives in a module-private `WeakMap` rather than on the `App` object,\n * because those two options are not equivalent. A `_internals` member is still\n * a member: it type-checks, autocompletes, survives `Object.keys`, and hands\n * every consumer a transport the SDK does not model a use for. Underscore and\n * an `@internal` tag are a request, not a boundary, and a request is what the\n * removed `Synapse._request` was — which is exactly how a bridge script ended\n * up hand-rolling its own `tools/call`.\n *\n * So the public type is the protocol surface and nothing else, and the seam is\n * genuinely closed: a caller who needs something the SDK does not expose gets a\n * named method for it, or the SDK is missing a feature.\n */\nimport type { App, AppInternals } from \"./types.js\";\n\nconst INTERNALS = new WeakMap<App, AppInternals>();\n\n/** Called once by `connect()` for each app it builds. */\nexport function registerInternals(app: App, internals: AppInternals): void {\n INTERNALS.set(app, internals);\n}\n\n/**\n * The plumbing behind an app. Throws if `app` did not come from this copy of\n * the SDK — which is what a duplicated install looks like, and is worth failing\n * loudly for rather than as an undefined-property read three frames later.\n */\nexport function internalsFor(app: App): AppInternals {\n const internals = INTERNALS.get(app);\n if (!internals) {\n throw new Error(\n \"This App did not come from this copy of @nimblebrain/synapse. \" +\n \"Two copies of the package are installed (check for a duplicate in your \" +\n \"lockfile, or a bundler resolving the ESM and CJS builds separately).\",\n );\n }\n return internals;\n}\n","import type { ToolCallResult } from \"./types.js\";\n\n/**\n * Normalize a raw tool call response into a consistent `ToolCallResult`.\n *\n * Handles three shapes:\n * 1. MCP `CallToolResult` — has a `content` array with typed blocks.\n * 2. Raw JSON object (NimbleBrain bridge) — used as-is.\n * 3. Null / undefined — returns `{ data: null, isError: false }`.\n *\n * `_meta` on a `CallToolResult` is preserved on the parsed output as a\n * whole-object passthrough — notably `io.modelcontextprotocol/related-task`\n * (`{ taskId }`) for MCP 2025-11-25 task-augmented results, but any other\n * namespaced `_meta` keys propagate for free.\n */\nexport function parseToolResult(raw: unknown): ToolCallResult {\n if (raw == null) {\n return { data: null, isError: false };\n }\n\n if (isCallToolResult(raw)) {\n return parseCallToolResult(raw);\n }\n\n // Raw JSON object — pass through.\n return { data: raw, isError: false };\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\ninterface McpTextBlock {\n type: \"text\";\n text: string;\n}\n\ninterface McpCallToolResult {\n content: unknown[];\n isError?: boolean;\n _meta?: { [key: string]: unknown };\n}\n\nfunction isCallToolResult(value: unknown): value is McpCallToolResult {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n return Array.isArray((value as Record<string, unknown>).content);\n}\n\nfunction isTextBlock(block: unknown): block is McpTextBlock {\n if (block === null || typeof block !== \"object\" || Array.isArray(block)) {\n return false;\n }\n const obj = block as Record<string, unknown>;\n return obj.type === \"text\" && typeof obj.text === \"string\";\n}\n\n/**\n * Extract `_meta` as a shallow-copied object if present and object-shaped.\n *\n * Key-preserving by design: every `_meta` entry propagates without\n * selective copying, so future spec additions flow through without code\n * changes. Returns `undefined` when the input has no meaningful `_meta`.\n */\nfunction extractMeta(result: McpCallToolResult): { [key: string]: unknown } | undefined {\n const meta = result._meta;\n if (!meta || typeof meta !== \"object\" || Array.isArray(meta)) return undefined;\n // Shallow spread so mutations on either side don't leak. Preserves the\n // full key set including `io.modelcontextprotocol/related-task`.\n return { ...meta };\n}\n\nfunction parseCallToolResult(result: McpCallToolResult): ToolCallResult {\n const isError = result.isError === true;\n const content = result.content;\n const meta = extractMeta(result);\n\n if (content.length === 0) {\n return { data: null, isError, content, ...(meta && { _meta: meta }) };\n }\n\n const firstText = content.find(isTextBlock);\n\n if (!firstText) {\n // No text blocks — return the full content array so callers can inspect it.\n return { data: content, isError, content, ...(meta && { _meta: meta }) };\n }\n\n // Try to parse JSON from the text block.\n try {\n return { data: JSON.parse(firstText.text), isError, content, ...(meta && { _meta: meta }) };\n } catch {\n // Invalid JSON — return the raw string.\n return { data: firstText.text, isError, content, ...(meta && { _meta: meta }) };\n }\n}\n","import type {\n CallToolRequest,\n CancelTaskRequest,\n CancelTaskResult,\n CreateTaskResult,\n GetTaskPayloadRequest,\n GetTaskPayloadResult,\n GetTaskRequest,\n GetTaskResult,\n Task,\n TaskStatus,\n TaskStatusNotification,\n TaskStatusNotificationParams,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { internalsFor } from \"./internals.js\";\nimport { parseToolResult } from \"./result-parser.js\";\nimport type { SynapseTransport } from \"./transport.js\";\nimport type {\n App,\n CallToolAsTaskOptions,\n TaskHandle,\n TaskStatusRouter,\n TaskStatusUpdate,\n ToolCallResult,\n} from \"./types.js\";\n\nexport type { TaskStatusRouter, TaskStatusUpdate };\n\n// -----------------------------------------------------------------------------\n// Spec method constants\n// -----------------------------------------------------------------------------\n//\n// The MCP SDK publishes task-method strings only inside Zod `z.literal(...)`s,\n// not as top-level `*_METHOD` constants. Derive each from its request's\n// `method` type so an upstream rename surfaces here as a compile error\n// (same pattern as `READ_RESOURCE_METHOD` in core.ts / connect.ts).\n//\n// When adding a new method here, also mirror it in `src/_shims/ext-apps.ts`\n// per the IIFE build instructions in CLAUDE.md — the shim must export the\n// same string constants any source file consumes.\n\nexport const TOOLS_CALL_METHOD: CallToolRequest[\"method\"] = \"tools/call\";\nexport const TASKS_GET_METHOD: GetTaskRequest[\"method\"] = \"tasks/get\";\nexport const TASKS_RESULT_METHOD: GetTaskPayloadRequest[\"method\"] = \"tasks/result\";\nexport const TASKS_CANCEL_METHOD: CancelTaskRequest[\"method\"] = \"tasks/cancel\";\nexport const TASKS_STATUS_NOTIFICATION_METHOD: TaskStatusNotification[\"method\"] =\n \"notifications/tasks/status\";\n\n// -----------------------------------------------------------------------------\n// Status router\n// -----------------------------------------------------------------------------\n\nexport function createTaskStatusRouter(transport: SynapseTransport): TaskStatusRouter {\n const listeners = new Map<string, Set<(update: TaskStatusUpdate) => void>>();\n\n // Single transport-level subscription. All per-handle listeners filter\n // in-memory by taskId off this one wire handler.\n const unsub = transport.onMessage(TASKS_STATUS_NOTIFICATION_METHOD, (rawParams) => {\n if (!rawParams) return;\n const params = rawParams as unknown as TaskStatusNotificationParams;\n const taskId = params.taskId;\n if (typeof taskId !== \"string\") return;\n\n const set = listeners.get(taskId);\n if (!set || set.size === 0) return;\n\n // Forward the spec-guaranteed fields verbatim. We deliberately don't\n // fabricate `createdAt`/`lastUpdatedAt`/`ttl` here — the handle merges\n // these from its initial `CreateTaskResult.task` so consumers always\n // see a real Task with no placeholder strings.\n const update: TaskStatusUpdate = {\n taskId: params.taskId,\n status: params.status,\n ...(params.statusMessage !== undefined && { statusMessage: params.statusMessage }),\n };\n\n for (const cb of set) cb(update);\n });\n\n return {\n subscribe(taskId, cb) {\n let set = listeners.get(taskId);\n if (!set) {\n set = new Set();\n listeners.set(taskId, set);\n }\n set.add(cb);\n return () => {\n const s = listeners.get(taskId);\n if (!s) return;\n s.delete(cb);\n if (s.size === 0) listeners.delete(taskId);\n };\n },\n dispose() {\n listeners.clear();\n unsub();\n },\n };\n}\n\n// -----------------------------------------------------------------------------\n// Caller-facing factory\n// -----------------------------------------------------------------------------\n\n/**\n * Task-augment a `tools/call` per the MCP 2025-11-25 tasks utility.\n *\n * A composable helper over {@link App} rather than a method on it: the object\n * `connect()` returns carries the ext-apps surface, and tasks ride alongside.\n * The receiver answers a task-augmented call with a `CreateTaskResult`\n * promptly; the actual `CallToolResult` arrives later via `tasks/result`.\n *\n * ```ts\n * const handle = await callToolAsTask(app, \"deep_research\", { topic });\n * handle.onStatus((t) => setStatus(t.status));\n * const result = await handle.result();\n * ```\n *\n * Throws if the host did not advertise `tasks.requests.tools.call` — per spec\n * a requestor MUST NOT task-augment without matching receiver capability.\n * Fall back to `app.callTool`.\n */\nexport async function callToolAsTask<TOutput = unknown>(\n app: App,\n toolName: string,\n args?: unknown,\n options?: CallToolAsTaskOptions,\n): Promise<TaskHandle<TOutput>> {\n const deps = internalsFor(app);\n const hostTasks = deps.hostTasksCapability;\n if (!hostTasks?.requests?.tools?.call) {\n throw new Error(\n \"callToolAsTask: host did not advertise tasks.requests.tools.call in its capabilities. \" +\n \"Per MCP 2025-11-25 §, requestors MUST NOT task-augment a tools/call without \" +\n \"matching receiver capability. Fall back to `app.callTool`.\",\n );\n }\n\n // Per spec, `task` is an object even when the caller provides no hints —\n // its presence is the signal to the receiver that augmentation is\n // requested. An empty `{}` is valid.\n const taskParam: { ttl?: number } = {};\n if (options?.ttl !== undefined) taskParam.ttl = options.ttl;\n\n // `internal` resolution:\n // - explicit `options.internal === true` → cross-server, add `server`\n // - explicit `options.internal === false` → never add `server`\n // - omitted → inherit from app-level\n // `internal` flag (same\n // semantics as `callTool`)\n const crossServer = options?.internal ?? deps.internalApp;\n\n // Build `tools/call` params. We layer our own shape on the SDK's\n // `CallToolRequest[\"params\"]` via `satisfies` so any rename upstream\n // (`name` → `toolName`, `arguments` → `args`, etc.) trips tsc. The\n // `server` extension is a NimbleBrain bridge convention, not an MCP\n // spec field.\n const callParams = {\n name: toolName,\n arguments: (args as Record<string, unknown> | undefined) ?? {},\n task: taskParam,\n ...(crossServer ? { server: deps.appName } : {}),\n } satisfies CallToolRequest[\"params\"] & { server?: string };\n\n const raw = await deps.request(\n TOOLS_CALL_METHOD,\n callParams as unknown as Record<string, unknown>,\n );\n\n // Spec: task-augmented `tools/call` returns a `CreateTaskResult`. If a\n // receiver that advertised the capability returns a bare\n // `CallToolResult` instead, that's a protocol violation — surface it.\n const createResult = raw as CreateTaskResult | null | undefined;\n const initialTask = createResult?.task;\n if (!initialTask || typeof initialTask !== \"object\" || typeof initialTask.taskId !== \"string\") {\n throw new Error(\n \"callToolAsTask: receiver returned a response without `task` per CreateTaskResult \" +\n \"(expected shape: `{ task: { taskId, status, ... } }`). Receiver may not honor \" +\n \"the advertised tasks capability.\",\n );\n }\n\n const taskId = initialTask.taskId;\n\n // Preserve the Set-semantic dedup contract on `onStatus` (matches\n // `SynapseTransport.onMessage`): registering the same callback twice\n // collapses to one wire subscription, and either returned unsub\n // releases it. Without this, every `onStatus(cb)` would create a\n // fresh wrapper that the router treats as distinct.\n const localCallbacks = new Map<(task: Task) => void, () => void>();\n\n const handle: TaskHandle<TOutput> = {\n task: initialTask,\n\n async result(): Promise<ToolCallResult<TOutput>> {\n const params = { taskId } satisfies GetTaskPayloadRequest[\"params\"];\n const rawResult = await deps.request(\n TASKS_RESULT_METHOD,\n params as unknown as Record<string, unknown>,\n );\n // Per spec §: `tasks/result` returns exactly what the non-task\n // response would return. Parse through the shared tool-result\n // parser so `_meta[\"io.modelcontextprotocol/related-task\"]`\n // propagates unchanged (key-preserving spread).\n //\n // Type note: `GetTaskPayloadResult` is a union of result shapes\n // (one per augmentable request type). For `tools/call` tasks,\n // the runtime shape is `CallToolResult`, which `parseToolResult`\n // already handles.\n const typed = rawResult as GetTaskPayloadResult;\n return parseToolResult(typed) as ToolCallResult<TOutput>;\n },\n\n async refresh(): Promise<Task> {\n const params = { taskId } satisfies GetTaskRequest[\"params\"];\n const raw = await deps.request(\n TASKS_GET_METHOD,\n params as unknown as Record<string, unknown>,\n );\n // Per spec, `tasks/get` returns the task shape FLAT (taskId, status,\n // ttl, createdAt, lastUpdatedAt, ... at the top level) — NOT\n // wrapped in a `{ task }` field (unlike `CreateTaskResult`).\n return projectTask(raw as GetTaskResult);\n },\n\n async cancel(): Promise<Task> {\n const params = { taskId } satisfies CancelTaskRequest[\"params\"];\n const raw = await deps.request(\n TASKS_CANCEL_METHOD,\n params as unknown as Record<string, unknown>,\n );\n // `CancelTaskResult` is flat like `GetTaskResult`.\n return projectTask(raw as CancelTaskResult);\n },\n\n onStatus(cb) {\n // Idempotent-in-callback: if the same `cb` is already subscribed,\n // return the existing unsub.\n const existing = localCallbacks.get(cb);\n if (existing) return existing;\n\n // Merge the notification's spec-guaranteed fields (taskId, status,\n // statusMessage) with the handle's initial `CreateTaskResult.task`\n // so the consumer always sees a full valid `Task`. `lastUpdatedAt`\n // is stamped at SDK-receive time (an approximation of the host's\n // update time — the spec doesn't wire the host's timestamp through\n // the notification, so this is the closest signal we have).\n // `createdAt`, `ttl`, `pollInterval` come from the initial task\n // because they don't change over a task's lifetime.\n const wireUnsub = deps.taskRouter.subscribe(taskId, (update) => {\n const merged: Task = {\n taskId: update.taskId,\n status: update.status,\n ttl: initialTask.ttl,\n createdAt: initialTask.createdAt,\n lastUpdatedAt: new Date().toISOString(),\n ...(initialTask.pollInterval !== undefined && {\n pollInterval: initialTask.pollInterval,\n }),\n ...(update.statusMessage !== undefined && { statusMessage: update.statusMessage }),\n };\n cb(merged);\n });\n\n const unsub = () => {\n localCallbacks.delete(cb);\n wireUnsub();\n };\n localCallbacks.set(cb, unsub);\n return unsub;\n },\n };\n\n return handle;\n}\n\n// -----------------------------------------------------------------------------\n// Internal helpers\n// -----------------------------------------------------------------------------\n\n/**\n * Project a `GetTaskResult` / `CancelTaskResult` down to the canonical\n * `Task` shape. Both result types are structurally `Task` with an\n * optional `_meta` field on top; we project explicitly so consumers\n * don't see protocol-level `_meta` leaking onto the task state they\n * get back from `refresh()` / `cancel()`.\n *\n * Asymmetry note: `parseToolResult` (for `tools/call` / `tasks/result`\n * payloads) is key-preserving — `_meta` flows through end-to-end, which\n * matters for `io.modelcontextprotocol/related-task` correlation. Here\n * we drop `_meta` because no downstream consumer reads it on `Task` state\n * today. If a host starts stamping useful keys on `tasks/get`/`tasks/cancel`\n * responses, switch to a key-preserving projection.\n */\nfunction projectTask(raw: GetTaskResult | CancelTaskResult): Task {\n return {\n taskId: raw.taskId,\n status: raw.status,\n ttl: raw.ttl,\n createdAt: raw.createdAt,\n lastUpdatedAt: raw.lastUpdatedAt,\n ...(raw.pollInterval !== undefined && { pollInterval: raw.pollInterval }),\n ...(raw.statusMessage !== undefined && { statusMessage: raw.statusMessage }),\n };\n}\n","import type { ToolResultData } from \"./types.js\";\n\nexport type { ToolResultData };\n\n/**\n * Parse inbound `ui/notifications/tool-result` notification params into\n * a consistent `ToolResultData` shape.\n *\n * Implements the 5-step parsing algorithm from the RFC:\n * 1. If `params.structuredContent` exists → use it as content.\n * 2. Else if `params.content` is an array of `{type:\"text\", text}` blocks →\n * join the text values and try JSON.parse.\n * 3. Else if `params.content` is a string → try JSON.parse.\n * 4. If JSON.parse fails in steps 2 or 3 → deliver the raw string.\n * 5. Return `{ content, structuredContent, raw }`.\n */\nexport function parseToolResultParams(params: Record<string, unknown> | undefined): ToolResultData {\n const raw = params ?? {};\n const structuredContent = raw.structuredContent ?? null;\n\n // Step 1: If structuredContent exists, use it as content\n if (structuredContent != null) {\n return { content: structuredContent, structuredContent, raw };\n }\n\n const rawContent = raw.content;\n\n // Step 2: If content is array of {type:\"text\", text} blocks, join texts and try JSON.parse\n if (Array.isArray(rawContent)) {\n const texts = rawContent\n .filter(\n (block: unknown) =>\n block != null &&\n typeof block === \"object\" &&\n (block as Record<string, unknown>).type === \"text\" &&\n typeof (block as Record<string, unknown>).text === \"string\",\n )\n .map((block: unknown) => (block as Record<string, unknown>).text as string);\n\n if (texts.length > 0) {\n const joined = texts.join(\"\");\n try {\n return { content: JSON.parse(joined), structuredContent: null, raw };\n } catch {\n return { content: joined, structuredContent: null, raw };\n }\n }\n\n // No text blocks — return raw content array\n return { content: rawContent, structuredContent: null, raw };\n }\n\n // Step 3: If content is string, try JSON.parse\n if (typeof rawContent === \"string\") {\n try {\n return { content: JSON.parse(rawContent), structuredContent: null, raw };\n } catch {\n return { content: rawContent, structuredContent: null, raw };\n }\n }\n\n // Fallback: return content as-is (could be null, object, etc.)\n return { content: rawContent ?? null, structuredContent: null, raw };\n}\n","import {\n HOST_CONTEXT_CHANGED_METHOD,\n RESOURCE_TEARDOWN_METHOD,\n TOOL_CANCELLED_METHOD,\n TOOL_INPUT_METHOD,\n TOOL_INPUT_PARTIAL_METHOD,\n TOOL_RESULT_METHOD,\n} from \"@modelcontextprotocol/ext-apps\";\n\n/**\n * NimbleBrain extension methods. No spec equivalent, so no constant to import\n * — but naming them once here means no source file spells the wire string\n * twice, and the `synapse/` prefix keeps them visibly outside the spec.\n * Hosts that don't implement them simply never send them.\n */\nexport const DATA_CHANGED_METHOD = \"synapse/data-changed\";\nexport const ACTION_METHOD = \"synapse/action\";\nexport const REQUEST_FILE_METHOD = \"synapse/request-file\";\nexport const DOWNLOAD_FILE_METHOD = \"synapse/download-file\";\n\n/**\n * Maps short event names used in App.on() to full MCP method names.\n * Uses canonical constants from @modelcontextprotocol/ext-apps to stay\n * in sync with the spec — if the spec changes a method name, this breaks\n * at compile time, not silently at runtime.\n *\n * `theme-changed`, `host-context-changed`, `data-changed` and `action` are\n * deliberately absent: `connect()` routes each of those itself, because each is\n * a typed *view* over a notification rather than the notification's raw params\n * (and the first two are two views over the same one). Listing them here would\n * be a second table nothing consults — the kind of copy that goes wrong quietly\n * because nothing reads it to notice.\n */\nconst EVENT_MAP: Record<string, string> = {\n \"tool-result\": TOOL_RESULT_METHOD,\n \"tool-input\": TOOL_INPUT_METHOD,\n \"tool-input-partial\": TOOL_INPUT_PARTIAL_METHOD,\n \"tool-cancelled\": TOOL_CANCELLED_METHOD,\n teardown: RESOURCE_TEARDOWN_METHOD,\n};\n\n/**\n * Resolve a short event name to a full MCP method name.\n * Returns the mapped method if found, otherwise passes through as-is.\n */\nexport function resolveEventMethod(name: string): string {\n return EVENT_MAP[name] ?? name;\n}\n\n/** The wire method behind the `theme-changed` / `host-context-changed` events. */\nexport { HOST_CONTEXT_CHANGED_METHOD };\n","import type { SynapseTransport } from \"./transport.js\";\nimport type { KeyForwardConfig } from \"./types.js\";\n\n/**\n * Forward keyboard shortcuts from the iframe document to the host.\n *\n * By default, forwards all Ctrl/Cmd+key combos and Escape.\n * Apps can customize via `forwardKeys` config.\n */\nexport class KeyboardForwarder {\n private listener: (event: KeyboardEvent) => void;\n private destroyed = false;\n\n constructor(transport: SynapseTransport, customKeys?: KeyForwardConfig[]) {\n const config = customKeys ?? null; // null = default behavior\n\n this.listener = (event: KeyboardEvent) => {\n if (this.destroyed) return;\n if (this.shouldForward(event, config)) {\n event.preventDefault();\n transport.send(\"synapse/keydown\", {\n key: event.key,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n altKey: event.altKey,\n });\n }\n };\n\n document.addEventListener(\"keydown\", this.listener);\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n document.removeEventListener(\"keydown\", this.listener);\n }\n\n private shouldForward(event: KeyboardEvent, config: KeyForwardConfig[] | null): boolean {\n // Empty array = forwarding disabled\n if (config && config.length === 0) return false;\n\n // Custom config: match exactly\n if (config) {\n return config.some(\n (k) =>\n event.key.toLowerCase() === k.key.toLowerCase() &&\n (k.ctrl === undefined || event.ctrlKey === k.ctrl) &&\n (k.meta === undefined || event.metaKey === k.meta) &&\n (k.shift === undefined || event.shiftKey === k.shift) &&\n (k.alt === undefined || event.altKey === k.alt),\n );\n }\n\n // Default: forward all Ctrl/Cmd combos + Escape,\n // EXCEPT clipboard shortcuts (c, v, x, a) which the browser must handle natively.\n if (event.key === \"Escape\") return true;\n if (event.ctrlKey || event.metaKey) {\n const key = event.key.toLowerCase();\n if (key === \"c\" || key === \"v\" || key === \"x\" || key === \"a\") return false;\n return true;\n }\n return false;\n }\n}\n","type SendFn = (method: string, params: Record<string, unknown>) => void;\n\ninterface Resizer {\n resize(width?: number, height?: number): void;\n measureAndSend(): void;\n destroy(): void;\n}\n\nexport function createResizer(send: SendFn, autoResize: boolean): Resizer {\n let destroyed = false;\n let observer: ResizeObserver | null = null;\n let rafId: number | null = null;\n\n function measureAndSend(): void {\n if (destroyed) return;\n const width = document.body.scrollWidth;\n const height = document.body.scrollHeight;\n send(\"ui/notifications/size-changed\", { width, height });\n }\n\n function resize(width?: number, height?: number): void {\n if (destroyed) return;\n if (width !== undefined && height !== undefined) {\n send(\"ui/notifications/size-changed\", { width, height });\n } else {\n measureAndSend();\n }\n }\n\n // Auto mode: attach ResizeObserver, debounced at 16ms via requestAnimationFrame\n if (autoResize && typeof ResizeObserver !== \"undefined\") {\n observer = new ResizeObserver(() => {\n if (destroyed) return;\n if (rafId !== null) cancelAnimationFrame(rafId);\n rafId = requestAnimationFrame(() => {\n rafId = null;\n measureAndSend();\n });\n });\n observer.observe(document.body);\n }\n\n function destroy(): void {\n if (destroyed) return;\n destroyed = true;\n if (rafId !== null) cancelAnimationFrame(rafId);\n observer?.disconnect();\n observer = null;\n }\n\n return { resize, measureAndSend, destroy };\n}\n","import type {\n JsonRpcMessage,\n JsonRpcNotification,\n JsonRpcRequest,\n JsonRpcResponse,\n} from \"./types.js\";\n\ntype PendingEntry = {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n};\n\ntype MessageHandler = (params: Record<string, unknown> | undefined) => void;\n\nexport class SynapseTransport {\n private counter = 0;\n private destroyed = false;\n private pending = new Map<string, PendingEntry>();\n private handlers = new Map<string, Set<MessageHandler>>();\n private listener: (event: MessageEvent) => void;\n\n constructor() {\n this.listener = (event: MessageEvent) => this.handleMessage(event);\n window.addEventListener(\"message\", this.listener);\n }\n\n send(method: string, params?: Record<string, unknown>): void {\n if (this.destroyed) return;\n\n const msg: JsonRpcNotification = {\n jsonrpc: \"2.0\",\n method,\n ...(params !== undefined && { params }),\n };\n window.parent.postMessage(msg, \"*\");\n }\n\n request(method: string, params?: Record<string, unknown>): Promise<unknown> {\n if (this.destroyed) {\n return Promise.reject(new Error(\"Transport destroyed\"));\n }\n\n const id = `syn-${++this.counter}`;\n const msg: JsonRpcRequest = {\n jsonrpc: \"2.0\",\n method,\n id,\n ...(params !== undefined && { params }),\n };\n\n return new Promise<unknown>((resolve, reject) => {\n this.pending.set(id, { resolve, reject });\n window.parent.postMessage(msg, \"*\");\n });\n }\n\n onMessage(method: string, callback: MessageHandler): () => void {\n if (!this.handlers.has(method)) {\n this.handlers.set(method, new Set());\n }\n this.handlers.get(method)?.add(callback);\n\n return () => {\n const set = this.handlers.get(method);\n if (set) {\n set.delete(callback);\n if (set.size === 0) {\n this.handlers.delete(method);\n }\n }\n };\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n window.removeEventListener(\"message\", this.listener);\n\n const error = new Error(\"Transport destroyed\");\n for (const entry of this.pending.values()) {\n entry.reject(error);\n }\n this.pending.clear();\n this.handlers.clear();\n }\n\n private handleMessage(event: MessageEvent): void {\n if (this.destroyed) return;\n\n const data = event.data as JsonRpcMessage;\n if (!data || data.jsonrpc !== \"2.0\") return;\n\n // Response to a pending request\n if (\"id\" in data && data.id && !(\"method\" in data)) {\n const response = data as JsonRpcResponse;\n const entry = this.pending.get(response.id);\n if (!entry) return;\n this.pending.delete(response.id);\n\n if (response.error) {\n const err = new Error(response.error.message);\n (err as any).code = response.error.code;\n (err as any).data = response.error.data;\n entry.reject(err);\n } else {\n entry.resolve(response.result);\n }\n return;\n }\n\n // Incoming notification\n if (\"method\" in data && !(\"id\" in data && data.id)) {\n const notification = data as JsonRpcNotification;\n const set = this.handlers.get(notification.method);\n if (set) {\n for (const handler of set) {\n handler(notification.params);\n }\n }\n }\n }\n}\n","import type {\n McpUiHostContext,\n McpUiHostContextChangedNotification,\n McpUiInitializeRequest,\n McpUiInitializeResult,\n McpUiMessageRequest,\n McpUiOpenLinkRequest,\n McpUiUpdateModelContextRequest,\n} from \"@modelcontextprotocol/ext-apps\";\nimport {\n HOST_CONTEXT_CHANGED_METHOD,\n INITIALIZE_METHOD,\n INITIALIZED_METHOD,\n LATEST_PROTOCOL_VERSION,\n MESSAGE_METHOD,\n OPEN_LINK_METHOD,\n TOOL_RESULT_METHOD,\n} from \"@modelcontextprotocol/ext-apps\";\nimport type {\n ReadResourceRequest,\n ReadResourceResult,\n TextContent,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { parseToolResultParams } from \"./content-parser.js\";\nimport { detectHost, extractTheme, foldFontFaces } from \"./detection.js\";\nimport { ACTION_METHOD, DATA_CHANGED_METHOD, resolveEventMethod } from \"./event-map.js\";\nimport { registerInternals } from \"./internals.js\";\nimport { KeyboardForwarder } from \"./keyboard.js\";\nimport { createResizer } from \"./resize.js\";\nimport { parseToolResult } from \"./result-parser.js\";\nimport { createTaskStatusRouter, TOOLS_CALL_METHOD } from \"./task-handle.js\";\nimport { applyTheme, fontFacesKey } from \"./theme-defaults.js\";\nimport { SynapseTransport } from \"./transport.js\";\nimport type {\n AgentAction,\n App,\n CallToolOptions,\n ConnectOptions,\n DataChangedEvent,\n Dimensions,\n FontFaceDescriptor,\n TasksCapability,\n Theme,\n ToolCallResult,\n} from \"./types.js\";\n\n// Derived locally because `@modelcontextprotocol/ext-apps` only exports\n// METHOD constants for ext-apps specific ui/* methods. Typing the literal\n// with the spec's request `method` field still produces a compile error if\n// upstream renames it.\nconst READ_RESOURCE_METHOD: ReadResourceRequest[\"method\"] = \"resources/read\";\nconst UPDATE_MODEL_CONTEXT_METHOD: McpUiUpdateModelContextRequest[\"method\"] =\n \"ui/update-model-context\";\n\n/**\n * Connect to an MCP Apps host.\n *\n * The one entry point: owns the ext-apps handshake, theme injection, content\n * parsing, resize management, and event routing, and resolves to a ready\n * {@link App}.\n *\n * The `App` it returns stays deliberately small. NimbleBrain's own extensions\n * (`action`, the file picker, `downloadFile`) and the MCP tasks utility are\n * composable functions over it — import them from the package root.\n */\nexport async function connect(options: ConnectOptions): Promise<App> {\n const { name, version, autoResize = false, internal = false, forwardKeys } = options;\n\n const transport = new SynapseTransport();\n let destroyed = false;\n\n // --- Mutable state ---\n //\n // The host context is the single source of truth. `theme` is a derived view\n // of it, not a parallel copy.\n let hostContext: McpUiHostContext = {};\n let hostInfo: { name: string; version: string } = { name: \"unknown\", version: \"unknown\" };\n let isNimbleBrainHost = false;\n let toolInfo: { tool: Record<string, unknown> } | null = null;\n let containerDimensions: Dimensions | null = null;\n let hostTasksCapability: TasksCapability | undefined;\n let keyboard: KeyboardForwarder | null = null;\n\n // Font faces are the one derived value that must NOT be recomputed from a\n // replaced context. A `host-context-changed` carries only the fields that\n // changed, so a bare `{ theme: \"dark\" }` toggle would otherwise re-derive\n // \"no fonts\" and unload the host's typeface mid-session — far more visible\n // than the equivalent for a colour token. Sticky here, cleared only by an\n // explicit empty list from the host.\n let fontFaces: FontFaceDescriptor[] | undefined;\n\n /**\n * The theme as reported to consumers: derived from the context, with the\n * sticky faces folded back in. Every public view goes through here — the\n * `theme` getter, the `theme-changed` payload, and its equality filter — so\n * they cannot disagree with each other or with what is actually loaded.\n */\n function resolveTheme(): Theme {\n const theme = extractTheme(hostContext);\n return fontFaces ? { ...theme, fontFaces } : theme;\n }\n\n // --- Event handlers ---\n //\n // Generic wire methods share one registry keyed by method. The four events\n // that are a *view* over a wire message rather than the message itself\n // (theme, host context, data-changed, action) get their own sets, because\n // two of them ride the same notification and hand their subscribers\n // different payloads.\n const handlers = new Map<string, Set<(params: unknown) => void>>();\n const themeCallbacks = new Set<(theme: Theme) => void>();\n const hostContextCallbacks = new Set<(ctx: McpUiHostContext) => void>();\n const dataCallbacks = new Set<(event: DataChangedEvent) => void>();\n const actionCallbacks = new Set<(action: AgentAction) => void>();\n\n // --- Step 1: Set up message listener (handled by SynapseTransport constructor) ---\n\n // --- Step 2: Send initial size ---\n const resizer = createResizer((method, params) => transport.send(method, params), autoResize);\n resizer.measureAndSend();\n\n // --- Steps 3-4: Send ui/initialize and wait for response ---\n //\n // `appCapabilities` is typed as `McpUiAppCapabilities` by the ext-apps spec\n // package, which does not yet model the MCP 2025-11-25 tasks utility. We\n // extend structurally via `TasksCapability` and `satisfies` the extension so\n // the nested objects match the spec literally — empty objects `{}` as\n // presence flags, NOT booleans.\n const appCapabilities = {\n tasks: {\n cancel: {},\n requests: { tools: { call: {} } },\n } satisfies TasksCapability,\n };\n const initParams: McpUiInitializeRequest[\"params\"] = {\n protocolVersion: LATEST_PROTOCOL_VERSION,\n appInfo: { name, version },\n appCapabilities:\n appCapabilities as unknown as McpUiInitializeRequest[\"params\"][\"appCapabilities\"],\n };\n\n const result = (await transport.request(\n INITIALIZE_METHOD,\n initParams as unknown as Record<string, unknown>,\n )) as McpUiInitializeResult | null;\n\n // --- Step 5: Adopt the handshake response ---\n if (result) {\n const detected = detectHost(result);\n isNimbleBrainHost = detected.isNimbleBrain;\n hostInfo = {\n name: result.hostInfo?.name ?? \"unknown\",\n version: result.hostInfo?.version ?? \"unknown\",\n };\n\n // The ext-apps `McpUiHostCapabilities` type lacks a `tasks` field (the\n // SDK extension post-dates it), so read via the result's index signature.\n const rawTasks = (result.hostCapabilities as Record<string, unknown> | undefined)?.tasks;\n hostTasksCapability =\n rawTasks && typeof rawTasks === \"object\" && !Array.isArray(rawTasks)\n ? (rawTasks as TasksCapability)\n : undefined;\n\n const ctx: McpUiHostContext | undefined = result.hostContext;\n if (ctx) {\n hostContext = ctx;\n fontFaces = foldFontFaces(fontFaces, ctx);\n\n if (ctx.toolInfo && typeof ctx.toolInfo === \"object\") {\n toolInfo = { tool: (ctx.toolInfo.tool as unknown as Record<string, unknown>) ?? {} };\n }\n if (ctx.containerDimensions && typeof ctx.containerDimensions === \"object\") {\n containerDimensions = ctx.containerDimensions as Dimensions;\n }\n\n // Inject the theme into the DOM: the host's values go inline, and the\n // neutral defaults for the mode go in a cascade layer, where they back\n // any var nobody declares and lose to every var that is declared. Any\n // host-supplied font faces load alongside — a token names a family, it\n // cannot load one.\n const theme = resolveTheme();\n applyTheme(theme.mode, theme.tokens, theme.fontFaces);\n }\n }\n\n // Keyboard forwarding is a NimbleBrain extension: only a NimbleBrain host\n // consumes `synapse/keydown`. Forwarding elsewhere would `preventDefault` a\n // key for a host that does nothing with it, so the gate is on identity, not\n // just on the option.\n if (forwardKeys && isNimbleBrainHost) {\n keyboard = new KeyboardForwarder(transport, forwardKeys === true ? undefined : forwardKeys);\n }\n\n // --- Route incoming notifications ---\n\n /**\n * Deliver a notification's raw params to anyone who subscribed by wire\n * method name rather than by short event. The three methods below are routed\n * by hand because each also has a typed view, and `ensureTransportSub` skips\n * them for that reason — so the raw fan-out has to happen here or a\n * `on(\"synapse/data-changed\", …)` would silently never fire.\n */\n function fanOutRaw(method: string, params: Record<string, unknown> | undefined): void {\n const set = handlers.get(method);\n if (!set) return;\n for (const handler of set) handler(params);\n }\n\n // `host-context-changed` feeds three different views, so it is handled once\n // here rather than through the generic registry.\n transport.onMessage(HOST_CONTEXT_CHANGED_METHOD, (params) => {\n if (destroyed) return;\n const ctx = (params ?? {}) as Partial<McpUiHostContextChangedNotification[\"params\"]>;\n const prevTheme = resolveTheme();\n\n // The spec types these params as \"a partial context update containing only\n // changed fields\", so the notification is a delta and `hostContext` is the\n // state it updates. Replacing wholesale would make a host that toggles dark\n // mode with a bare `{ theme: \"dark\" }` lose its entire palette and every\n // extension it published — `styles.variables` re-derived as `{}` strips the\n // host's CSS variables from the DOM, and `workspace` reads `undefined`.\n //\n // The merge is SHALLOW on purpose. `styles.variables` is a complete map\n // when the host sends one, so deep-merging it would leave a host no way to\n // remove a variable.\n hostContext = { ...hostContext, ...ctx };\n\n // Fonts keep their own fold even so, because it encodes a rule the merge\n // cannot: a batch whose entries are ALL malformed reads as `undefined` and\n // must leave the loaded faces alone. Deriving from the merged context would\n // instead see the key present, find nothing usable in it, and unload the\n // host's typeface — a far more visible break than the colour equivalent.\n fontFaces = foldFontFaces(fontFaces, ctx);\n const nextTheme = resolveTheme();\n\n applyTheme(nextTheme.mode, nextTheme.tokens, nextTheme.fontFaces);\n\n // Subscribers to the short event get the merged snapshot, because that is\n // what `app.hostContext` means and a delta cannot distinguish an omitted\n // field from a cleared one. A caller who genuinely wants the notification\n // as sent subscribes to the wire method instead, which `fanOutRaw` passes\n // through untouched.\n for (const cb of hostContextCallbacks) cb(hostContext);\n fanOutRaw(HOST_CONTEXT_CHANGED_METHOD, params);\n // Theme subscribers see only real theme movement: a host-context change\n // that leaves the derived theme identical (a workspace switch, say) must\n // not re-render every themed component in the app.\n if (!themesEqual(prevTheme, nextTheme)) {\n for (const cb of themeCallbacks) cb(nextTheme);\n }\n });\n\n transport.onMessage(DATA_CHANGED_METHOD, (params) => {\n if (destroyed) return;\n fanOutRaw(DATA_CHANGED_METHOD, params);\n if (!params) return;\n const event: DataChangedEvent = {\n source: \"agent\",\n server: (params.server as string) ?? \"\",\n tool: (params.tool as string) ?? \"\",\n };\n for (const cb of dataCallbacks) cb(event);\n });\n\n transport.onMessage(ACTION_METHOD, (params) => {\n if (destroyed) return;\n fanOutRaw(ACTION_METHOD, params);\n // The typed view drops an action with no `type` discriminator; a raw\n // subscriber above has already seen it verbatim.\n if (!params || typeof params.type !== \"string\") return;\n const action: AgentAction = {\n type: params.type as string,\n payload: (params.payload as Record<string, unknown>) ?? {},\n requiresConfirmation: params.requiresConfirmation === true,\n label: typeof params.label === \"string\" ? params.label : undefined,\n };\n for (const cb of actionCallbacks) cb(action);\n });\n\n // Helper to ensure a transport subscription exists for a generic method\n const subscribedMethods = new Set<string>([\n HOST_CONTEXT_CHANGED_METHOD,\n DATA_CHANGED_METHOD,\n ACTION_METHOD,\n ]);\n\n function ensureTransportSub(method: string): void {\n if (subscribedMethods.has(method)) return;\n subscribedMethods.add(method);\n\n const isToolResult = method === TOOL_RESULT_METHOD;\n\n transport.onMessage(method, (params) => {\n if (destroyed) return;\n const set = handlers.get(method);\n if (!set) return;\n for (const handler of set) {\n if (isToolResult) {\n handler(parseToolResultParams(params));\n } else {\n handler(params);\n }\n }\n });\n }\n\n /** Register one handler and return its unsubscribe. */\n function subscribe(event: string, handler: (params: any) => void): () => void {\n switch (event) {\n case \"theme-changed\":\n themeCallbacks.add(handler);\n return () => {\n themeCallbacks.delete(handler);\n };\n case \"host-context-changed\":\n hostContextCallbacks.add(handler);\n return () => {\n hostContextCallbacks.delete(handler);\n };\n case \"data-changed\":\n dataCallbacks.add(handler);\n return () => {\n dataCallbacks.delete(handler);\n };\n case \"action\":\n actionCallbacks.add(handler);\n return () => {\n actionCallbacks.delete(handler);\n };\n default: {\n const method = resolveEventMethod(event);\n if (!handlers.has(method)) handlers.set(method, new Set());\n handlers.get(method)?.add(handler);\n ensureTransportSub(method);\n return () => {\n const set = handlers.get(method);\n if (set) {\n set.delete(handler);\n if (set.size === 0) handlers.delete(method);\n }\n };\n }\n }\n }\n\n // --- Step 6: Pre-register handlers from options.on, then send initialized ---\n if (options.on) {\n for (const [event, handler] of Object.entries(options.on)) {\n if (typeof handler === \"function\") subscribe(event, handler);\n }\n }\n transport.send(INITIALIZED_METHOD, {});\n\n // Shared router for `notifications/tasks/status`. Created eagerly so the\n // transport-level listener registers exactly once — every `TaskHandle`\n // filters off this single wire subscription by taskId.\n const taskRouter = createTaskStatusRouter(transport);\n\n // --- Step 7: Build and return the App object ---\n const app: App = {\n get theme() {\n return resolveTheme();\n },\n get hostInfo() {\n return { ...hostInfo };\n },\n get hostContext() {\n return hostContext;\n },\n get isNimbleBrainHost() {\n return isNimbleBrainHost;\n },\n get toolInfo() {\n return toolInfo;\n },\n get containerDimensions() {\n return containerDimensions;\n },\n get destroyed() {\n return destroyed;\n },\n get supportsTasks() {\n return hostTasksCapability?.requests?.tools?.call !== undefined;\n },\n\n on(event: string, handler: (params: any) => void): () => void {\n return subscribe(event, handler);\n },\n\n resize(width?: number, height?: number): void {\n resizer.resize(width, height);\n },\n\n openLink(url: string): void {\n if (destroyed) return;\n const params: McpUiOpenLinkRequest[\"params\"] = { url };\n // Spec: ui/open-link is a request (expects a response), not a notification\n transport\n .request(OPEN_LINK_METHOD, params as unknown as Record<string, unknown>)\n .catch(() => {\n // Fallback: if the host doesn't respond, open directly.\n window.open(url, \"_blank\", \"noopener\");\n });\n },\n\n updateModelContext(state: Record<string, unknown>, summary?: string): void {\n if (destroyed) return;\n const params: McpUiUpdateModelContextRequest[\"params\"] = {\n structuredContent: state,\n ...(summary !== undefined && {\n content: [{ type: \"text\", text: summary } satisfies TextContent],\n }),\n };\n transport.send(UPDATE_MODEL_CONTEXT_METHOD, params as unknown as Record<string, unknown>);\n },\n\n async callTool<TOutput = unknown>(\n toolName: string,\n args?: Record<string, unknown>,\n callOptions?: CallToolOptions,\n ): Promise<ToolCallResult<TOutput>> {\n // `server` is a NimbleBrain bridge convention for cross-server dispatch,\n // not an MCP spec field. An internal app defaults to its own name, which\n // is what makes a plain `callTool` work for one.\n const server = callOptions?.server ?? (internal ? name : undefined);\n const params = {\n name: toolName,\n arguments: args ?? {},\n ...(server !== undefined && { server }),\n };\n const raw = await transport.request(TOOLS_CALL_METHOD, params);\n return parseToolResult(raw) as ToolCallResult<TOutput>;\n },\n\n async readServerResource(params: ReadResourceRequest[\"params\"]): Promise<ReadResourceResult> {\n const raw = await transport.request(\n READ_RESOURCE_METHOD,\n params as unknown as Record<string, unknown>,\n );\n return raw as ReadResourceResult;\n },\n\n sendMessage(text: string, context?: { action?: string; entity?: string }): void {\n if (destroyed) return;\n const textBlock: TextContent = {\n type: \"text\",\n text,\n // `_meta.context` is a NimbleBrain convention; other hosts ignore it,\n // but there is no reason to spend the bytes off one.\n ...(isNimbleBrainHost && context && { _meta: { context } }),\n };\n const params: McpUiMessageRequest[\"params\"] = {\n role: \"user\",\n content: [textBlock],\n };\n transport.send(MESSAGE_METHOD, params as unknown as Record<string, unknown>);\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n keyboard?.destroy();\n resizer.destroy();\n taskRouter.dispose();\n handlers.clear();\n themeCallbacks.clear();\n hostContextCallbacks.clear();\n dataCallbacks.clear();\n actionCallbacks.clear();\n transport.destroy();\n },\n };\n\n registerInternals(app, {\n send(method, params) {\n if (destroyed) return;\n transport.send(method, params);\n },\n request(method, params) {\n return transport.request(method, params);\n },\n onMessage(method, handler) {\n return transport.onMessage(method, handler);\n },\n taskRouter,\n get hostTasksCapability() {\n return hostTasksCapability;\n },\n appName: name,\n internalApp: internal,\n });\n\n return app;\n}\n\n/**\n * Shallow equality for `Theme` — used to filter host-context changes that\n * don't actually move the theme (e.g. a workspace switch that leaves\n * theme/styles untouched). Cheap; tokens are ~40 entries. Typography counts:\n * a host can swap typeface without touching mode or tokens, and that must\n * still reach subscribers.\n */\nfunction themesEqual(a: Theme, b: Theme): boolean {\n if (a.mode !== b.mode) return false;\n if (fontFacesKey(a.fontFaces) !== fontFacesKey(b.fontFaces)) return false;\n const aKeys = Object.keys(a.tokens);\n const bKeys = Object.keys(b.tokens);\n if (aKeys.length !== bKeys.length) return false;\n // Iterating only over `a`'s keys is sufficient: under equal length, any key\n // in `a` missing from `b` reads `b[k] === undefined`, which fails the strict\n // inequality check. Symmetric difference is covered.\n for (const k of aKeys) {\n if (a.tokens[k] !== b.tokens[k]) return false;\n }\n return true;\n}\n","/**\n * NimbleBrain host extensions — composable functions over {@link App}.\n *\n * These are not ext-apps spec surface. They ride the `synapse/` method prefix,\n * which `McpUiHostContext`'s open index signature makes legal, and only a\n * NimbleBrain host implements them. They live here rather than on the `App`\n * object so the object stays the spec surface plus the handshake state, and\n * so an app that never picks a file never pulls this code in.\n *\n * Every one of them is gated on the host identity established by the\n * handshake: off a NimbleBrain host, the fire-and-forget ones are no-ops and\n * the ones with a return value throw, because a picker that silently resolves\n * `null` forever is worse than one that says it isn't there.\n */\nimport { ACTION_METHOD, DOWNLOAD_FILE_METHOD, REQUEST_FILE_METHOD } from \"./event-map.js\";\nimport { internalsFor } from \"./internals.js\";\nimport type { App, FileResult, RequestFileOptions } from \"./types.js\";\n\n/** 25 MB — the host's default cap on a single picked file. */\nconst DEFAULT_MAX_FILE_SIZE = 26_214_400;\n\n/**\n * Trigger a host-side action.\n *\n * The inverse direction of the `action` event: this sends a command *to* the\n * host (navigate, open a panel), where `app.on(\"action\", …)` receives the ones\n * a tool emits. No-op off a NimbleBrain host.\n */\nexport function action(app: App, name: string, params?: Record<string, unknown>): void {\n if (!app.isNimbleBrainHost) return;\n // The outbound frame reuses the inbound method name; the host distinguishes\n // direction, not method.\n internalsFor(app).send(ACTION_METHOD, { action: name, ...params });\n}\n\n/**\n * Hand the user a file to save.\n *\n * Precedence for the MIME type: the explicit argument, then the Blob's own\n * type, then `application/octet-stream`. An empty-string argument falls\n * through — a `\"\"` MIME is effectively \"no type\".\n */\nexport function downloadFile(\n app: App,\n filename: string,\n content: string | Blob,\n mimeType?: string,\n): void {\n const resolvedMime =\n mimeType || (content instanceof Blob ? content.type : \"\") || \"application/octet-stream\";\n const blob = content instanceof Blob ? content : new Blob([content], { type: resolvedMime });\n internalsFor(app).send(DOWNLOAD_FILE_METHOD, {\n data: blob,\n filename,\n mimeType: resolvedMime,\n });\n}\n\n/**\n * Request one file from the user via the host's native file picker.\n *\n * Resolves `null` if the user cancels. Throws off a NimbleBrain host.\n */\nexport async function pickFile(app: App, options?: RequestFileOptions): Promise<FileResult | null> {\n if (!app.isNimbleBrainHost) {\n throw new Error(\"pickFile is not supported in this host\");\n }\n const result = await requestFile(app, options, false);\n if (result === null) return null;\n // The host may return an array even for a single pick — take the first\n // entry to preserve the documented `FileResult | null` shape.\n return Array.isArray(result) ? (result[0] ?? null) : result;\n}\n\n/**\n * Request several files from the user.\n *\n * Resolves `[]` if the user cancels. Throws off a NimbleBrain host.\n */\nexport async function pickFiles(app: App, options?: RequestFileOptions): Promise<FileResult[]> {\n if (!app.isNimbleBrainHost) {\n throw new Error(\"pickFiles is not supported in this host\");\n }\n const result = await requestFile(app, options, true);\n if (result === null) return [];\n return Array.isArray(result) ? result : [result];\n}\n\n/**\n * Shared request path for `pickFile` / `pickFiles`. Centralizes:\n *\n * - The wire method name (which is what the NimbleBrain bridge actually\n * handles — earlier SDK versions sent `synapse/pick-file` and the call would\n * silently time out).\n * - Runtime shape validation. Older hosts (pre-`POST /v1/resources`) still\n * respond but return the legacy `{ base64Data, … }` shape. The TS type\n * promises a string `id`; without this guard, consumers would silently get\n * `undefined.id` and fail downstream in confusing ways. Failing loud at the\n * boundary tells the developer exactly which side is mismatched.\n */\nasync function requestFile(\n app: App,\n options: RequestFileOptions | undefined,\n multiple: boolean,\n): Promise<FileResult | FileResult[] | null> {\n const result = await internalsFor(app).request(REQUEST_FILE_METHOD, {\n accept: options?.accept,\n maxSize: options?.maxSize ?? DEFAULT_MAX_FILE_SIZE,\n multiple,\n });\n if (result == null) return null;\n if (Array.isArray(result)) {\n return result.map(validateFileResult);\n }\n return validateFileResult(result);\n}\n\nfunction validateFileResult(value: unknown): FileResult {\n if (\n typeof value !== \"object\" ||\n value === null ||\n typeof (value as { id?: unknown }).id !== \"string\"\n ) {\n throw new Error(\n \"synapse/request-file returned a result without a string `id`. \" +\n \"The host appears to be on a version older than this SDK targets — \" +\n \"@nimblebrain/synapse 0.8.0+ requires a host with POST /v1/resources \" +\n \"(NimbleBrain ≥ the version that ships PR #93).\",\n );\n }\n return value as FileResult;\n}\n"]}
@@ -23,6 +23,7 @@ var LIGHT = {
23
23
  "--color-ring-primary": "#2563eb",
24
24
  // ── Status / brand semantics ──
25
25
  "--nb-color-danger": "#dc2626",
26
+ "--nb-color-danger-foreground": "#ffffff",
26
27
  "--nb-color-success": "#059669",
27
28
  "--nb-color-warning": "#f59e0b",
28
29
  "--nb-color-processing": "#7c3aed",
@@ -46,6 +47,8 @@ var DARK = {
46
47
  "--color-ring-primary": "#818cf8",
47
48
  // ── Status / brand semantics (brightened for contrast on dark) ──
48
49
  "--nb-color-danger": "#f87171",
50
+ // Dark text on the brightened red: white on #f87171 is under 3:1.
51
+ "--nb-color-danger-foreground": "#18181b",
49
52
  "--nb-color-success": "#34d399",
50
53
  "--nb-color-warning": "#fbbf24",
51
54
  "--nb-color-processing": "#a78bfa",
@@ -181,5 +184,5 @@ function foldFontFaces(prev, ctx) {
181
184
  }
182
185
 
183
186
  export { FONT_FACES_CONTEXT_KEY, applyTheme, detectHost, extractTheme, foldFontFaces, fontFacesKey };
184
- //# sourceMappingURL=chunk-UPDBDXQB.js.map
185
- //# sourceMappingURL=chunk-UPDBDXQB.js.map
187
+ //# sourceMappingURL=chunk-HKRTDGXN.js.map
188
+ //# sourceMappingURL=chunk-HKRTDGXN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/theme-defaults.ts","../src/detection.ts"],"names":[],"mappings":"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","file":"chunk-HKRTDGXN.js","sourcesContent":["/**\n * Theme-aware default backing for the `@nimblebrain/synapse/ui` token contract.\n *\n * `tokens` (see `ui/tokens.ts`) are `var(--token, fallback)` references. A CSS\n * `var()` fallback is a *static literal* — it cannot branch on light vs. dark.\n * So any var the host does NOT inject resolves to its single hardcoded (light)\n * fallback in BOTH themes. Pair such a token with a theme-aware one and you get\n * white-on-white in dark mode: it looks correct in light, passes `tsc`/build,\n * and only breaks when the theme is toggled.\n *\n * This module closes that gap with a default layer the SDK controls and that\n * CAN branch on theme. {@link applyThemeVariables} puts the neutral defaults for\n * the active `mode` in a cascade layer and the host's variables inline — so:\n * - the host's (brand) values always win for the keys it provides, through\n * either the protocol or a stylesheet it injects, and\n * - any var nobody declares still resolves to a theme-correct neutral value.\n *\n * It's the `var()` fallback, but able to branch on theme. The values stay\n * neutral grays, a generic blue, and generic semantic hues for danger, success,\n * warning and processing — never a *brand* value. Brand arrives only by host\n * injection, mirroring `ui/tokens.ts`. `__tests__/ui/tokens.test.ts` holds the\n * line: every hex here must be in the sanctioned set. This keeps\n * the library host-agnostic while guaranteeing every token resolves correctly\n * in both themes even against an incomplete host, a standalone `connect()`\n * widget, or a third-party host.\n *\n * Font *faces* are the one part of theming CSS variables cannot carry — a token\n * names a family, it cannot load one. {@link applyThemeFontFaces} closes that\n * half, and {@link applyTheme} applies both together.\n *\n * Only theme-sensitive (color) vars are listed here. Theme-invariant vars\n * (radii, type scale, shadows, font stacks, weights, border widths) look the\n * same in both themes, so their static `var()` fallback is already correct —\n * they are intentionally absent. The `tokens` regression test enforces this\n * with a TOTAL partition: every referenced var must be either declared\n * theme-invariant (an explicit allowlist) or defined in both maps below, so a\n * newly added theme-sensitive token can't slip through unbacked.\n */\n\nimport type { FontDisplayValue, FontFaceDescriptor } from \"./types.js\";\n\nconst FONT_DISPLAY_VALUES = new Set<FontDisplayValue>([\n \"auto\",\n \"block\",\n \"swap\",\n \"fallback\",\n \"optional\",\n]);\n\n/**\n * Light-theme neutral defaults. Values match the (light) fallbacks baked into\n * `tokens` — applying them changes nothing observable in light mode; they exist\n * so the light path flows through the same code as dark and so a standalone\n * render with an explicit `light` theme is backed identically to its fallbacks.\n */\nconst LIGHT: Record<string, string> = {\n // ── Surfaces ──\n \"--color-background-primary\": \"#ffffff\",\n \"--color-background-secondary\": \"#fafafa\",\n \"--color-background-tertiary\": \"#f3f4f6\",\n // ── Text ──\n \"--color-text-primary\": \"#111827\",\n \"--color-text-secondary\": \"#6b7280\",\n \"--color-text-tertiary\": \"#9ca3af\",\n \"--color-text-accent\": \"#2563eb\",\n \"--nb-color-accent-foreground\": \"#ffffff\",\n // ── Border / ring ──\n \"--color-border-primary\": \"#e5e7eb\",\n \"--color-border-secondary\": \"#d1d5db\",\n \"--color-ring-primary\": \"#2563eb\",\n // ── Status / brand semantics ──\n \"--nb-color-danger\": \"#dc2626\",\n \"--nb-color-danger-foreground\": \"#ffffff\",\n \"--nb-color-success\": \"#059669\",\n \"--nb-color-warning\": \"#f59e0b\",\n \"--nb-color-processing\": \"#7c3aed\",\n \"--nb-color-processing-light\": \"#f3eeff\",\n \"--nb-color-info-light\": \"#eef4ff\",\n};\n\n/**\n * Dark-theme neutral defaults. A monotonic neutral ladder — the three surface\n * tiers are the darkest, borders sit a step lighter so they stay visible\n * against every surface, and text inverts to light. \"Subtle\"/\"strong\" keep\n * their light-mode semantics: `bgSubtle` reads as a lifted hover/inset tint and\n * `borderStrong` is more prominent than `border`.\n */\nconst DARK: Record<string, string> = {\n // ── Surfaces (base → lifted) ──\n \"--color-background-primary\": \"#18181b\",\n \"--color-background-secondary\": \"#27272a\",\n \"--color-background-tertiary\": \"#2f2f34\",\n // ── Text ──\n \"--color-text-primary\": \"#fafafa\",\n \"--color-text-secondary\": \"#a1a1aa\",\n \"--color-text-tertiary\": \"#71717a\",\n \"--color-text-accent\": \"#818cf8\",\n \"--nb-color-accent-foreground\": \"#ffffff\",\n // ── Border / ring (lighter than surfaces so they remain visible) ──\n \"--color-border-primary\": \"#3f3f46\",\n \"--color-border-secondary\": \"#52525b\",\n \"--color-ring-primary\": \"#818cf8\",\n // ── Status / brand semantics (brightened for contrast on dark) ──\n \"--nb-color-danger\": \"#f87171\",\n // Dark text on the brightened red: white on #f87171 is under 3:1.\n \"--nb-color-danger-foreground\": \"#18181b\",\n \"--nb-color-success\": \"#34d399\",\n \"--nb-color-warning\": \"#fbbf24\",\n \"--nb-color-processing\": \"#a78bfa\",\n \"--nb-color-processing-light\": \"#2a2440\",\n \"--nb-color-info-light\": \"#1e2a44\",\n};\n\n/**\n * The neutral default theme, keyed by mode. Exported for the regression test\n * that asserts every color var referenced by `tokens` is backed in both modes.\n */\nexport const DEFAULT_THEME_VARS: Record<\"light\" | \"dark\", Record<string, string>> = {\n light: LIGHT,\n dark: DARK,\n};\n\n/** Cascade layer holding the neutral defaults. Named so an app can order it. */\nexport const DEFAULTS_LAYER_NAME = \"synapse-defaults\";\n\n/** `id` of the single `<style>` element this module owns. */\nexport const DEFAULTS_STYLE_ID = \"synapse-theme-defaults\";\n\n/** Custom properties this module last wrote inline, so a later apply clears only\n * what it owns and never an inline property the app set itself. */\nlet appliedInlineKeys = new Set<string>();\n\n/** Test seam — forget what was written inline so a fresh apply is observable. */\nexport function resetAppliedInlineKeys(): void {\n appliedInlineKeys = new Set();\n}\n\n/**\n * Whether this document can host the defaults stylesheet.\n *\n * Not the same question as `typeof document !== \"undefined\"`. An embedder or a\n * test harness may install a *partial* `document` — `documentElement.style` plus\n * listeners and nothing else — which is everything this module needed while the\n * defaults were inline properties. Moving them into a stylesheet added three new\n * requirements (`getElementById`, `createElement`, `head.prepend`), and reaching\n * for them on such a document throws.\n *\n * A throw here is not contained: it unwinds through `applyTheme` into the\n * handshake, so an app in that environment never finishes connecting. The\n * default layer is a rendering nicety and the connection is not, so a document\n * that cannot carry a stylesheet gets no layer rather than no session.\n */\nfunction canInstallStylesheet(): boolean {\n return (\n typeof document !== \"undefined\" &&\n typeof document.getElementById === \"function\" &&\n typeof document.createElement === \"function\" &&\n typeof document.head?.prepend === \"function\"\n );\n}\n\n/**\n * Install the neutral defaults for `mode` as a cascade layer.\n *\n * A layer, not inline properties on `documentElement`, and that distinction is\n * the whole point: **a default has to lose.** An inline style outranks every\n * author stylesheet, so writing defaults there made them beat any rule a host or\n * app had written for the same var — the opposite of a fallback.\n *\n * A host cannot always deliver a var through the protocol.\n * `hostContext.styles.variables` is a closed enum, so a host whose design system\n * is larger than that enum has to put the remainder in a stylesheet it injects\n * into the app document. Those declarations are ordinary unlayered author rules.\n * Unlayered beats layered, so they now win — while a var nobody declares still\n * resolves to a neutral default, which is what this map is for.\n *\n * An app's own `:root` rule wins for the same reason, so overriding a default\n * needs no `!important` and no knowledge of this module.\n *\n * One element, replaced in place, so a mode flip swaps the whole map atomically\n * and repeat calls are cheap. SSR-safe.\n */\nfunction applyDefaultThemeLayer(mode: \"light\" | \"dark\"): void {\n if (!canInstallStylesheet()) return;\n\n // Safe to concatenate ONLY because every key and value here is module-local\n // (`DEFAULT_THEME_VARS`). `applyThemeFontFaces` below deliberately avoids\n // building CSS text for exactly this reason — a host-supplied value containing\n // `}` would escape the rule. Never fold host or app input into this template;\n // host variables go through `setProperty`, which cannot escape.\n const declarations = Object.entries(DEFAULT_THEME_VARS[mode])\n .map(([k, v]) => ` ${k}: ${v};`)\n .join(\"\\n\");\n const css = `@layer ${DEFAULTS_LAYER_NAME} {\\n :root {\\n${declarations}\\n }\\n}`;\n\n const existing = document.getElementById(DEFAULTS_STYLE_ID);\n if (existing) {\n // Avoid a needless style invalidation when the mode hasn't changed.\n if (existing.textContent !== css) existing.textContent = css;\n return;\n }\n const el = document.createElement(\"style\");\n el.id = DEFAULTS_STYLE_ID;\n el.textContent = css;\n // Prepended so this is the first layer the document declares, which puts it\n // first in layer order — an app that declares its own layers sorts after, and\n // therefore wins. Unlayered app rules win regardless of DOM order.\n document.head.prepend(el);\n}\n\n/**\n * Apply theme CSS custom properties to the app document.\n *\n * The host's variables go inline on `documentElement`, where they outrank\n * everything; the neutral defaults for `mode` go into a cascade layer, where\n * they lose to any rule that actually declares the var. So a host value beats\n * this module's default through *either* channel — the protocol or a stylesheet\n * it injects — and a var nobody declares still resolves to a theme-correct\n * default. Only the protocol channel also outranks the app: a host's injected\n * stylesheet and the app's own `:root` are both unlayered rules of equal\n * specificity, so document order decides between them, not this module.\n *\n * A key this module wrote on a previous call and the incoming set does NOT carry\n * is *removed* inline rather than left behind, because a host may legitimately\n * narrow its key set: stop sending a var and it must stop applying, or it stays\n * pinned inline forever where the layer, the host's own stylesheet and the app's\n * own rules all cannot reach it. Removing lets the cascade resolve it against\n * those instead, which is the property this module exists to establish, and is\n * strictly less destructive than overwriting the key with our own default.\n *\n * Tracked as the set of keys last written, not as `DEFAULT_THEME_VARS`'s keys.\n * Those are two different sets: a host can send any spec-enum var, and ~25\n * theme-sensitive ones (`--color-text-danger`, `--color-background-inverse`, …)\n * have no neutral default, so keying the removal off the default map would pin\n * exactly those at the previous mode's value. Tracking what we wrote also means\n * this module never clears an inline property it did not set — an app writing its\n * own `documentElement.style` is left alone.\n *\n * Today an empty var set also arrives for a reason that is a bug rather than a\n * narrowing — `core.ts` replaces the host context wholesale, so a partial\n * `host-context-changed` that omits `styles` reads as \"no tokens\" (#46;\n * `connect.ts` already carries them forward). Fixing #46 is the better outcome —\n * it keeps the host's brand across a mode flip instead of collapsing to our\n * neutral — and does not make this loop unnecessary.\n *\n * SSR-safe (no-ops when `document` is unavailable). Idempotent — re-applying on\n * every theme change is correct and cheap.\n *\n * Prefer {@link applyTheme}: it applies variables *and* font faces together, so\n * a caller cannot wire up half a theme.\n */\nexport function applyThemeVariables(\n mode: \"light\" | \"dark\",\n hostVars: Record<string, string> | undefined | null,\n): void {\n if (typeof document === \"undefined\") return;\n applyDefaultThemeLayer(mode);\n\n // ONE definition of \"the host provided this key\", read by both loops below.\n // Wire data is untyped, so a key can arrive with a non-string value; that is\n // not a provided value, so the clear loop must reach it. Two predicates —\n // `k in hostVars` to clear, `typeof v === \"string\"` to write — leave such a key\n // in the gap: neither removed nor written, so the previous theme's value stays\n // pinned inline where the layer, the host's stylesheet and the app's `:root`\n // all cannot reach it. That is the un-self-healing pin this module exists to\n // eliminate, re-entered by a different door.\n const incoming: Record<string, string> = {};\n if (hostVars && typeof hostVars === \"object\") {\n for (const [k, v] of Object.entries(hostVars)) {\n if (typeof k === \"string\" && typeof v === \"string\") incoming[k] = v;\n }\n }\n\n const root = document.documentElement.style;\n // `removeProperty` is feature-checked and `setProperty` deliberately is not.\n // The setter is the one capability this module has always required, so a\n // document lacking it was never supported and gets no new promise here; the\n // clear pass arrived with the defaults layer, so a `style` carrying only the\n // setter is a shape that used to work. Dropping the clear pass for it is far\n // better than throwing out of the loop and leaving the host's variables\n // unwritten entirely.\n if (typeof root.removeProperty === \"function\") {\n for (const k of appliedInlineKeys) {\n if (!(k in incoming)) root.removeProperty(k);\n }\n }\n for (const [k, v] of Object.entries(incoming)) root.setProperty(k, v);\n appliedInlineKeys = new Set(Object.keys(incoming));\n}\n\n/** The faces this module has added, so a re-apply replaces rather than accumulates. */\nconst managedFaces = new Set<FontFace>();\n\n/** Signature of the currently-applied set — lets a repeat call no-op. */\nlet appliedFontKey = \"\";\n\n/** Stable signature of a face list — the one comparison rule for \"same fonts?\",\n * shared by the sink's re-apply guard and `onThemeChanged`'s equality filter. */\nexport function fontFacesKey(faces: readonly FontFaceDescriptor[] | undefined | null): string {\n if (!Array.isArray(faces)) return \"\";\n return JSON.stringify(faces.map((d) => [d.family, d.src, d.weight, d.style, d.display]));\n}\n\n/**\n * Normalise an untrusted face list into the one shape every layer trusts.\n *\n * THE rule, in one place:\n * - not an array → `undefined` — nothing was said, keep what's loaded\n * - array, none usable → `undefined` — a shape mistake is not a clear\n * - array, some usable → those entries\n * - empty array → `[]` — the explicit clear\n *\n * The wire and the sink each used to spell this out separately and drifted\n * apart, so a host whose descriptors were mis-shaped kept its typeface through\n * one path and lost it through the other. One predicate, one spelling.\n */\nexport function normalizeFontFaces(raw: unknown): FontFaceDescriptor[] | undefined {\n if (!Array.isArray(raw)) return undefined;\n const usable = raw.filter(isFontFaceDescriptor);\n if (raw.length > 0 && usable.length === 0) return undefined;\n return usable;\n}\n\n/**\n * Load host-supplied `@font-face`s into the app document.\n *\n * Uses the CSSOM {@link FontFace} constructor rather than building `@font-face`\n * CSS text. That is deliberate, and load-bearing for two reasons:\n *\n * 1. **No CSS-injection sink.** `family` and `src` are separate arguments, not\n * concatenated into a stylesheet, so a host value containing `}` cannot\n * escape the rule and inject arbitrary CSS into the app.\n * 2. **Uniform URL handling.** The `src` descriptor is parsed by the browser\n * against the `src` grammar, so relative (`url('/fonts/x.woff2')`), absolute\n * (`url('https://cdn.example/x.woff2')`) and `data:` forms all just work.\n * A malformed descriptor throws `SyntaxError` here instead of silently\n * producing dead CSS.\n *\n * The SDK ships no font data. A host that sends nothing leaves the web-safe\n * fallbacks in `ui/tokens.ts` in force — which is why omitting fonts entirely is\n * a supported configuration, not a degraded one.\n *\n * Faces are added but not force-loaded: the browser fetches a face when CSS\n * first matches it, so an unused weight costs nothing. `display` defaults to\n * `swap` so text paints in the fallback immediately rather than blocking.\n *\n * SSR-safe, and safe in environments without the CSS Font Loading API (older\n * jsdom): both no-op. Re-applying an unchanged set is a no-op.\n */\nexport function applyThemeFontFaces(faces: readonly FontFaceDescriptor[] | undefined | null): void {\n // `normalizeFontFaces` owns what absent/garbage means. Reached from the public\n // `applyHostTheme`, so the input here is not necessarily typed: a host\n // building `fontFaces` from untrusted JSON can hand us mis-shaped entries,\n // and reading those as \"clear\" would unload the typeface over a typo.\n const next = normalizeFontFaces(faces);\n if (next === undefined) return;\n if (typeof document === \"undefined\") return;\n // `document.fonts` (CSS Font Loading API) is absent in some test DOMs.\n if (!document.fonts || typeof FontFace === \"undefined\") return;\n\n const key = fontFacesKey(next);\n if (key === appliedFontKey) return;\n appliedFontKey = key;\n\n for (const face of managedFaces) {\n try {\n document.fonts.delete(face);\n } catch {\n // Already evicted, or the API rejected the handle — nothing to undo.\n }\n }\n managedFaces.clear();\n\n for (const d of next) {\n try {\n const face = new FontFace(d.family, d.src, {\n weight: d.weight,\n style: d.style,\n // Wire data is untyped: ignore an unrecognised `display` rather than let\n // the constructor reject the descriptor and cost the app this face.\n display: d.display && FONT_DISPLAY_VALUES.has(d.display) ? d.display : \"swap\",\n });\n document.fonts.add(face);\n managedFaces.add(face);\n } catch {\n // Malformed descriptor — skip this face and keep the web-safe fallback.\n // One bad entry must not cost the app the rest of its typography.\n }\n }\n}\n\nfunction isFontFaceDescriptor(value: unknown): value is FontFaceDescriptor {\n if (!value || typeof value !== \"object\") return false;\n const d = value as Partial<FontFaceDescriptor>;\n return typeof d.family === \"string\" && typeof d.src === \"string\";\n}\n\n/**\n * Apply a resolved theme to the app document — CSS variables and font faces.\n *\n * This is the single path by which theming reaches the DOM: the handshake and\n * `host-context-changed` both funnel through here. Keeping colour and typography on one call is the point — two entry\n * points invite a caller to wire one and forget the other, shipping a host's\n * palette under the wrong typeface.\n *\n * Omitting `fontFaces` is safe and means \"leave the loaded faces alone\" (see\n * {@link applyThemeFontFaces}), so a caller re-applying a theme derived from a\n * partial host context cannot silently strip the host's typeface.\n */\nexport function applyTheme(\n mode: \"light\" | \"dark\",\n hostVars: Record<string, string> | undefined | null,\n fontFaces?: readonly FontFaceDescriptor[] | null,\n): void {\n applyThemeVariables(mode, hostVars);\n applyThemeFontFaces(fontFaces);\n}\n\n/** Test seam — forget applied faces so a fresh apply is observable. */\nexport function resetAppliedFontFaces(): void {\n managedFaces.clear();\n appliedFontKey = \"\";\n}\n","import type { McpUiHostContext, McpUiInitializeResult } from \"@modelcontextprotocol/ext-apps\";\nimport { normalizeFontFaces } from \"./theme-defaults.js\";\nimport type { FontFaceDescriptor, HostInfo, Theme } from \"./types\";\n\n/**\n * Host-context key carrying `@font-face` descriptors.\n *\n * A NimbleBrain extension (`synapse/` prefix), because the ext-apps spec has no\n * equivalent: `styles.variables` is a flat `Record<McpUiStyleVariableKey, string>`\n * that can name a font family but cannot carry the rule that loads it.\n * `McpUiHostContext` declares `[key: string]: unknown` for forward\n * compatibility, so riding an extra key is spec-legal, and hosts that don't send\n * it degrade to the web-safe token fallbacks.\n */\nexport const FONT_FACES_CONTEXT_KEY = \"synapse/fontFaces\";\n\nconst DEFAULT_THEME: Theme = {\n mode: \"light\",\n tokens: {},\n};\n\n/**\n * Detect the host environment from the ext-apps `ui/initialize` response.\n *\n * Reports identity only (host name, protocol version). Theme lives in the\n * unified host-context state and is read via `extractTheme(hostContext)`\n * — no parallel `theme` field on `HostInfo`.\n *\n * Handles missing or malformed fields gracefully — never throws.\n */\nexport function detectHost(initResponse: unknown): HostInfo {\n const resp = initResponse as Partial<McpUiInitializeResult> | null | undefined;\n\n const hostName = resp?.hostInfo?.name ?? \"unknown\";\n const protocolVersion = resp?.protocolVersion ?? \"unknown\";\n\n return {\n isNimbleBrain: hostName === \"nimblebrain\",\n serverName: hostName,\n protocolVersion,\n };\n}\n\nexport function extractTheme(ctx: Partial<McpUiHostContext> | undefined): Theme {\n if (!ctx) return { ...DEFAULT_THEME };\n\n // Spec: theme is a string (\"light\" | \"dark\")\n const mode = ctx.theme === \"light\" || ctx.theme === \"dark\" ? ctx.theme : DEFAULT_THEME.mode;\n\n // Spec: tokens live under styles.variables\n const variables = ctx.styles?.variables;\n const tokens =\n variables && typeof variables === \"object\" && !Array.isArray(variables)\n ? (variables as Record<string, string>)\n : {};\n\n // Deliberately no `fontFaces` here. Faces are sticky across a partial context\n // (see `foldFontFaces`), and this function sees only the context in hand — so\n // populating the field would publish a NON-sticky value on the return type and\n // invite `extractTheme(ctx).fontFaces`, which is the unload-on-toggle bug.\n // `resolveTheme` overlays the sticky set; nothing else should.\n return { mode, tokens };\n}\n\n/**\n * Read the `synapse/fontFaces` host-context extension.\n *\n * `undefined` and `[]` are **distinct answers**, because a host-context-changed\n * carries only the fields that changed:\n * - `undefined` — the host said nothing about fonts, so keep what's loaded.\n * - `[]` — the host explicitly sent an empty list, i.e. drop the faces.\n * Collapsing the two would leave a host no way to clear typography it had\n * previously set.\n *\n * Individual malformed entries are dropped rather than rejecting the batch —\n * one bad face must not cost the app the rest of its typography. Anything that\n * survives is still validated by the browser when the descriptor is built.\n */\nexport function extractFontFaces(\n ctx: Partial<McpUiHostContext> | undefined,\n): FontFaceDescriptor[] | undefined {\n return normalizeFontFaces(ctx?.[FONT_FACES_CONTEXT_KEY]);\n}\n\n/**\n * THE rule for merging incoming faces over what is already loaded, in one\n * place: **absent — or a batch with nothing usable — means unchanged; an\n * explicit list, including empty, replaces.**\n *\n * Every consumer of the host-context font extension folds through here. The\n * rule leaked one layer at a time when each site spelled it itself, so the\n * spelling now lives once and the call sites just call it.\n */\nexport function foldFontFaces(\n prev: FontFaceDescriptor[] | undefined,\n ctx: Partial<McpUiHostContext> | undefined,\n): FontFaceDescriptor[] | undefined {\n return extractFontFaces(ctx) ?? prev;\n}\n"]}
@@ -25,6 +25,7 @@ var LIGHT = {
25
25
  "--color-ring-primary": "#2563eb",
26
26
  // ── Status / brand semantics ──
27
27
  "--nb-color-danger": "#dc2626",
28
+ "--nb-color-danger-foreground": "#ffffff",
28
29
  "--nb-color-success": "#059669",
29
30
  "--nb-color-warning": "#f59e0b",
30
31
  "--nb-color-processing": "#7c3aed",
@@ -48,6 +49,8 @@ var DARK = {
48
49
  "--color-ring-primary": "#818cf8",
49
50
  // ── Status / brand semantics (brightened for contrast on dark) ──
50
51
  "--nb-color-danger": "#f87171",
52
+ // Dark text on the brightened red: white on #f87171 is under 3:1.
53
+ "--nb-color-danger-foreground": "#18181b",
51
54
  "--nb-color-success": "#34d399",
52
55
  "--nb-color-warning": "#fbbf24",
53
56
  "--nb-color-processing": "#a78bfa",
@@ -188,5 +191,5 @@ exports.detectHost = detectHost;
188
191
  exports.extractTheme = extractTheme;
189
192
  exports.foldFontFaces = foldFontFaces;
190
193
  exports.fontFacesKey = fontFacesKey;
191
- //# sourceMappingURL=chunk-TXJMGQYF.cjs.map
192
- //# sourceMappingURL=chunk-TXJMGQYF.cjs.map
194
+ //# sourceMappingURL=chunk-LPWEQCZV.cjs.map
195
+ //# sourceMappingURL=chunk-LPWEQCZV.cjs.map