{"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"]}