@nimblebrain/synapse 0.18.0 → 0.20.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.
Files changed (69) hide show
  1. package/README.md +32 -37
  2. package/dist/check-JEM5PN64.cjs +435 -0
  3. package/dist/check-JEM5PN64.cjs.map +1 -0
  4. package/dist/check-YDZUQT6A.js +429 -0
  5. package/dist/check-YDZUQT6A.js.map +1 -0
  6. package/dist/{chunk-VDQZQDU3.cjs → chunk-BNF352SA.cjs} +56 -145
  7. package/dist/chunk-BNF352SA.cjs.map +1 -0
  8. package/dist/{chunk-HKRTDGXN.js → chunk-DJS2FKBN.js} +21 -89
  9. package/dist/chunk-DJS2FKBN.js.map +1 -0
  10. package/dist/chunk-H3INUKA3.js +32 -0
  11. package/dist/chunk-H3INUKA3.js.map +1 -0
  12. package/dist/{chunk-FB7GPBEM.cjs → chunk-HQLSVUOR.cjs} +193 -314
  13. package/dist/chunk-HQLSVUOR.cjs.map +1 -0
  14. package/dist/chunk-ISV6HFQE.cjs +40 -0
  15. package/dist/chunk-ISV6HFQE.cjs.map +1 -0
  16. package/dist/{chunk-3YSXPBEQ.js → chunk-TR2YNWZ5.js} +190 -313
  17. package/dist/chunk-TR2YNWZ5.js.map +1 -0
  18. package/dist/{chunk-ZLASWV4N.js → chunk-UKP4W6DI.js} +56 -145
  19. package/dist/chunk-UKP4W6DI.js.map +1 -0
  20. package/dist/{chunk-LPWEQCZV.cjs → chunk-YSL7KJNU.cjs} +21 -92
  21. package/dist/chunk-YSL7KJNU.cjs.map +1 -0
  22. package/dist/codegen/cli.cjs +38 -1
  23. package/dist/codegen/cli.cjs.map +1 -1
  24. package/dist/codegen/cli.js +38 -1
  25. package/dist/codegen/cli.js.map +1 -1
  26. package/dist/codegen/index.d.cts +1 -1
  27. package/dist/codegen/index.d.ts +1 -1
  28. package/dist/connect.iife.global.js +66 -43
  29. package/dist/{detect-BHYg26_d.d.cts → detect-DVGaL2bH.d.cts} +39 -33
  30. package/dist/{detect-Bf8Q_0dK.d.ts → detect-DVGaL2bH.d.ts} +39 -33
  31. package/dist/host/index.cjs +17 -17
  32. package/dist/host/index.d.cts +11 -27
  33. package/dist/host/index.d.ts +11 -27
  34. package/dist/host/index.js +2 -2
  35. package/dist/index.cjs +52 -17
  36. package/dist/index.cjs.map +1 -1
  37. package/dist/index.d.cts +104 -31
  38. package/dist/index.d.ts +104 -31
  39. package/dist/index.js +34 -3
  40. package/dist/index.js.map +1 -1
  41. package/dist/react/index.cjs +11 -10
  42. package/dist/react/index.cjs.map +1 -1
  43. package/dist/react/index.d.cts +49 -12
  44. package/dist/react/index.d.ts +49 -12
  45. package/dist/react/index.js +6 -5
  46. package/dist/react/index.js.map +1 -1
  47. package/dist/{server-QIYIJHD5.cjs → server-BR5MNFOB.cjs} +40 -29
  48. package/dist/server-BR5MNFOB.cjs.map +1 -0
  49. package/dist/{server-5N76YCWC.js → server-OOEEWAEG.js} +40 -30
  50. package/dist/server-OOEEWAEG.js.map +1 -0
  51. package/dist/synapse-runtime.iife.global.js +66 -43
  52. package/dist/synapse-ui.iife.global.js +4 -4
  53. package/dist/{types-uEO4VFJ2.d.cts → types-BxPfGHKO.d.cts} +48 -125
  54. package/dist/{types-uEO4VFJ2.d.ts → types-BxPfGHKO.d.ts} +48 -125
  55. package/dist/vite/index.cjs +77 -33
  56. package/dist/vite/index.cjs.map +1 -1
  57. package/dist/vite/index.d.cts +5 -1
  58. package/dist/vite/index.d.ts +5 -1
  59. package/dist/vite/index.js +77 -33
  60. package/dist/vite/index.js.map +1 -1
  61. package/package.json +12 -6
  62. package/dist/chunk-3YSXPBEQ.js.map +0 -1
  63. package/dist/chunk-FB7GPBEM.cjs.map +0 -1
  64. package/dist/chunk-HKRTDGXN.js.map +0 -1
  65. package/dist/chunk-LPWEQCZV.cjs.map +0 -1
  66. package/dist/chunk-VDQZQDU3.cjs.map +0 -1
  67. package/dist/chunk-ZLASWV4N.js.map +0 -1
  68. package/dist/server-5N76YCWC.js.map +0 -1
  69. package/dist/server-QIYIJHD5.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/app-provider.tsx","../../src/react/hooks.ts"],"names":["createContext","useState","useRef","useEffect","connect","useContext","useCallback","action","pickFile","pickFiles","isTerminal","callToolAsTask"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createContext, type ReactNode, useContext, useEffect, useRef, useState } from \"react\";\nimport { connect } from \"../connect.js\";\nimport type { App, ConnectOptions } from \"../types.js\";\n\nconst AppContext = createContext<App | null>(null);\n\nexport interface AppProviderProps extends ConnectOptions {\n children: ReactNode;\n}\n\n/**\n * Connect on mount and provide the {@link App} to everything below.\n *\n * Renders nothing until the handshake completes, so no hook below can observe\n * a half-connected app and no tool call can be fired into a host that has not\n * answered `ui/initialize` yet.\n */\nexport function AppProvider({ children, ...options }: AppProviderProps) {\n const [app, setApp] = useState<App | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const connectingRef = useRef(false);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: connect once on mount\n useEffect(() => {\n // A ref, not cleanup-on-unmount: StrictMode unmounts and immediately\n // remounts, and the transport must survive that. The app is GC'd when the\n // provider is truly gone.\n if (connectingRef.current) return;\n connectingRef.current = true;\n\n connect(options).then(setApp, (err: unknown) => {\n setError(err instanceof Error ? err : new Error(String(err)));\n });\n }, []);\n\n // A host that answers `ui/initialize` with an error is a failure the app\n // cannot proceed through, and rendering nothing forever is the worst way to\n // report it: a blank pane and an unhandled rejection in a console nobody has\n // open. Re-throwing during render makes it an ordinary React error, so it\n // reaches the nearest error boundary and is loud in development.\n if (error) throw error;\n\n // Still connecting. Nothing below can observe a half-connected app, and no\n // hook can fire a call into a host that has not answered yet.\n if (!app) return null;\n\n return <AppContext.Provider value={app}>{children}</AppContext.Provider>;\n}\n\nexport function useAppContext(): App {\n const ctx = useContext(AppContext);\n if (!ctx) {\n throw new Error(\n \"useApp must be used within an <AppProvider>. Wrap your component tree with <AppProvider>.\",\n );\n }\n return ctx;\n}\n","import type { McpUiHostContext } from \"@modelcontextprotocol/ext-apps\";\nimport type { Task, TaskStatus } from \"@modelcontextprotocol/sdk/types.js\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { pickFile, pickFiles, action as sendAction } from \"../extensions.js\";\nimport { callToolAsTask } from \"../task-handle.js\";\nimport type {\n App,\n CallToolAsTaskOptions,\n CallToolOptions,\n DataChangedEvent,\n FileResult,\n ModelContext,\n RequestFileOptions,\n TaskHandle,\n Theme,\n ToolCallResult,\n ToolResultData,\n} from \"../types.js\";\nimport { useAppContext } from \"./app-provider.js\";\n\n/** The connected app. Throws outside an `<AppProvider>`. */\nexport function useApp(): App {\n return useAppContext();\n}\n\n// -----------------------------------------------------------------------------\n// Host state\n// -----------------------------------------------------------------------------\n\n/**\n * The current theme, re-rendering only when it actually moves.\n *\n * `App` filters `host-context-changed` notifications through a theme equality\n * check, so a context update that leaves the derived theme untouched (a\n * workspace switch, say) does not re-render every themed component.\n */\nexport function useTheme(): Theme {\n const app = useAppContext();\n const [theme, setTheme] = useState<Theme>(() => app.theme);\n\n useEffect(() => {\n // Sync in case the theme changed between render and effect.\n setTheme(app.theme);\n return app.on(\"theme-changed\", setTheme);\n }, [app]);\n\n return theme;\n}\n\n/**\n * The full ext-apps host context — spec fields (`theme`, `styles`,\n * `displayMode`, `toolInfo`) plus whatever the host publishes alongside.\n * Re-renders on every `host-context-changed`.\n *\n * Prefer `useTheme()` when only theming matters: it filters no-op fires.\n * Reach for this one for host extensions, e.g. on NimbleBrain:\n *\n * ```tsx\n * const { workspace } = useHostContext<{ workspace?: { id: string } }>();\n * ```\n */\nexport function useHostContext<T extends McpUiHostContext = McpUiHostContext>(): T {\n const app = useAppContext();\n const [ctx, setCtx] = useState<T>(() => app.hostContext as T);\n\n useEffect(() => {\n setCtx(app.hostContext as T);\n return app.on(\"host-context-changed\", (c) => setCtx(c as T));\n }, [app]);\n\n return ctx;\n}\n\n/** The latest tool result pushed by the host, or `null` before one arrives. */\nexport function useToolResult(): ToolResultData | null {\n const app = useAppContext();\n const [data, setData] = useState<ToolResultData | null>(null);\n\n useEffect(() => {\n return app.on(\"tool-result\", setData);\n }, [app]);\n\n return data;\n}\n\n/** The arguments the host is calling the bound tool with, as they arrive. */\nexport function useToolInput(): Record<string, unknown> | null {\n const app = useAppContext();\n const [input, setInput] = useState<Record<string, unknown> | null>(null);\n\n useEffect(() => {\n return app.on(\"tool-input\", setInput);\n }, [app]);\n\n return input;\n}\n\n/** Ask the host to resize this app's frame. */\nexport function useResize(): (width?: number, height?: number) => void {\n const app = useAppContext();\n return useCallback((width?: number, height?: number) => app.resize(width, height), [app]);\n}\n\n// -----------------------------------------------------------------------------\n// Tools\n// -----------------------------------------------------------------------------\n\nexport interface UseCallToolResult<TOutput> {\n call: (\n args?: Record<string, unknown>,\n options?: CallToolOptions,\n ) => Promise<ToolCallResult<TOutput>>;\n isPending: boolean;\n error: Error | null;\n data: TOutput | null;\n}\n\n/** Call one tool, with pending/error/data state for the latest call. */\nexport function useCallTool<TOutput = unknown>(toolName: string): UseCallToolResult<TOutput> {\n const app = useAppContext();\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<TOutput | null>(null);\n const callIdRef = useRef(0);\n\n const call = useCallback(\n async (\n args?: Record<string, unknown>,\n options?: CallToolOptions,\n ): Promise<ToolCallResult<TOutput>> => {\n const id = ++callIdRef.current;\n setIsPending(true);\n setError(null);\n\n try {\n const result = await app.callTool<TOutput>(toolName, args, options);\n // Stale guard: only update if this is still the latest call.\n if (id === callIdRef.current) {\n setData(result.data);\n setIsPending(false);\n }\n return result;\n } catch (err) {\n if (id === callIdRef.current) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n setIsPending(false);\n }\n throw err;\n }\n },\n [app, toolName],\n );\n\n return { call, isPending, error, data };\n}\n\n/** Run `callback` whenever the agent changes data this app displays. */\nexport function useDataSync(callback: (event: DataChangedEvent) => void): void {\n const app = useAppContext();\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n return app.on(\"data-changed\", (event) => callbackRef.current(event));\n }, [app]);\n}\n\n// -----------------------------------------------------------------------------\n// Agent-facing state\n// -----------------------------------------------------------------------------\n\n/** Debounce window for `useModelContext`, in milliseconds. */\nconst MODEL_CONTEXT_DEBOUNCE_MS = 250;\n\n/**\n * Push what the user is looking at to the agent (ext-apps\n * `ui/update-model-context`), debounced so a selection the user drags through\n * costs one frame rather than thirty.\n *\n * **Declarative** — pushes when `deps` change:\n * ```tsx\n * useModelContext(() => ({\n * state: { board: selectedBoard },\n * summary: `Viewing \"${selectedBoard?.name}\"`,\n * }), [selectedBoard]);\n * ```\n *\n * **Imperative** — returns a push function:\n * ```tsx\n * const push = useModelContext();\n * push({ board: selectedBoard }, \"Viewing board X\");\n * ```\n *\n * The debounce lives here rather than on `app.updateModelContext`, which\n * sends immediately: the rapid-change problem is a React one, and the plain\n * method should do what it says.\n */\nexport function useModelContext(): (state: Record<string, unknown>, summary?: string) => void;\nexport function useModelContext(factory: () => ModelContext, deps: unknown[]): void;\nexport function useModelContext(\n factory?: () => ModelContext,\n deps?: unknown[],\n): ((state: Record<string, unknown>, summary?: string) => void) | undefined {\n const app = useAppContext();\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const push = useCallback(\n (state: Record<string, unknown>, summary?: string) => {\n if (timerRef.current) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n app.updateModelContext(state, summary);\n }, MODEL_CONTEXT_DEBOUNCE_MS);\n },\n [app],\n );\n\n useEffect(() => {\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n };\n }, []);\n\n // Declarative mode: push when deps change. The deps array is\n // caller-provided (mirrors useMemo/useEffect).\n const factoryRef = useRef(factory);\n factoryRef.current = factory;\n useEffect(() => {\n if (!factoryRef.current) return;\n const { state, summary } = factoryRef.current();\n push(state, summary);\n }, [...(deps ?? []), push]);\n\n if (!factory) return push;\n}\n\n/** Send a user message into the agent conversation. */\nexport function useSendMessage(): (\n text: string,\n context?: { action?: string; entity?: string },\n) => void {\n const app = useAppContext();\n return useCallback(\n (text: string, context?: { action?: string; entity?: string }) =>\n app.sendMessage(text, context),\n [app],\n );\n}\n\n// -----------------------------------------------------------------------------\n// NimbleBrain host extensions\n// -----------------------------------------------------------------------------\n\n/** Trigger a host-side action. No-op off a NimbleBrain host. */\nexport function useAction(): (name: string, params?: Record<string, unknown>) => void {\n const app = useAppContext();\n return useCallback(\n (name: string, params?: Record<string, unknown>) => sendAction(app, name, params),\n [app],\n );\n}\n\nexport interface UseFileUploadResult {\n pickFile: (options?: RequestFileOptions) => Promise<FileResult | null>;\n pickFiles: (options?: RequestFileOptions) => Promise<FileResult[]>;\n isPending: boolean;\n}\n\n/** The host's native file picker, with a pending flag. NimbleBrain only. */\nexport function useFileUpload(): UseFileUploadResult {\n const app = useAppContext();\n const [isPending, setIsPending] = useState(false);\n\n const one = useCallback(\n async (options?: RequestFileOptions) => {\n setIsPending(true);\n try {\n return await pickFile(app, options);\n } finally {\n setIsPending(false);\n }\n },\n [app],\n );\n\n const many = useCallback(\n async (options?: RequestFileOptions) => {\n setIsPending(true);\n try {\n return await pickFiles(app, options);\n } finally {\n setIsPending(false);\n }\n },\n [app],\n );\n\n return { pickFile: one, pickFiles: many, isPending };\n}\n\n// -----------------------------------------------------------------------------\n// useCallToolAsTask — lifecycle wrapper around `callToolAsTask(app, …)`\n// -----------------------------------------------------------------------------\n\n/**\n * Spec terminal status values for the MCP 2025-11-25 tasks utility.\n *\n * Typed via `satisfies TaskStatus` so a rename of any member of the\n * spec enum (`completed`/`failed`/`cancelled`) trips `tsc` — we never\n * hand-type these as bare string literals in comparisons.\n */\nconst COMPLETED_STATUS = \"completed\" satisfies TaskStatus;\nconst FAILED_STATUS = \"failed\" satisfies TaskStatus;\nconst CANCELLED_STATUS = \"cancelled\" satisfies TaskStatus;\n\nconst TERMINAL_STATUSES: ReadonlySet<TaskStatus> = new Set<TaskStatus>([\n COMPLETED_STATUS,\n FAILED_STATUS,\n CANCELLED_STATUS,\n]);\n\n/**\n * Fallback poll cadence used when the receiver's `CreateTaskResult.task`\n * carries no `pollInterval`. The effective fire delay is this value × 1.5\n * ≈ 7.5s, well below default TTLs but long enough to avoid hammering hosts\n * that do emit `notifications/tasks/status`.\n */\nconst DEFAULT_POLL_INTERVAL_MS = 5_000;\nconst POLL_FALLBACK_MULTIPLIER = 1.5;\n\n/**\n * Stop the poll fallback after this many consecutive `refresh()` failures.\n * Bridge teardown / TTL eviction / network outage all manifest as repeated\n * `tasks/get` rejections. Without a guard the timer re-arms forever; with\n * it we stop polling silently after `MAX_REFRESH_FAILURES` strikes — the\n * blocking `result()` path remains the authoritative source of truth, so\n * giving up on polling never loses the terminal value.\n */\nconst MAX_REFRESH_FAILURES = 5;\n\nexport interface UseCallToolAsTaskResult<TInput, TOutput> {\n /**\n * Start (or re-start) a task-augmented tool call. Returns the\n * resolved `TaskHandle` so callers can `await fire(...)` if they\n * want to know when the server has accepted the task, but reading\n * `task`/`result`/`error` from the hook is usually enough.\n *\n * Re-firing while a previous task is still in flight detaches this\n * hook from the prior handle (stops polling, unsubscribes) but does\n * NOT cancel the server-side task — the task keeps running and its\n * result may still be fetched elsewhere (e.g. on page revisit).\n */\n fire(args?: TInput, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>>;\n /** Latest `Task` state, or `null` before `fire()` has been called. */\n task: Task | null;\n /** Populated once `handle.result()` resolves non-error. */\n result: ToolCallResult<TOutput> | null;\n /** Populated on rejection or when `result.isError === true`. */\n error: Error | null;\n /** `true` while the task is non-terminal (`working` / `input_required`). */\n isWorking: boolean;\n /** `true` when `task.status ∈ {completed, failed, cancelled}`. */\n isTerminal: boolean;\n /**\n * Cancel the active task via `tasks/cancel`. No-op when no task is\n * active. Swallowed errors surface via `error`.\n */\n cancel(): Promise<void>;\n}\n\n/**\n * React wrapper around `callToolAsTask(app, …)`.\n *\n * Handles the full MCP 2025-11-25 task lifecycle:\n *\n * 1. `fire(args, options?)` sends the task-augmented `tools/call` and\n * stores the returned `TaskHandle` in a ref.\n * 2. Subscribes to `handle.onStatus` — updates `task` whenever the\n * host emits `notifications/tasks/status` (OPTIONAL per spec).\n * 3. Starts a polling fallback: if no status notification arrives\n * within `pollInterval × 1.5` (defaulting to ~7.5s), calls\n * `handle.refresh()` for canonical state. Stops on terminal.\n * 4. Awaits `handle.result()` in the background — resolves to either\n * `result` (success / `isError: false`) or `error` (network reject\n * OR `result.isError === true`).\n *\n * Cleanup (unmount or re-fire) unsubscribes from status events and\n * clears the poll timer, but does NOT cancel the server-side task —\n * the caller may remount and recover state by firing again, and tasks\n * outlive iframe teardown until TTL elapses.\n */\nexport function useCallToolAsTask<TInput = Record<string, unknown>, TOutput = unknown>(\n toolName: string,\n): UseCallToolAsTaskResult<TInput, TOutput> {\n const app = useAppContext();\n\n const [task, setTask] = useState<Task | null>(null);\n const [result, setResult] = useState<ToolCallResult<TOutput> | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n // Per-fire generation counter. Every `fire()` increments; any\n // asynchronous callback (status listener, poll timer, `result()`\n // resolution) captures the gen at schedule time and bails if the\n // current gen has moved past it. This is the single source of truth\n // for \"is this work still relevant?\" — more robust than comparing\n // TaskHandle identity because handles can be detached by re-fire.\n const genRef = useRef(0);\n\n // Active handle + its teardown handles. We keep both in refs so the\n // hook's stable `fire`/`cancel` callbacks can reach the current\n // lifecycle state without re-binding on every render.\n const handleRef = useRef<TaskHandle<TOutput> | null>(null);\n const unsubscribeRef = useRef<(() => void) | null>(null);\n const pollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // `pollInterval × 1.5`, captured per-fire. Falls back to the 5s\n // default when the host didn't provide a `pollInterval` in the\n // initial CreateTaskResult.task.\n const pollDelayRef = useRef<number>(DEFAULT_POLL_INTERVAL_MS * POLL_FALLBACK_MULTIPLIER);\n\n // Track the latest known status out-of-band so the poll callback\n // can decide whether to keep polling without depending on the\n // `task` React state (which lags a render behind setState).\n const terminalRef = useRef<boolean>(false);\n\n // Consecutive `refresh()` failure count for the active fire. Reset\n // on every successful refresh, status notification, or new fire.\n const refreshFailureCountRef = useRef<number>(0);\n\n const clearPollTimer = useCallback(() => {\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n }, []);\n\n const detachCurrent = useCallback(() => {\n clearPollTimer();\n if (unsubscribeRef.current) {\n unsubscribeRef.current();\n unsubscribeRef.current = null;\n }\n handleRef.current = null;\n }, [clearPollTimer]);\n\n const scheduleNextPoll = useCallback(\n (gen: number) => {\n clearPollTimer();\n if (terminalRef.current) return;\n pollTimerRef.current = setTimeout(() => {\n // Bail if this fire has been superseded or torn down.\n if (gen !== genRef.current) return;\n const h = handleRef.current;\n if (!h) return;\n if (terminalRef.current) return;\n // `refresh()` is the canonical source for `createdAt` /\n // `lastUpdatedAt` / `ttl` — notification-derived Tasks carry\n // placeholders per the router in `task-handle.ts`.\n h.refresh().then(\n (fresh) => {\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current = 0;\n setTask(fresh);\n const isTerminal = TERMINAL_STATUSES.has(fresh.status);\n terminalRef.current = isTerminal;\n if (!isTerminal) scheduleNextPoll(gen);\n },\n () => {\n // Swallow refresh errors — the blocking `tasks/result` is\n // the authoritative path; polling is best-effort. But guard\n // against runaway re-arming: if the bridge is gone or the\n // task TTL has elapsed, every refresh rejects. Stop after\n // MAX_REFRESH_FAILURES consecutive strikes; result() will\n // still surface a terminal value or error when it settles.\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current += 1;\n if (refreshFailureCountRef.current >= MAX_REFRESH_FAILURES) return;\n if (!terminalRef.current) scheduleNextPoll(gen);\n },\n );\n }, pollDelayRef.current);\n },\n [clearPollTimer],\n );\n\n const fire = useCallback(\n async (args?: TInput, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>> => {\n // Detach any in-flight prior task BEFORE incrementing the gen so\n // its callbacks see the new gen and bail. (Incrementing then\n // detaching would also work, but detach-first makes the order\n // obvious: stop listening, bump generation, start fresh.)\n detachCurrent();\n const gen = ++genRef.current;\n\n // Reset per-fire state. Don't wipe `task` yet — `callToolAsTask`\n // is async; showing the previous terminal state briefly is less\n // jarring than flicker to null → working. We clear on resolution.\n setResult(null);\n setError(null);\n terminalRef.current = false;\n refreshFailureCountRef.current = 0;\n\n let handle: TaskHandle<TOutput>;\n try {\n handle = await callToolAsTask<TOutput>(app, toolName, args, options);\n } catch (err) {\n if (gen !== genRef.current) throw err;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw err;\n }\n\n // Caller superseded the fire between request and response —\n // don't attach listeners, but still return the handle so the\n // awaiter can observe it.\n if (gen !== genRef.current) return handle;\n\n handleRef.current = handle;\n\n // Derive the fallback poll delay from the receiver's advertised\n // `pollInterval`. Spec allows it to be absent; we then use the\n // 5s default.\n const hintedInterval = handle.task.pollInterval;\n pollDelayRef.current =\n typeof hintedInterval === \"number\" && hintedInterval > 0\n ? hintedInterval * POLL_FALLBACK_MULTIPLIER\n : DEFAULT_POLL_INTERVAL_MS * POLL_FALLBACK_MULTIPLIER;\n\n setTask(handle.task);\n terminalRef.current = TERMINAL_STATUSES.has(handle.task.status);\n\n // Subscribe to `notifications/tasks/status`. Each notification\n // resets the poll countdown (that's the whole point of the\n // \"notification OR polling\" contract — if notifications flow,\n // we don't poll; if they don't, the timer fires).\n unsubscribeRef.current = handle.onStatus((updated) => {\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current = 0;\n setTask(updated);\n const isTerminal = TERMINAL_STATUSES.has(updated.status);\n terminalRef.current = isTerminal;\n if (isTerminal) {\n clearPollTimer();\n } else {\n scheduleNextPoll(gen);\n }\n });\n\n // Kick off the blocking result fetch — this is the authoritative\n // terminal value regardless of whether notifications or polls\n // landed in between. By spec, `tasks/result` blocks until the task\n // reaches a terminal status, so when this settles we KNOW the task\n // is terminal — stop polling and synthesize a terminal `task`\n // status so derived flags (`isTerminal`, `isWorking`) match the\n // populated `result` / `error` immediately.\n handle.result().then(\n (res) => {\n if (gen !== genRef.current) return;\n terminalRef.current = true;\n clearPollTimer();\n // Synthesize the terminal Task: failed if `isError`, otherwise\n // completed. The next status notification or refresh would\n // confirm this, but we want internal state consistent the\n // instant `result` is populated — a \"result populated while\n // isWorking=true\" render is incoherent for consumers.\n setTask((prev) => {\n const status: TaskStatus = res.isError ? FAILED_STATUS : COMPLETED_STATUS;\n const now = new Date().toISOString();\n return prev\n ? { ...prev, status, lastUpdatedAt: now }\n : {\n taskId: handle.task.taskId,\n status,\n ttl: handle.task.ttl,\n createdAt: handle.task.createdAt,\n lastUpdatedAt: now,\n };\n });\n if (res.isError) {\n // Spec: `CallToolResult.isError === true` is a tool-level\n // error, not a protocol error. Surface via `error` for\n // consumers who treat it as a failure, but also populate\n // `result` so callers inspecting the raw content block\n // still have access.\n setResult(res);\n const msg =\n typeof res.data === \"string\" && res.data.length > 0\n ? res.data\n : `Tool \"${toolName}\" returned isError: true`;\n setError(new Error(msg));\n } else {\n setResult(res);\n }\n },\n (err) => {\n if (gen !== genRef.current) return;\n // result() rejection means the `tasks/result` RPC failed\n // (transport error, taskId not found, bridge teardown). We\n // can't know the server-side task's actual final state, but\n // we know polling won't recover here either — same transport.\n // Mark terminal and synthesize `failed` status for UX\n // coherence; the populated `error` tells the consumer what\n // specifically went wrong.\n terminalRef.current = true;\n clearPollTimer();\n setTask((prev) => {\n const now = new Date().toISOString();\n return prev\n ? { ...prev, status: FAILED_STATUS, lastUpdatedAt: now }\n : {\n taskId: handle.task.taskId,\n status: FAILED_STATUS,\n ttl: handle.task.ttl,\n createdAt: handle.task.createdAt,\n lastUpdatedAt: now,\n };\n });\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n },\n );\n\n // Start the poll fallback only if we aren't already terminal.\n if (!terminalRef.current) scheduleNextPoll(gen);\n\n return handle;\n },\n [app, toolName, detachCurrent, clearPollTimer, scheduleNextPoll],\n );\n\n const cancel = useCallback(async (): Promise<void> => {\n const h = handleRef.current;\n if (!h) return;\n const gen = genRef.current;\n try {\n const cancelled = await h.cancel();\n if (gen !== genRef.current) return;\n setTask(cancelled);\n terminalRef.current = TERMINAL_STATUSES.has(cancelled.status);\n clearPollTimer();\n } catch (err) {\n if (gen !== genRef.current) return;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n }\n }, [clearPollTimer]);\n\n // Cleanup on unmount: stop polling, drop the status subscription.\n // Deliberately do NOT call `handle.cancel()` — the server-side task\n // keeps running so a remount can recover state.\n useEffect(() => {\n return () => {\n genRef.current += 1;\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n if (unsubscribeRef.current) {\n unsubscribeRef.current();\n unsubscribeRef.current = null;\n }\n handleRef.current = null;\n };\n }, []);\n\n const isTerminal = task !== null && TERMINAL_STATUSES.has(task.status);\n const isWorking = task !== null && !isTerminal;\n\n return { fire, task, result, error, isWorking, isTerminal, cancel };\n}\n"]}
1
+ {"version":3,"sources":["../../src/react/app-provider.tsx","../../src/react/hooks.ts"],"names":["createContext","useState","useRef","useEffect","connect","useContext","useCallback","RESOURCE_LIST_CHANGED_METHOD","action","pickFile","pickFiles","isTerminal","callToolAsTask"],"mappings":"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","file":"index.cjs","sourcesContent":["import { createContext, type ReactNode, useContext, useEffect, useRef, useState } from \"react\";\nimport { connect } from \"../connect.js\";\nimport type { App, ConnectOptions } from \"../types.js\";\n\nconst AppContext = createContext<App | null>(null);\n\nexport interface AppProviderProps extends ConnectOptions {\n children: ReactNode;\n}\n\n/**\n * Connect on mount and provide the {@link App} to everything below.\n *\n * Renders nothing until the handshake completes, so no hook below can observe\n * a half-connected app and no tool call can be fired into a host that has not\n * answered `ui/initialize` yet.\n */\nexport function AppProvider({ children, ...options }: AppProviderProps) {\n const [app, setApp] = useState<App | null>(null);\n const [error, setError] = useState<Error | null>(null);\n const connectingRef = useRef(false);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: connect once on mount\n useEffect(() => {\n // A ref, not cleanup-on-unmount: StrictMode unmounts and immediately\n // remounts, and the transport must survive that. The app is GC'd when the\n // provider is truly gone.\n if (connectingRef.current) return;\n connectingRef.current = true;\n\n connect(options).then(setApp, (err: unknown) => {\n setError(err instanceof Error ? err : new Error(String(err)));\n });\n }, []);\n\n // A host that answers `ui/initialize` with an error is a failure the app\n // cannot proceed through, and rendering nothing forever is the worst way to\n // report it: a blank pane and an unhandled rejection in a console nobody has\n // open. Re-throwing during render makes it an ordinary React error, so it\n // reaches the nearest error boundary and is loud in development.\n if (error) throw error;\n\n // Still connecting. Nothing below can observe a half-connected app, and no\n // hook can fire a call into a host that has not answered yet.\n if (!app) return null;\n\n return <AppContext.Provider value={app}>{children}</AppContext.Provider>;\n}\n\nexport function useAppContext(): App {\n const ctx = useContext(AppContext);\n if (!ctx) {\n throw new Error(\n \"useApp must be used within an <AppProvider>. Wrap your component tree with <AppProvider>.\",\n );\n }\n return ctx;\n}\n","import type { McpUiHostContext } from \"@modelcontextprotocol/ext-apps\";\nimport type {\n ResourceListChangedNotification,\n Task,\n TaskStatus,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { RESOURCE_LIST_CHANGED_METHOD } from \"../event-map.js\";\nimport { pickFile, pickFiles, action as sendAction } from \"../extensions.js\";\nimport { callToolAsTask } from \"../task-handle.js\";\nimport type {\n App,\n CallToolAsTaskOptions,\n FileResult,\n ModelContext,\n RequestFileOptions,\n TaskHandle,\n Theme,\n ToolCallResult,\n ToolResultData,\n} from \"../types.js\";\nimport { useAppContext } from \"./app-provider.js\";\n\n/** The connected app. Throws outside an `<AppProvider>`. */\nexport function useApp(): App {\n return useAppContext();\n}\n\n// -----------------------------------------------------------------------------\n// Host state\n// -----------------------------------------------------------------------------\n\n/**\n * The current theme, re-rendering only when it actually moves.\n *\n * `App` filters `host-context-changed` notifications through a theme equality\n * check, so a context update that leaves the derived theme untouched (a\n * workspace switch, say) does not re-render every themed component.\n */\nexport function useTheme(): Theme {\n const app = useAppContext();\n const [theme, setTheme] = useState<Theme>(() => app.theme);\n\n useEffect(() => {\n // Sync in case the theme changed between render and effect.\n setTheme(app.theme);\n return app.on(\"theme-changed\", setTheme);\n }, [app]);\n\n return theme;\n}\n\n/**\n * The full ext-apps host context — spec fields (`theme`, `styles`,\n * `displayMode`, `toolInfo`) plus whatever the host publishes alongside.\n * Re-renders on every `host-context-changed`.\n *\n * Prefer `useTheme()` when only theming matters: it filters no-op fires.\n * Reach for this one for host extensions, e.g. on NimbleBrain:\n *\n * ```tsx\n * const { workspace } = useHostContext<{ workspace?: { id: string } }>();\n * ```\n */\nexport function useHostContext<T extends McpUiHostContext = McpUiHostContext>(): T {\n const app = useAppContext();\n const [ctx, setCtx] = useState<T>(() => app.hostContext as T);\n\n useEffect(() => {\n setCtx(app.hostContext as T);\n return app.on(\"host-context-changed\", (c) => setCtx(c as T));\n }, [app]);\n\n return ctx;\n}\n\n/**\n * The latest tool result pushed by the host, or `null` before one arrives. A\n * host that mounts the app without a tool call never sends one, so `null` is a\n * state to render, not only a loading state.\n */\nexport function useToolResult(): ToolResultData | null {\n const app = useAppContext();\n const [data, setData] = useState<ToolResultData | null>(null);\n\n useEffect(() => {\n return app.on(\"tool-result\", setData);\n }, [app]);\n\n return data;\n}\n\n/** The arguments the host is calling the bound tool with, or `null` until it sends them. */\nexport function useToolInput(): Record<string, unknown> | null {\n const app = useAppContext();\n const [input, setInput] = useState<Record<string, unknown> | null>(null);\n\n useEffect(() => {\n return app.on(\"tool-input\", setInput);\n }, [app]);\n\n return input;\n}\n\n/** Report this app's frame size to the host. Every host accepts it; the spec has no capability for it. */\nexport function useResize(): (width?: number, height?: number) => void {\n const app = useAppContext();\n return useCallback((width?: number, height?: number) => app.resize(width, height), [app]);\n}\n\n// -----------------------------------------------------------------------------\n// Tools\n// -----------------------------------------------------------------------------\n\nexport interface UseCallToolResult<TOutput> {\n call: (args?: Record<string, unknown>) => Promise<ToolCallResult<TOutput>>;\n isPending: boolean;\n error: Error | null;\n data: TOutput | null;\n}\n\n/**\n * Call one tool, with pending/error/data state for the latest call.\n *\n * Where the host did not declare `serverTools`, `call` rejects with\n * `HostCapabilityError` without sending, and `error` holds it.\n */\nexport function useCallTool<TOutput = unknown>(toolName: string): UseCallToolResult<TOutput> {\n const app = useAppContext();\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<TOutput | null>(null);\n const callIdRef = useRef(0);\n\n const call = useCallback(\n async (args?: Record<string, unknown>): Promise<ToolCallResult<TOutput>> => {\n const id = ++callIdRef.current;\n setIsPending(true);\n setError(null);\n\n try {\n const result = await app.callTool<TOutput>(toolName, args);\n // Stale guard: only update if this is still the latest call.\n if (id === callIdRef.current) {\n setData(result.data);\n setIsPending(false);\n }\n return result;\n } catch (err) {\n if (id === callIdRef.current) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n setIsPending(false);\n }\n throw err;\n }\n },\n [app, toolName],\n );\n\n return { call, isPending, error, data };\n}\n\n/**\n * Run `callback` when the app's own MCP server announces that its data changed.\n *\n * A server sends `notifications/resources/list_changed` from the write that\n * changed its data, and an MCP Apps host forwards it to that server's views\n * (host capability `serverResources.listChanged`). The callback receives the\n * notification's params as the spec defines them, or `{}` when the host sends\n * none. They name no server and no tool: the notification only ever comes from\n * this app's own server, and a change need not come from a tool call at all.\n *\n * Where the host did not declare `serverResources.listChanged`, the callback\n * never runs. Nothing fails: the app shows what it last loaded until the user\n * or the app reloads it.\n */\nexport function useDataSync(\n callback: (params: NonNullable<ResourceListChangedNotification[\"params\"]>) => void,\n): void {\n const app = useAppContext();\n const callbackRef = useRef(callback);\n callbackRef.current = callback;\n\n useEffect(() => {\n return app.on(RESOURCE_LIST_CHANGED_METHOD, (params) => callbackRef.current(params ?? {}));\n }, [app]);\n}\n\n// -----------------------------------------------------------------------------\n// Agent-facing state\n// -----------------------------------------------------------------------------\n\n/** Debounce window for `useModelContext`, in milliseconds. */\nconst MODEL_CONTEXT_DEBOUNCE_MS = 250;\n\n/**\n * Push what the user is looking at to the agent (ext-apps\n * `ui/update-model-context`), debounced so a selection the user drags through\n * costs one frame rather than thirty.\n *\n * **Declarative** — pushes when `deps` change:\n * ```tsx\n * useModelContext(() => ({\n * state: { board: selectedBoard },\n * summary: `Viewing \"${selectedBoard?.name}\"`,\n * }), [selectedBoard]);\n * ```\n *\n * **Imperative** — returns a push function:\n * ```tsx\n * const push = useModelContext();\n * push({ board: selectedBoard }, \"Viewing board X\");\n * ```\n *\n * The debounce lives here rather than on `app.updateModelContext`, which\n * sends immediately: the rapid-change problem is a React one, and the plain\n * method should do what it says.\n *\n * A no-op where the host did not declare `updateModelContext`.\n */\nexport function useModelContext(): (state: Record<string, unknown>, summary?: string) => void;\nexport function useModelContext(factory: () => ModelContext, deps: unknown[]): void;\nexport function useModelContext(\n factory?: () => ModelContext,\n deps?: unknown[],\n): ((state: Record<string, unknown>, summary?: string) => void) | undefined {\n const app = useAppContext();\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const push = useCallback(\n (state: Record<string, unknown>, summary?: string) => {\n if (timerRef.current) clearTimeout(timerRef.current);\n timerRef.current = setTimeout(() => {\n timerRef.current = null;\n app.updateModelContext(state, summary);\n }, MODEL_CONTEXT_DEBOUNCE_MS);\n },\n [app],\n );\n\n useEffect(() => {\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n };\n }, []);\n\n // Declarative mode: push when deps change. The deps array is\n // caller-provided (mirrors useMemo/useEffect).\n const factoryRef = useRef(factory);\n factoryRef.current = factory;\n useEffect(() => {\n if (!factoryRef.current) return;\n const { state, summary } = factoryRef.current();\n push(state, summary);\n }, [...(deps ?? []), push]);\n\n if (!factory) return push;\n}\n\n/**\n * Send a user message into the agent conversation. A no-op where the host did\n * not declare `message`; check `app.hostCapabilities.message` to decide whether\n * to offer the control at all.\n */\nexport function useSendMessage(): (\n text: string,\n context?: { action?: string; entity?: string },\n) => void {\n const app = useAppContext();\n return useCallback(\n (text: string, context?: { action?: string; entity?: string }) =>\n app.sendMessage(text, context),\n [app],\n );\n}\n\n// -----------------------------------------------------------------------------\n// NimbleBrain host extensions\n// -----------------------------------------------------------------------------\n\n/** Trigger a host-side action. A no-op where the host did not declare `ai.nimblebrain/action`. */\nexport function useAction(): (name: string, params?: Record<string, unknown>) => void {\n const app = useAppContext();\n return useCallback(\n (name: string, params?: Record<string, unknown>) => sendAction(app, name, params),\n [app],\n );\n}\n\nexport interface UseFileUploadResult {\n pickFile: (options?: RequestFileOptions) => Promise<FileResult | null>;\n pickFiles: (options?: RequestFileOptions) => Promise<FileResult[]>;\n isPending: boolean;\n}\n\n/**\n * The host's native file picker, with a pending flag. Both functions reject\n * with `HostCapabilityError` where the host did not declare\n * `ai.nimblebrain/request-file`; `hostSupports(app, \"requestFile\")` says so up\n * front.\n */\nexport function useFileUpload(): UseFileUploadResult {\n const app = useAppContext();\n const [isPending, setIsPending] = useState(false);\n\n const one = useCallback(\n async (options?: RequestFileOptions) => {\n setIsPending(true);\n try {\n return await pickFile(app, options);\n } finally {\n setIsPending(false);\n }\n },\n [app],\n );\n\n const many = useCallback(\n async (options?: RequestFileOptions) => {\n setIsPending(true);\n try {\n return await pickFiles(app, options);\n } finally {\n setIsPending(false);\n }\n },\n [app],\n );\n\n return { pickFile: one, pickFiles: many, isPending };\n}\n\n// -----------------------------------------------------------------------------\n// useCallToolAsTask — lifecycle wrapper around `callToolAsTask(app, …)`\n// -----------------------------------------------------------------------------\n\n/**\n * Spec terminal status values for the MCP 2025-11-25 tasks utility.\n *\n * Typed via `satisfies TaskStatus` so a rename of any member of the\n * spec enum (`completed`/`failed`/`cancelled`) trips `tsc` — we never\n * hand-type these as bare string literals in comparisons.\n */\nconst COMPLETED_STATUS = \"completed\" satisfies TaskStatus;\nconst FAILED_STATUS = \"failed\" satisfies TaskStatus;\nconst CANCELLED_STATUS = \"cancelled\" satisfies TaskStatus;\n\nconst TERMINAL_STATUSES: ReadonlySet<TaskStatus> = new Set<TaskStatus>([\n COMPLETED_STATUS,\n FAILED_STATUS,\n CANCELLED_STATUS,\n]);\n\n/**\n * Fallback poll cadence used when the receiver's `CreateTaskResult.task`\n * carries no `pollInterval`. The effective fire delay is this value × 1.5\n * ≈ 7.5s, well below default TTLs but long enough to avoid hammering hosts\n * that do emit `notifications/tasks/status`.\n */\nconst DEFAULT_POLL_INTERVAL_MS = 5_000;\nconst POLL_FALLBACK_MULTIPLIER = 1.5;\n\n/**\n * Stop the poll fallback after this many consecutive `refresh()` failures.\n * Bridge teardown / TTL eviction / network outage all manifest as repeated\n * `tasks/get` rejections. Without a guard the timer re-arms forever; with\n * it we stop polling silently after `MAX_REFRESH_FAILURES` strikes — the\n * blocking `result()` path remains the authoritative source of truth, so\n * giving up on polling never loses the terminal value.\n */\nconst MAX_REFRESH_FAILURES = 5;\n\nexport interface UseCallToolAsTaskResult<TInput, TOutput> {\n /**\n * Start (or re-start) a task-augmented tool call. Returns the\n * resolved `TaskHandle` so callers can `await fire(...)` if they\n * want to know when the server has accepted the task, but reading\n * `task`/`result`/`error` from the hook is usually enough.\n *\n * Re-firing while a previous task is still in flight detaches this\n * hook from the prior handle (stops polling, unsubscribes) but does\n * NOT cancel the server-side task — the task keeps running and its\n * result may still be fetched elsewhere (e.g. on page revisit).\n */\n fire(args?: TInput, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>>;\n /** Latest `Task` state, or `null` before `fire()` has been called. */\n task: Task | null;\n /** Populated once `handle.result()` resolves non-error. */\n result: ToolCallResult<TOutput> | null;\n /** Populated on rejection or when `result.isError === true`. */\n error: Error | null;\n /** `true` while the task is non-terminal (`working` / `input_required`). */\n isWorking: boolean;\n /** `true` when `task.status ∈ {completed, failed, cancelled}`. */\n isTerminal: boolean;\n /**\n * Cancel the active task via `tasks/cancel`. No-op when no task is\n * active. Swallowed errors surface via `error`.\n */\n cancel(): Promise<void>;\n}\n\n/**\n * React wrapper around `callToolAsTask(app, …)`.\n *\n * Handles the full MCP 2025-11-25 task lifecycle:\n *\n * 1. `fire(args, options?)` sends the task-augmented `tools/call` and\n * stores the returned `TaskHandle` in a ref.\n * 2. Subscribes to `handle.onStatus` — updates `task` whenever the\n * host emits `notifications/tasks/status` (OPTIONAL per spec).\n * 3. Starts a polling fallback: if no status notification arrives\n * within `pollInterval × 1.5` (defaulting to ~7.5s), calls\n * `handle.refresh()` for canonical state. Stops on terminal.\n * 4. Awaits `handle.result()` in the background — resolves to either\n * `result` (success / `isError: false`) or `error` (network reject\n * OR `result.isError === true`).\n *\n * Where the host did not declare the tasks capability, `fire` rejects with\n * `HostCapabilityError` and `error` holds it; `app.supportsTasks` says so up\n * front.\n *\n * Cleanup (unmount or re-fire) unsubscribes from status events and\n * clears the poll timer, but does NOT cancel the server-side task —\n * the caller may remount and recover state by firing again, and tasks\n * outlive iframe teardown until TTL elapses.\n */\nexport function useCallToolAsTask<TInput = Record<string, unknown>, TOutput = unknown>(\n toolName: string,\n): UseCallToolAsTaskResult<TInput, TOutput> {\n const app = useAppContext();\n\n const [task, setTask] = useState<Task | null>(null);\n const [result, setResult] = useState<ToolCallResult<TOutput> | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n // Per-fire generation counter. Every `fire()` increments; any\n // asynchronous callback (status listener, poll timer, `result()`\n // resolution) captures the gen at schedule time and bails if the\n // current gen has moved past it. This is the single source of truth\n // for \"is this work still relevant?\" — more robust than comparing\n // TaskHandle identity because handles can be detached by re-fire.\n const genRef = useRef(0);\n\n // Active handle + its teardown handles. We keep both in refs so the\n // hook's stable `fire`/`cancel` callbacks can reach the current\n // lifecycle state without re-binding on every render.\n const handleRef = useRef<TaskHandle<TOutput> | null>(null);\n const unsubscribeRef = useRef<(() => void) | null>(null);\n const pollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n // `pollInterval × 1.5`, captured per-fire. Falls back to the 5s\n // default when the host didn't provide a `pollInterval` in the\n // initial CreateTaskResult.task.\n const pollDelayRef = useRef<number>(DEFAULT_POLL_INTERVAL_MS * POLL_FALLBACK_MULTIPLIER);\n\n // Track the latest known status out-of-band so the poll callback\n // can decide whether to keep polling without depending on the\n // `task` React state (which lags a render behind setState).\n const terminalRef = useRef<boolean>(false);\n\n // Consecutive `refresh()` failure count for the active fire. Reset\n // on every successful refresh, status notification, or new fire.\n const refreshFailureCountRef = useRef<number>(0);\n\n const clearPollTimer = useCallback(() => {\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n }, []);\n\n const detachCurrent = useCallback(() => {\n clearPollTimer();\n if (unsubscribeRef.current) {\n unsubscribeRef.current();\n unsubscribeRef.current = null;\n }\n handleRef.current = null;\n }, [clearPollTimer]);\n\n const scheduleNextPoll = useCallback(\n (gen: number) => {\n clearPollTimer();\n if (terminalRef.current) return;\n pollTimerRef.current = setTimeout(() => {\n // Bail if this fire has been superseded or torn down.\n if (gen !== genRef.current) return;\n const h = handleRef.current;\n if (!h) return;\n if (terminalRef.current) return;\n // `refresh()` is the canonical source for `createdAt` /\n // `lastUpdatedAt` / `ttl` — notification-derived Tasks carry\n // placeholders per the router in `task-handle.ts`.\n h.refresh().then(\n (fresh) => {\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current = 0;\n setTask(fresh);\n const isTerminal = TERMINAL_STATUSES.has(fresh.status);\n terminalRef.current = isTerminal;\n if (!isTerminal) scheduleNextPoll(gen);\n },\n () => {\n // Swallow refresh errors — the blocking `tasks/result` is\n // the authoritative path; polling is best-effort. But guard\n // against runaway re-arming: if the bridge is gone or the\n // task TTL has elapsed, every refresh rejects. Stop after\n // MAX_REFRESH_FAILURES consecutive strikes; result() will\n // still surface a terminal value or error when it settles.\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current += 1;\n if (refreshFailureCountRef.current >= MAX_REFRESH_FAILURES) return;\n if (!terminalRef.current) scheduleNextPoll(gen);\n },\n );\n }, pollDelayRef.current);\n },\n [clearPollTimer],\n );\n\n const fire = useCallback(\n async (args?: TInput, options?: CallToolAsTaskOptions): Promise<TaskHandle<TOutput>> => {\n // Detach any in-flight prior task BEFORE incrementing the gen so\n // its callbacks see the new gen and bail. (Incrementing then\n // detaching would also work, but detach-first makes the order\n // obvious: stop listening, bump generation, start fresh.)\n detachCurrent();\n const gen = ++genRef.current;\n\n // Reset per-fire state. Don't wipe `task` yet — `callToolAsTask`\n // is async; showing the previous terminal state briefly is less\n // jarring than flicker to null → working. We clear on resolution.\n setResult(null);\n setError(null);\n terminalRef.current = false;\n refreshFailureCountRef.current = 0;\n\n let handle: TaskHandle<TOutput>;\n try {\n handle = await callToolAsTask<TOutput>(app, toolName, args, options);\n } catch (err) {\n if (gen !== genRef.current) throw err;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw err;\n }\n\n // Caller superseded the fire between request and response —\n // don't attach listeners, but still return the handle so the\n // awaiter can observe it.\n if (gen !== genRef.current) return handle;\n\n handleRef.current = handle;\n\n // Derive the fallback poll delay from the receiver's advertised\n // `pollInterval`. Spec allows it to be absent; we then use the\n // 5s default.\n const hintedInterval = handle.task.pollInterval;\n pollDelayRef.current =\n typeof hintedInterval === \"number\" && hintedInterval > 0\n ? hintedInterval * POLL_FALLBACK_MULTIPLIER\n : DEFAULT_POLL_INTERVAL_MS * POLL_FALLBACK_MULTIPLIER;\n\n setTask(handle.task);\n terminalRef.current = TERMINAL_STATUSES.has(handle.task.status);\n\n // Subscribe to `notifications/tasks/status`. Each notification\n // resets the poll countdown (that's the whole point of the\n // \"notification OR polling\" contract — if notifications flow,\n // we don't poll; if they don't, the timer fires).\n unsubscribeRef.current = handle.onStatus((updated) => {\n if (gen !== genRef.current) return;\n refreshFailureCountRef.current = 0;\n setTask(updated);\n const isTerminal = TERMINAL_STATUSES.has(updated.status);\n terminalRef.current = isTerminal;\n if (isTerminal) {\n clearPollTimer();\n } else {\n scheduleNextPoll(gen);\n }\n });\n\n // Kick off the blocking result fetch — this is the authoritative\n // terminal value regardless of whether notifications or polls\n // landed in between. By spec, `tasks/result` blocks until the task\n // reaches a terminal status, so when this settles we KNOW the task\n // is terminal — stop polling and synthesize a terminal `task`\n // status so derived flags (`isTerminal`, `isWorking`) match the\n // populated `result` / `error` immediately.\n handle.result().then(\n (res) => {\n if (gen !== genRef.current) return;\n terminalRef.current = true;\n clearPollTimer();\n // Synthesize the terminal Task: failed if `isError`, otherwise\n // completed. The next status notification or refresh would\n // confirm this, but we want internal state consistent the\n // instant `result` is populated — a \"result populated while\n // isWorking=true\" render is incoherent for consumers.\n setTask((prev) => {\n const status: TaskStatus = res.isError ? FAILED_STATUS : COMPLETED_STATUS;\n const now = new Date().toISOString();\n return prev\n ? { ...prev, status, lastUpdatedAt: now }\n : {\n taskId: handle.task.taskId,\n status,\n ttl: handle.task.ttl,\n createdAt: handle.task.createdAt,\n lastUpdatedAt: now,\n };\n });\n if (res.isError) {\n // Spec: `CallToolResult.isError === true` is a tool-level\n // error, not a protocol error. Surface via `error` for\n // consumers who treat it as a failure, but also populate\n // `result` so callers inspecting the raw content block\n // still have access.\n setResult(res);\n const msg =\n typeof res.data === \"string\" && res.data.length > 0\n ? res.data\n : `Tool \"${toolName}\" returned isError: true`;\n setError(new Error(msg));\n } else {\n setResult(res);\n }\n },\n (err) => {\n if (gen !== genRef.current) return;\n // result() rejection means the `tasks/result` RPC failed\n // (transport error, taskId not found, bridge teardown). We\n // can't know the server-side task's actual final state, but\n // we know polling won't recover here either — same transport.\n // Mark terminal and synthesize `failed` status for UX\n // coherence; the populated `error` tells the consumer what\n // specifically went wrong.\n terminalRef.current = true;\n clearPollTimer();\n setTask((prev) => {\n const now = new Date().toISOString();\n return prev\n ? { ...prev, status: FAILED_STATUS, lastUpdatedAt: now }\n : {\n taskId: handle.task.taskId,\n status: FAILED_STATUS,\n ttl: handle.task.ttl,\n createdAt: handle.task.createdAt,\n lastUpdatedAt: now,\n };\n });\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n },\n );\n\n // Start the poll fallback only if we aren't already terminal.\n if (!terminalRef.current) scheduleNextPoll(gen);\n\n return handle;\n },\n [app, toolName, detachCurrent, clearPollTimer, scheduleNextPoll],\n );\n\n const cancel = useCallback(async (): Promise<void> => {\n const h = handleRef.current;\n if (!h) return;\n const gen = genRef.current;\n try {\n const cancelled = await h.cancel();\n if (gen !== genRef.current) return;\n setTask(cancelled);\n terminalRef.current = TERMINAL_STATUSES.has(cancelled.status);\n clearPollTimer();\n } catch (err) {\n if (gen !== genRef.current) return;\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n }\n }, [clearPollTimer]);\n\n // Cleanup on unmount: stop polling, drop the status subscription.\n // Deliberately do NOT call `handle.cancel()` — the server-side task\n // keeps running so a remount can recover state.\n useEffect(() => {\n return () => {\n genRef.current += 1;\n if (pollTimerRef.current !== null) {\n clearTimeout(pollTimerRef.current);\n pollTimerRef.current = null;\n }\n if (unsubscribeRef.current) {\n unsubscribeRef.current();\n unsubscribeRef.current = null;\n }\n handleRef.current = null;\n };\n }, []);\n\n const isTerminal = task !== null && TERMINAL_STATUSES.has(task.status);\n const isWorking = task !== null && !isTerminal;\n\n return { fire, task, result, error, isWorking, isTerminal, cancel };\n}\n"]}
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { C as ConnectOptions, a as CallToolAsTaskOptions, T as TaskHandle, b as ToolCallResult, c as CallToolOptions, R as RequestFileOptions, F as FileResult, A as App, D as DataChangedEvent, M as ModelContext, d as Theme, e as ToolResultData } from '../types-uEO4VFJ2.cjs';
3
+ import { C as ConnectOptions, a as CallToolAsTaskOptions, T as TaskHandle, b as ToolCallResult, R as RequestFileOptions, F as FileResult, A as App, M as ModelContext, c as Theme, d as ToolResultData } from '../types-BxPfGHKO.cjs';
4
4
  import { McpUiHostContext } from '@modelcontextprotocol/ext-apps';
5
- import { Task } from '@modelcontextprotocol/sdk/types.js';
5
+ import { Task, ResourceListChangedNotification } from '@modelcontextprotocol/sdk/types.js';
6
6
 
7
7
  interface AppProviderProps extends ConnectOptions {
8
8
  children: ReactNode;
@@ -39,22 +39,44 @@ declare function useTheme(): Theme;
39
39
  * ```
40
40
  */
41
41
  declare function useHostContext<T extends McpUiHostContext = McpUiHostContext>(): T;
42
- /** The latest tool result pushed by the host, or `null` before one arrives. */
42
+ /**
43
+ * The latest tool result pushed by the host, or `null` before one arrives. A
44
+ * host that mounts the app without a tool call never sends one, so `null` is a
45
+ * state to render, not only a loading state.
46
+ */
43
47
  declare function useToolResult(): ToolResultData | null;
44
- /** The arguments the host is calling the bound tool with, as they arrive. */
48
+ /** The arguments the host is calling the bound tool with, or `null` until it sends them. */
45
49
  declare function useToolInput(): Record<string, unknown> | null;
46
- /** Ask the host to resize this app's frame. */
50
+ /** Report this app's frame size to the host. Every host accepts it; the spec has no capability for it. */
47
51
  declare function useResize(): (width?: number, height?: number) => void;
48
52
  interface UseCallToolResult<TOutput> {
49
- call: (args?: Record<string, unknown>, options?: CallToolOptions) => Promise<ToolCallResult<TOutput>>;
53
+ call: (args?: Record<string, unknown>) => Promise<ToolCallResult<TOutput>>;
50
54
  isPending: boolean;
51
55
  error: Error | null;
52
56
  data: TOutput | null;
53
57
  }
54
- /** Call one tool, with pending/error/data state for the latest call. */
58
+ /**
59
+ * Call one tool, with pending/error/data state for the latest call.
60
+ *
61
+ * Where the host did not declare `serverTools`, `call` rejects with
62
+ * `HostCapabilityError` without sending, and `error` holds it.
63
+ */
55
64
  declare function useCallTool<TOutput = unknown>(toolName: string): UseCallToolResult<TOutput>;
56
- /** Run `callback` whenever the agent changes data this app displays. */
57
- declare function useDataSync(callback: (event: DataChangedEvent) => void): void;
65
+ /**
66
+ * Run `callback` when the app's own MCP server announces that its data changed.
67
+ *
68
+ * A server sends `notifications/resources/list_changed` from the write that
69
+ * changed its data, and an MCP Apps host forwards it to that server's views
70
+ * (host capability `serverResources.listChanged`). The callback receives the
71
+ * notification's params as the spec defines them, or `{}` when the host sends
72
+ * none. They name no server and no tool: the notification only ever comes from
73
+ * this app's own server, and a change need not come from a tool call at all.
74
+ *
75
+ * Where the host did not declare `serverResources.listChanged`, the callback
76
+ * never runs. Nothing fails: the app shows what it last loaded until the user
77
+ * or the app reloads it.
78
+ */
79
+ declare function useDataSync(callback: (params: NonNullable<ResourceListChangedNotification["params"]>) => void): void;
58
80
  /**
59
81
  * Push what the user is looking at to the agent (ext-apps
60
82
  * `ui/update-model-context`), debounced so a selection the user drags through
@@ -77,22 +99,33 @@ declare function useDataSync(callback: (event: DataChangedEvent) => void): void;
77
99
  * The debounce lives here rather than on `app.updateModelContext`, which
78
100
  * sends immediately: the rapid-change problem is a React one, and the plain
79
101
  * method should do what it says.
102
+ *
103
+ * A no-op where the host did not declare `updateModelContext`.
80
104
  */
81
105
  declare function useModelContext(): (state: Record<string, unknown>, summary?: string) => void;
82
106
  declare function useModelContext(factory: () => ModelContext, deps: unknown[]): void;
83
- /** Send a user message into the agent conversation. */
107
+ /**
108
+ * Send a user message into the agent conversation. A no-op where the host did
109
+ * not declare `message`; check `app.hostCapabilities.message` to decide whether
110
+ * to offer the control at all.
111
+ */
84
112
  declare function useSendMessage(): (text: string, context?: {
85
113
  action?: string;
86
114
  entity?: string;
87
115
  }) => void;
88
- /** Trigger a host-side action. No-op off a NimbleBrain host. */
116
+ /** Trigger a host-side action. A no-op where the host did not declare `ai.nimblebrain/action`. */
89
117
  declare function useAction(): (name: string, params?: Record<string, unknown>) => void;
90
118
  interface UseFileUploadResult {
91
119
  pickFile: (options?: RequestFileOptions) => Promise<FileResult | null>;
92
120
  pickFiles: (options?: RequestFileOptions) => Promise<FileResult[]>;
93
121
  isPending: boolean;
94
122
  }
95
- /** The host's native file picker, with a pending flag. NimbleBrain only. */
123
+ /**
124
+ * The host's native file picker, with a pending flag. Both functions reject
125
+ * with `HostCapabilityError` where the host did not declare
126
+ * `ai.nimblebrain/request-file`; `hostSupports(app, "requestFile")` says so up
127
+ * front.
128
+ */
96
129
  declare function useFileUpload(): UseFileUploadResult;
97
130
  interface UseCallToolAsTaskResult<TInput, TOutput> {
98
131
  /**
@@ -139,6 +172,10 @@ interface UseCallToolAsTaskResult<TInput, TOutput> {
139
172
  * `result` (success / `isError: false`) or `error` (network reject
140
173
  * OR `result.isError === true`).
141
174
  *
175
+ * Where the host did not declare the tasks capability, `fire` rejects with
176
+ * `HostCapabilityError` and `error` holds it; `app.supportsTasks` says so up
177
+ * front.
178
+ *
142
179
  * Cleanup (unmount or re-fire) unsubscribes from status events and
143
180
  * clears the poll timer, but does NOT cancel the server-side task —
144
181
  * the caller may remount and recover state by firing again, and tasks
@@ -1,8 +1,8 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { C as ConnectOptions, a as CallToolAsTaskOptions, T as TaskHandle, b as ToolCallResult, c as CallToolOptions, R as RequestFileOptions, F as FileResult, A as App, D as DataChangedEvent, M as ModelContext, d as Theme, e as ToolResultData } from '../types-uEO4VFJ2.js';
3
+ import { C as ConnectOptions, a as CallToolAsTaskOptions, T as TaskHandle, b as ToolCallResult, R as RequestFileOptions, F as FileResult, A as App, M as ModelContext, c as Theme, d as ToolResultData } from '../types-BxPfGHKO.js';
4
4
  import { McpUiHostContext } from '@modelcontextprotocol/ext-apps';
5
- import { Task } from '@modelcontextprotocol/sdk/types.js';
5
+ import { Task, ResourceListChangedNotification } from '@modelcontextprotocol/sdk/types.js';
6
6
 
7
7
  interface AppProviderProps extends ConnectOptions {
8
8
  children: ReactNode;
@@ -39,22 +39,44 @@ declare function useTheme(): Theme;
39
39
  * ```
40
40
  */
41
41
  declare function useHostContext<T extends McpUiHostContext = McpUiHostContext>(): T;
42
- /** The latest tool result pushed by the host, or `null` before one arrives. */
42
+ /**
43
+ * The latest tool result pushed by the host, or `null` before one arrives. A
44
+ * host that mounts the app without a tool call never sends one, so `null` is a
45
+ * state to render, not only a loading state.
46
+ */
43
47
  declare function useToolResult(): ToolResultData | null;
44
- /** The arguments the host is calling the bound tool with, as they arrive. */
48
+ /** The arguments the host is calling the bound tool with, or `null` until it sends them. */
45
49
  declare function useToolInput(): Record<string, unknown> | null;
46
- /** Ask the host to resize this app's frame. */
50
+ /** Report this app's frame size to the host. Every host accepts it; the spec has no capability for it. */
47
51
  declare function useResize(): (width?: number, height?: number) => void;
48
52
  interface UseCallToolResult<TOutput> {
49
- call: (args?: Record<string, unknown>, options?: CallToolOptions) => Promise<ToolCallResult<TOutput>>;
53
+ call: (args?: Record<string, unknown>) => Promise<ToolCallResult<TOutput>>;
50
54
  isPending: boolean;
51
55
  error: Error | null;
52
56
  data: TOutput | null;
53
57
  }
54
- /** Call one tool, with pending/error/data state for the latest call. */
58
+ /**
59
+ * Call one tool, with pending/error/data state for the latest call.
60
+ *
61
+ * Where the host did not declare `serverTools`, `call` rejects with
62
+ * `HostCapabilityError` without sending, and `error` holds it.
63
+ */
55
64
  declare function useCallTool<TOutput = unknown>(toolName: string): UseCallToolResult<TOutput>;
56
- /** Run `callback` whenever the agent changes data this app displays. */
57
- declare function useDataSync(callback: (event: DataChangedEvent) => void): void;
65
+ /**
66
+ * Run `callback` when the app's own MCP server announces that its data changed.
67
+ *
68
+ * A server sends `notifications/resources/list_changed` from the write that
69
+ * changed its data, and an MCP Apps host forwards it to that server's views
70
+ * (host capability `serverResources.listChanged`). The callback receives the
71
+ * notification's params as the spec defines them, or `{}` when the host sends
72
+ * none. They name no server and no tool: the notification only ever comes from
73
+ * this app's own server, and a change need not come from a tool call at all.
74
+ *
75
+ * Where the host did not declare `serverResources.listChanged`, the callback
76
+ * never runs. Nothing fails: the app shows what it last loaded until the user
77
+ * or the app reloads it.
78
+ */
79
+ declare function useDataSync(callback: (params: NonNullable<ResourceListChangedNotification["params"]>) => void): void;
58
80
  /**
59
81
  * Push what the user is looking at to the agent (ext-apps
60
82
  * `ui/update-model-context`), debounced so a selection the user drags through
@@ -77,22 +99,33 @@ declare function useDataSync(callback: (event: DataChangedEvent) => void): void;
77
99
  * The debounce lives here rather than on `app.updateModelContext`, which
78
100
  * sends immediately: the rapid-change problem is a React one, and the plain
79
101
  * method should do what it says.
102
+ *
103
+ * A no-op where the host did not declare `updateModelContext`.
80
104
  */
81
105
  declare function useModelContext(): (state: Record<string, unknown>, summary?: string) => void;
82
106
  declare function useModelContext(factory: () => ModelContext, deps: unknown[]): void;
83
- /** Send a user message into the agent conversation. */
107
+ /**
108
+ * Send a user message into the agent conversation. A no-op where the host did
109
+ * not declare `message`; check `app.hostCapabilities.message` to decide whether
110
+ * to offer the control at all.
111
+ */
84
112
  declare function useSendMessage(): (text: string, context?: {
85
113
  action?: string;
86
114
  entity?: string;
87
115
  }) => void;
88
- /** Trigger a host-side action. No-op off a NimbleBrain host. */
116
+ /** Trigger a host-side action. A no-op where the host did not declare `ai.nimblebrain/action`. */
89
117
  declare function useAction(): (name: string, params?: Record<string, unknown>) => void;
90
118
  interface UseFileUploadResult {
91
119
  pickFile: (options?: RequestFileOptions) => Promise<FileResult | null>;
92
120
  pickFiles: (options?: RequestFileOptions) => Promise<FileResult[]>;
93
121
  isPending: boolean;
94
122
  }
95
- /** The host's native file picker, with a pending flag. NimbleBrain only. */
123
+ /**
124
+ * The host's native file picker, with a pending flag. Both functions reject
125
+ * with `HostCapabilityError` where the host did not declare
126
+ * `ai.nimblebrain/request-file`; `hostSupports(app, "requestFile")` says so up
127
+ * front.
128
+ */
96
129
  declare function useFileUpload(): UseFileUploadResult;
97
130
  interface UseCallToolAsTaskResult<TInput, TOutput> {
98
131
  /**
@@ -139,6 +172,10 @@ interface UseCallToolAsTaskResult<TInput, TOutput> {
139
172
  * `result` (success / `isError: false`) or `error` (network reject
140
173
  * OR `result.isError === true`).
141
174
  *
175
+ * Where the host did not declare the tasks capability, `fire` rejects with
176
+ * `HostCapabilityError` and `error` holds it; `app.supportsTasks` says so up
177
+ * front.
178
+ *
142
179
  * Cleanup (unmount or re-fire) unsubscribes from status events and
143
180
  * clears the poll timer, but does NOT cancel the server-side task —
144
181
  * the caller may remount and recover state by firing again, and tasks
@@ -1,5 +1,6 @@
1
- import { connect, action, pickFile, pickFiles, callToolAsTask } from '../chunk-3YSXPBEQ.js';
2
- import '../chunk-HKRTDGXN.js';
1
+ import { connect, action, pickFile, pickFiles, callToolAsTask } from '../chunk-TR2YNWZ5.js';
2
+ import '../chunk-DJS2FKBN.js';
3
+ import { RESOURCE_LIST_CHANGED_METHOD } from '../chunk-H3INUKA3.js';
3
4
  import { createContext, useState, useRef, useEffect, useCallback, useContext } from 'react';
4
5
  import { jsx } from 'react/jsx-runtime';
5
6
 
@@ -76,12 +77,12 @@ function useCallTool(toolName) {
76
77
  const [data, setData] = useState(null);
77
78
  const callIdRef = useRef(0);
78
79
  const call = useCallback(
79
- async (args, options) => {
80
+ async (args) => {
80
81
  const id = ++callIdRef.current;
81
82
  setIsPending(true);
82
83
  setError(null);
83
84
  try {
84
- const result = await app.callTool(toolName, args, options);
85
+ const result = await app.callTool(toolName, args);
85
86
  if (id === callIdRef.current) {
86
87
  setData(result.data);
87
88
  setIsPending(false);
@@ -105,7 +106,7 @@ function useDataSync(callback) {
105
106
  const callbackRef = useRef(callback);
106
107
  callbackRef.current = callback;
107
108
  useEffect(() => {
108
- return app.on("data-changed", (event) => callbackRef.current(event));
109
+ return app.on(RESOURCE_LIST_CHANGED_METHOD, (params) => callbackRef.current(params ?? {}));
109
110
  }, [app]);
110
111
  }
111
112
  var MODEL_CONTEXT_DEBOUNCE_MS = 250;