{"version":3,"sources":["../src/errors.ts","../src/internals.ts","../src/result-parser.ts","../src/task-handle.ts","../src/content-parser.ts","../src/keyboard.ts","../src/resize.ts","../src/connect.ts","../src/extensions.ts"],"names":["TOOLS_CALL_METHOD","raw","KEYDOWN_METHOD","SIZE_CHANGED_METHOD","TOOL_INPUT_METHOD","TOOL_INPUT_PARTIAL_METHOD","TOOL_RESULT_METHOD","TOOL_CANCELLED_METHOD","ExtAppsApp","extractTheme","extractHostFontCss","applyTheme","ResultSchema","HOST_CONTEXT_CHANGED_METHOD","RESOURCE_TEARDOWN_METHOD","resolveEventMethod","NIMBLEBRAIN_EXTENSIONS","CallToolResultSchema"],"mappings":"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","file":"chunk-HQLSVUOR.cjs","sourcesContent":["/**\n * Thrown when an app asks for something the host did not declare in\n * `ui/initialize`.\n *\n * The request is never sent. A host that does not implement a request may never\n * answer it, and this SDK's requests carry no deadline, so sending anyway would\n * leave the caller waiting forever rather than failing.\n *\n * `capability` names what was missing, as the host would have declared it: a\n * `hostCapabilities` field (`serverTools`, `downloadFile`) or an extension\n * identifier (`ai.nimblebrain/request-file`, `io.modelcontextprotocol/tasks`).\n */\nexport class HostCapabilityError extends Error {\n  readonly capability: string;\n\n  constructor(feature: string, capability: string) {\n    super(`${feature} is not supported in this host: it did not declare ${capability}`);\n    this.name = \"HostCapabilityError\";\n    this.capability = capability;\n  }\n}\n","/**\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 { McpUiHostCapabilities } from \"@modelcontextprotocol/ext-apps\";\nimport 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 { HostCapabilityError } from \"./errors.js\";\nimport { TOOLS_CALL_METHOD } from \"./event-map.js\";\nimport { internalsFor } from \"./internals.js\";\nimport { parseToolResult } from \"./result-parser.js\";\nimport type {\n  App,\n  CallToolAsTaskOptions,\n  TaskHandle,\n  TaskStatusRouter,\n  TaskStatusUpdate,\n  TasksCapability,\n  ToolCallResult,\n} from \"./types.js\";\n\nexport type { TaskStatusRouter, TaskStatusUpdate };\n\n// -----------------------------------------------------------------------------\n// Host capability\n// -----------------------------------------------------------------------------\n\n/** The MCP Tasks extension identifier. */\nexport const TASKS_EXTENSION_ID = \"io.modelcontextprotocol/tasks\";\n\n/**\n * The host's tasks capability, from the `ui/initialize` result.\n *\n * It lives in `hostCapabilities.experimental`, under the MCP Tasks extension\n * identifier. The ext-apps host capability type has no `tasks` field, so a client that\n * validates the handshake against the spec's schema strips a top-level `tasks`;\n * `experimental` is the one slot whose contents survive that parse (ext-apps\n * 1.7.5 and later). A top-level `tasks` is therefore not read at all — reading\n * it would make a capability visible here that no spec client can see.\n *\n * One key, and only that one: the identifier is the extension registry's, and a\n * host publishing the capability under any other name is not advertising this\n * extension.\n */\nexport function readHostTasksCapability(\n  capabilities: McpUiHostCapabilities | undefined,\n): TasksCapability | undefined {\n  const entry = capabilities?.experimental?.[TASKS_EXTENSION_ID];\n  return entry && typeof entry === \"object\" && !Array.isArray(entry)\n    ? (entry as TasksCapability)\n    : undefined;\n}\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 event-map.ts, where the core-MCP\n// method constants live).\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 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\n/** Subscribe to a wire method, and return the unsubscribe. */\ntype SubscribeFn = (\n  method: string,\n  handler: (params: Record<string, unknown> | undefined) => void,\n) => () => void;\n\nexport function createTaskStatusRouter(subscribe: SubscribeFn): TaskStatusRouter {\n  const listeners = new Map<string, Set<(update: TaskStatusUpdate) => void>>();\n\n  // A single subscription to the wire method. All per-handle listeners filter\n  // in-memory by taskId off this one handler.\n  const unsub = subscribe(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 * Rejects with `HostCapabilityError` if the host did not advertise\n * `tasks.requests.tools.call` — per spec a requestor MUST NOT task-augment\n * without matching receiver capability. Check `app.supportsTasks` first, and\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 HostCapabilityError(\n      \"callToolAsTask\",\n      `${TASKS_EXTENSION_ID} with requests.tools.call`,\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  // 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.\n  const callParams = {\n    name: toolName,\n    arguments: (args as Record<string, unknown> | undefined) ?? {},\n    task: taskParam,\n  } satisfies CallToolRequest[\"params\"];\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`: registering the\n  // same callback twice collapses to one wire subscription, and either\n  // returned unsub releases it. Without this, every `onStatus(cb)` would\n  // create a 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 { KEYDOWN_METHOD } from \"./event-map.js\";\nimport type { KeyForwardConfig } from \"./types.js\";\n\n/** Send a notification to the host. */\ntype SendFn = (method: string, params: Record<string, unknown>) => void;\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(send: SendFn, 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        send(KEYDOWN_METHOD, {\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","import { SIZE_CHANGED_METHOD } from \"@modelcontextprotocol/ext-apps\";\n\ntype 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(SIZE_CHANGED_METHOD, { width, height });\n  }\n\n  function resize(width?: number, height?: number): void {\n    if (destroyed) return;\n    if (width !== undefined && height !== undefined) {\n      send(SIZE_CHANGED_METHOD, { 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  AppEventMap,\n  AppNotification,\n  AppRequest,\n  McpUiHostCapabilities,\n  McpUiHostContext,\n  McpUiInitializeRequest,\n  McpUiMessageRequest,\n  McpUiOpenLinkRequest,\n  McpUiUpdateModelContextRequest,\n} from \"@modelcontextprotocol/ext-apps\";\nimport {\n  applyHostFonts,\n  App as ExtAppsApp,\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\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport type {\n  CallToolRequest,\n  ReadResourceRequest,\n  ReadResourceResult,\n  TextContent,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { CallToolResultSchema, ResultSchema } from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { parseToolResultParams } from \"./content-parser.js\";\nimport { extractHostFontCss, extractTheme } from \"./detection.js\";\nimport { HostCapabilityError } from \"./errors.js\";\nimport { NIMBLEBRAIN_EXTENSIONS, resolveEventMethod, TOOLS_CALL_METHOD } 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, readHostTasksCapability } from \"./task-handle.js\";\nimport { applyTheme } from \"./theme-defaults.js\";\nimport type {\n  App,\n  ConnectOptions,\n  Dimensions,\n  TasksCapability,\n  Theme,\n  ToolCallResult,\n} from \"./types.js\";\n\n/**\n * The host name that identifies a NimbleBrain host in the handshake. Identity\n * only: the NimbleBrain host extensions are gated on the host declaring each one.\n */\nconst NIMBLEBRAIN_HOST = \"nimblebrain\";\n\n/** The `_meta` key a `ui/message` text block carries the NimbleBrain chat context under. */\nconst CHAT_CONTEXT_META_KEY = \"ai.nimblebrain/context\";\n\n/**\n * Requests this SDK sends carry no deadline.\n *\n * The MCP SDK gives every request a 60-second one, which is wrong for all three\n * kinds of request an app makes: a file picker waits on a person, `tasks/result`\n * blocks until the task finishes, and a tool call takes as long as the tool\n * takes. A deadline here would reject a call the host is still working on, and\n * the app would report a failure that did not happen.\n *\n * `Infinity` is not usable — `setTimeout` coerces it to `0` and the timer fires\n * immediately — so this is the largest delay a browser timer accepts, about 24\n * days.\n */\nconst NO_DEADLINE: RequestOptions = { timeout: 2_147_483_647 };\n\n/**\n * The events `App` models, paired with the wire method each one carries.\n *\n * Every one is registered exactly once, before the handshake, and fans out to\n * this SDK's own subscribers underneath. Two reasons it has to be this way: a\n * second registration for the same method through the `on*` setters throws, and\n * `App` warns when a handler for a one-shot event (the tool ones) is registered\n * after `connect()` resolves, which is when every hook subscribes.\n */\nconst MAPPED_EVENTS = [\n  [\"toolinput\", TOOL_INPUT_METHOD],\n  [\"toolinputpartial\", TOOL_INPUT_PARTIAL_METHOD],\n  [\"toolresult\", TOOL_RESULT_METHOD],\n  [\"toolcancelled\", TOOL_CANCELLED_METHOD],\n] as const satisfies ReadonlyArray<readonly [keyof AppEventMap, string]>;\n\n/**\n * Connect to an MCP Apps host.\n *\n * The one entry point. The protocol underneath is the spec's own client,\n * `@modelcontextprotocol/ext-apps`'s `App`: it owns the transport, the\n * handshake and the wire schemas. What this adds is the framework on top —\n * theme injection, the parsed payloads, multi-subscriber events, resize, and\n * the NimbleBrain extensions — and it resolves to a ready {@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, forwardKeys } = options;\n\n  let destroyed = false;\n\n  // --- Mutable state ---\n  //\n  // The host context lives in `App`, which merges each delta into it, so it is\n  // read back rather than copied. `theme` is a derived view of it.\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 hostCapabilities: McpUiHostCapabilities = {};\n  let hostTasksCapability: TasksCapability | undefined;\n  let keyboard: KeyboardForwarder | null = null;\n\n  // The theme currently applied to the document. Tracked rather than derived at\n  // dispatch time, because `App` merges a host-context delta into the context it\n  // holds *before* it calls listeners — so by the time this SDK hears about a\n  // change, \"the theme before it\" is no longer recoverable from the context.\n  // Comparing against what is actually loaded is also the honest question: the\n  // filter exists to skip a re-render when nothing visible moved.\n  let appliedTheme: Theme = { mode: \"light\", tokens: {} };\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\n  // `autoResize` is handed to `App`, which observes the document and reports\n  // size after the handshake. Ours must not observe as well: two observers mean\n  // two `size-changed` streams for one document.\n  const client = new ExtAppsApp(\n    { name, version },\n    appCapabilities as unknown as McpUiInitializeRequest[\"params\"][\"appCapabilities\"],\n    { autoResize },\n  );\n\n  function currentContext(): McpUiHostContext {\n    return client.getHostContext() ?? {};\n  }\n\n  /**\n   * The theme as reported to consumers, derived from the context. Every public\n   * view goes through here — the `theme` getter, the `theme-changed` payload,\n   * and its equality filter — so they cannot disagree with each other or with\n   * what is actually applied.\n   */\n  function resolveTheme(): Theme {\n    return extractTheme(currentContext());\n  }\n\n  /**\n   * Load the host's `@font-face` CSS (`styles.css.fonts`) into the document.\n   *\n   * The spec's helper injects it once and leaves it in place, so a later\n   * host-context change that carries no `css` — a theme toggle, say — keeps the\n   * host's typeface loaded rather than unloading it.\n   */\n  function applyFontsFrom(ctx: Partial<McpUiHostContext> | undefined): void {\n    const css = extractHostFontCss(ctx);\n    if (css !== undefined && typeof document !== \"undefined\") applyHostFonts(css);\n  }\n\n  /** Apply the current theme to the document, and record what was applied. */\n  function applyResolvedTheme(): Theme {\n    const theme = resolveTheme();\n    applyTheme(theme.mode, theme.tokens);\n    appliedTheme = theme;\n    return theme;\n  }\n\n  // --- Event handlers ---\n  //\n  // Generic wire methods share one registry keyed by method. The two events\n  // that are a *view* over a wire message rather than the message itself\n  // (theme, host context) get their own sets, because they ride the same\n  // notification and hand their subscribers 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\n  /** Deliver a payload to everyone subscribed to a wire method. */\n  function fanOut(method: string, payload: unknown): void {\n    const set = handlers.get(method);\n    if (!set) return;\n    for (const handler of set) handler(payload);\n  }\n\n  /**\n   * Send a notification `App` does not model. The NimbleBrain host extensions have\n   * no spec equivalent and so no place in its notification union; the cast is\n   * the one place that is admitted, and the method still comes from a constant\n   * rather than a literal spelled at the call site.\n   */\n  function sendRaw(method: string, params?: Record<string, unknown>): void {\n    if (destroyed) return;\n    void client\n      .notification({ method, params } as unknown as AppNotification)\n      // A closed transport is the ordinary way this rejects, during teardown.\n      .catch(() => {});\n  }\n\n  /** Send a request `App` does not model, and resolve with the host's result. */\n  function requestRaw(method: string, params?: Record<string, unknown>): Promise<unknown> {\n    return client.request({ method, params } as unknown as AppRequest, ResultSchema, NO_DEADLINE);\n  }\n\n  // --- Route what the host sends ---\n  //\n  // Registered before `connect()`, so a notification the host sends the instant\n  // the handshake completes is already routed.\n\n  for (const [event, method] of MAPPED_EVENTS) {\n    client.addEventListener(event, (params) => {\n      if (destroyed) return;\n      // `tool-result` is delivered parsed — the payload every subscriber gets,\n      // however they subscribed — because the wire shape is three shapes and\n      // picking between them is work each app would otherwise repeat.\n      fanOut(\n        method,\n        method === TOOL_RESULT_METHOD\n          ? parseToolResultParams(params as Record<string, unknown>)\n          : params,\n      );\n    });\n  }\n\n  client.addEventListener(\"hostcontextchanged\", (params) => {\n    if (destroyed) return;\n    const prevTheme = appliedTheme;\n\n    // `App` has already merged this delta into the context it holds — shallowly,\n    // which is what the spec asks for: `styles.variables` is a complete map when\n    // the host sends one, so a deep merge would leave a host no way to remove a\n    // variable. Fonts are read from the delta as sent, because a merged\n    // context loses `styles.css` whenever the host sends `styles.variables`\n    // alone.\n    applyFontsFrom(params as Partial<McpUiHostContext>);\n    const nextTheme = applyResolvedTheme();\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 as\n    // sent subscribes to the wire method instead, which is passed through\n    // untouched.\n    const merged = currentContext();\n    for (const cb of hostContextCallbacks) cb(merged);\n    fanOut(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  // Teardown is a *request* in the spec, not a notification: the host asks, and\n  // the view is expected to answer. Subscribers see it as the `teardown` event;\n  // answering it is this SDK's job, not theirs.\n  client.onteardown = (params) => {\n    if (!destroyed) fanOut(RESOURCE_TEARDOWN_METHOD, params);\n    return {};\n  };\n\n  // Everything else the host sends: vendor extension notifications, the server's\n  // `notifications/resources/list_changed`, and `notifications/tasks/status`.\n  // `App` routes a notification here when no typed handler claims its method,\n  // and one handler with a fan-out under it is the only safe shape —\n  // registering a second handler for a method would silently replace the first.\n  client.fallbackNotificationHandler = async (notification) => {\n    if (destroyed) return;\n    fanOut(notification.method, notification.params);\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      default: {\n        const method = resolveEventMethod(event);\n        if (!handlers.has(method)) handlers.set(method, new Set());\n        handlers.get(method)?.add(handler);\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  // Handlers from `options.on` are registered before the handshake goes out, so\n  // a tool result the host sends in the same turn as `initialized` is not lost.\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\n  // --- The handshake: `ui/initialize`, then `initialized` ---\n  await client.connect();\n\n  const hostVersion = client.getHostVersion();\n  hostInfo = {\n    name: hostVersion?.name ?? \"unknown\",\n    version: hostVersion?.version ?? \"unknown\",\n  };\n  isNimbleBrainHost = hostInfo.name === NIMBLEBRAIN_HOST;\n\n  // Everything an app may ask of the host is decided here, once: each method\n  // below and each helper beside `App` checks the declaration before sending.\n  hostCapabilities = client.getHostCapabilities() ?? {};\n  hostTasksCapability = readHostTasksCapability(hostCapabilities);\n\n  const initialContext = client.getHostContext();\n  if (initialContext) {\n    if (initialContext.toolInfo && typeof initialContext.toolInfo === \"object\") {\n      toolInfo = {\n        tool: (initialContext.toolInfo.tool as unknown as Record<string, unknown>) ?? {},\n      };\n    }\n    if (\n      initialContext.containerDimensions &&\n      typeof initialContext.containerDimensions === \"object\"\n    ) {\n      containerDimensions = initialContext.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 any\n    // var nobody declares and lose to every var that is declared. The host's\n    // `@font-face` CSS loads alongside — a token names a family, it cannot load\n    // one.\n    applyFontsFrom(initialContext);\n    applyResolvedTheme();\n  }\n\n  // Keyboard forwarding is a NimbleBrain extension. Forwarding to a host that\n  // did not declare it would `preventDefault` a key for a host that does\n  // nothing with it, so the gate is on the declaration, not just the option.\n  if (\n    forwardKeys &&\n    hostCapabilities.experimental?.[NIMBLEBRAIN_EXTENSIONS.keydown.capability] !== undefined\n  ) {\n    keyboard = new KeyboardForwarder(sendRaw, forwardKeys === true ? undefined : forwardKeys);\n  }\n\n  // The resizer serves `app.resize()`. It never observes: under `autoResize`\n  // that is `App`'s job, and it has already reported the first size.\n  const resizer = createResizer(sendRaw, false);\n  if (!autoResize) resizer.measureAndSend();\n\n  // Shared router for `notifications/tasks/status`. Created eagerly so the\n  // subscription registers exactly once — every `TaskHandle` filters off this\n  // single wire subscription by taskId.\n  const taskRouter = createTaskStatusRouter((method, handler) =>\n    subscribe(method, handler as (params: any) => void),\n  );\n\n  // --- The App this SDK hands out ---\n  const app: App = {\n    get theme() {\n      return resolveTheme();\n    },\n    get hostInfo() {\n      return { ...hostInfo };\n    },\n    get hostContext() {\n      return currentContext();\n    },\n    get hostCapabilities() {\n      return hostCapabilities;\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      if (!hostCapabilities.openLinks) {\n        window.open(url, \"_blank\", \"noopener\");\n        return;\n      }\n      const params: McpUiOpenLinkRequest[\"params\"] = { url };\n      client.openLink(params, NO_DEADLINE).catch(() => {\n        // The host refused or does not serve it: open directly instead.\n        window.open(url, \"_blank\", \"noopener\");\n      });\n    },\n\n    updateModelContext(state: Record<string, unknown>, summary?: string): void {\n      if (destroyed || !hostCapabilities.updateModelContext) return;\n      const params: McpUiUpdateModelContextRequest[\"params\"] = {\n        structuredContent: state,\n        ...(summary !== undefined && {\n          content: [{ type: \"text\", text: summary } satisfies TextContent],\n        }),\n      };\n      client.updateModelContext(params, NO_DEADLINE).catch(() => {});\n    },\n\n    async callTool<TOutput = unknown>(\n      toolName: string,\n      args?: Record<string, unknown>,\n    ): Promise<ToolCallResult<TOutput>> {\n      if (!hostCapabilities.serverTools) {\n        throw new HostCapabilityError(\"callTool\", \"serverTools\");\n      }\n      // No target. A host scopes an app's call to the server that mounted it,\n      // so `params` carries what the spec names and nothing else.\n      const params: CallToolRequest[\"params\"] = {\n        name: toolName,\n        arguments: args ?? {},\n      };\n      // Sent through the generic request path rather than `callServerTool`,\n      // which asks for a progress token: that puts `_meta.progressToken` on\n      // every call, and nothing here subscribes to progress. The result is\n      // validated against the spec's schema either way.\n      const raw = await client.request(\n        { method: TOOLS_CALL_METHOD, params },\n        CallToolResultSchema,\n        NO_DEADLINE,\n      );\n      return parseToolResult(raw) as ToolCallResult<TOutput>;\n    },\n\n    async readServerResource(params: ReadResourceRequest[\"params\"]): Promise<ReadResourceResult> {\n      if (!hostCapabilities.serverResources) {\n        throw new HostCapabilityError(\"readServerResource\", \"serverResources\");\n      }\n      return await client.readServerResource(params, NO_DEADLINE);\n    },\n\n    sendMessage(text: string, context?: { action?: string; entity?: string }): void {\n      if (destroyed || !hostCapabilities.message) return;\n      const textBlock: TextContent = {\n        type: \"text\",\n        text,\n        // The chat context is a NimbleBrain host field; other hosts ignore it,\n        // but there is no reason to spend the bytes off one.\n        ...(isNimbleBrainHost && context && { _meta: { [CHAT_CONTEXT_META_KEY]: context } }),\n      };\n      const params: McpUiMessageRequest[\"params\"] = {\n        role: \"user\",\n        content: [textBlock],\n      };\n      client.sendMessage(params, NO_DEADLINE).catch(() => {});\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      void client.close();\n    },\n  };\n\n  registerInternals(app, {\n    send(method, params) {\n      sendRaw(method, params);\n    },\n    request(method, params) {\n      return requestRaw(method, params);\n    },\n    onMessage(method, handler) {\n      return subscribe(method, handler as (params: any) => void);\n    },\n    taskRouter,\n    get hostTasksCapability() {\n      return hostTasksCapability;\n    },\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.\n */\nfunction themesEqual(a: Theme, b: Theme): boolean {\n  if (a.mode !== b.mode) 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 are the NimbleBrain host's own\n * `ai.nimblebrain/*` methods, which this package implements a client for, and\n * `NIMBLEBRAIN_EXTENSIONS` in `event-map.ts` is the complete list. They\n * live here rather than on the `App` object so the object stays the spec\n * surface plus the handshake state, and so an app that never picks a file\n * never pulls this code in.\n *\n * Every one of them is gated on the host declaring it in `ui/initialize`: where\n * it is not declared, the fire-and-forget ones are no-ops and the ones with a\n * return value throw `HostCapabilityError`, because a picker that silently\n * resolves `null` forever is worse than one that says it isn't there.\n * `keydown` has no function here; `connect({ forwardKeys })` applies the same\n * gate.\n */\nimport { HostCapabilityError } from \"./errors.js\";\nimport { NIMBLEBRAIN_EXTENSIONS, type NimbleBrainExtension } from \"./event-map.js\";\nimport { internalsFor } from \"./internals.js\";\nimport type { App, FileResult, RequestFileOptions } from \"./types.js\";\n\n/**\n * Whether the host declared a NimbleBrain extension. Use it to decide what to\n * offer, e.g. to hide an upload button on a host with no file picker.\n */\nexport function hostSupports(app: App, extension: NimbleBrainExtension): boolean {\n  const { capability } = NIMBLEBRAIN_EXTENSIONS[extension];\n  return app.hostCapabilities.experimental?.[capability] !== undefined;\n}\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 * Sends a command *to* the host (navigate, open a panel). A no-op when the host\n * did not declare `ai.nimblebrain/action`.\n */\nexport function action(app: App, name: string, params?: Record<string, unknown>): void {\n  if (!hostSupports(app, \"action\")) return;\n  internalsFor(app).send(NIMBLEBRAIN_EXTENSIONS.action.method, { action: name, ...params });\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. Rejects with `HostCapabilityError` when\n * the host did not declare `ai.nimblebrain/request-file`.\n */\nexport async function pickFile(app: App, options?: RequestFileOptions): Promise<FileResult | null> {\n  requireRequestFile(\"pickFile\", app);\n  const files = await requestFile(app, options, false);\n  // One pick, so the first entry is the answer; an empty list is a cancel.\n  return files[0] ?? null;\n}\n\n/**\n * Request several files from the user.\n *\n * Resolves `[]` if the user cancels. Rejects with `HostCapabilityError` when\n * the host did not declare `ai.nimblebrain/request-file`.\n */\nexport async function pickFiles(app: App, options?: RequestFileOptions): Promise<FileResult[]> {\n  requireRequestFile(\"pickFiles\", app);\n  return await requestFile(app, options, true);\n}\n\nfunction requireRequestFile(feature: string, app: App): void {\n  if (!hostSupports(app, \"requestFile\")) {\n    throw new HostCapabilityError(feature, NIMBLEBRAIN_EXTENSIONS.requestFile.capability);\n  }\n}\n\n/**\n * Shared request path for `pickFile` / `pickFiles`.\n *\n * The host answers with `{ files }` — an empty array when the user cancelled.\n * A JSON-RPC result is an object by definition, and MCP types it as one, so the\n * files travel under a field rather than as a bare array or a bare `null`: a\n * spec client refuses to parse anything else, and the call would hang rather\n * than resolve.\n *\n * Entries are shape-checked here. The type promises a string `id`, and without\n * the guard a consumer reads `undefined.id` three frames later, where nothing\n * says which side is mismatched.\n */\nasync function requestFile(\n  app: App,\n  options: RequestFileOptions | undefined,\n  multiple: boolean,\n): Promise<FileResult[]> {\n  const result = await internalsFor(app).request(NIMBLEBRAIN_EXTENSIONS.requestFile.method, {\n    accept: options?.accept,\n    maxSize: options?.maxSize ?? DEFAULT_MAX_FILE_SIZE,\n    multiple,\n  });\n  const files = (result as { files?: unknown } | null | undefined)?.files;\n  if (files === undefined) {\n    throw new Error(\n      \"ai.nimblebrain/request-file returned no `files`. The host is older than this \" +\n        \"SDK targets: it answers the picker with a bare array or `null`, which \" +\n        \"a spec-compliant client cannot parse.\",\n    );\n  }\n  if (!Array.isArray(files)) {\n    throw new Error(\"ai.nimblebrain/request-file returned a `files` field that is not an array.\");\n  }\n  return files.map(validateFileResult);\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      \"ai.nimblebrain/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"]}