{"version":3,"sources":["../src/mcp/server.ts","../src/presence/wrap-tool-with-activity.ts","../src/undo/undo-tools.ts","../src/bridges/sheets.ts"],"names":["emitActivity","undoOne","redoOne","readHistory"],"mappings":"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","file":"bridges-sheets.cjs","sourcesContent":["import {\n  type CallToolResult,\n  type JsonObject,\n  type JsonRpcMessage,\n  type JsonRpcRequest,\n  type JsonRpcId,\n  type RegisteredTool,\n  type ServerCapabilities,\n  type ServerInfo,\n  type ToolDefinition,\n  type ToolHandler,\n  JSONRPC_INTERNAL_ERROR,\n  JSONRPC_INVALID_PARAMS,\n  JSONRPC_METHOD_NOT_FOUND,\n  MCP_PROTOCOL_VERSION,\n} from \"./types\";\nimport { ToolRegistry } from \"./tool-host\";\n\nexport type McpServerOptions = {\n  info: ServerInfo;\n  /** Defaults to { tools: { listChanged: true } } */\n  capabilities?: ServerCapabilities;\n  /** Free-text instructions surfaced to clients during initialize. */\n  instructions?: string;\n  /**\n   * The protocol revisions this server speaks, NEWEST FIRST.\n   *\n   * `initialize` echoes the client's requested revision when it is in this\n   * list, and answers the first entry otherwise — the spec's rule, which leaves\n   * the client to decide whether it can live with the answer.\n   *\n   * Defaults to `[MCP_PROTOCOL_VERSION]`: one revision, answered whatever the\n   * client asks, which is exactly what this server did before the option\n   * existed. Only list a revision the tools you register are correct under.\n   */\n  protocolVersions?: readonly string[];\n};\n\nexport type Transport = {\n  /** Called by the server when it has a message to deliver to the client. */\n  send: (message: JsonRpcMessage) => void;\n  /** Called by the server when it's torn down so the transport can clean up. */\n  close?: () => void;\n};\n\n/**\n * MicroMcpServer — protocol-level MCP server, transport-agnostic.\n *\n * Use it like:\n *\n *   const server = new MicroMcpServer({ info: { name: \"session\", version: \"0.1\" } });\n *   server.registerTool({ name: \"...\", inputSchema: { type: \"object\" } }, async (args) => ({...}));\n *   const transport = new InProcessTransport();\n *   server.attach(transport);\n *   transport.deliver({ ... }); // client → server frames\n *\n * The same server can serve multiple transports (e.g. an in-process agent\n * AND a relayed external client) by attaching each one.\n */\nexport class MicroMcpServer extends ToolRegistry {\n  private transports = new Set<Transport>();\n  /**\n   * Transports owed a `tools/list_changed` at the end of this tick. Empty when\n   * none is scheduled. See {@link scheduleListChangedNotification}.\n   */\n  private listChangedOwed = new Set<Transport>();\n\n  readonly info: ServerInfo;\n  readonly capabilities: ServerCapabilities;\n  readonly instructions?: string;\n  readonly protocolVersions: readonly string[];\n\n  constructor(options: McpServerOptions) {\n    super();\n    this.info = options.info;\n    this.capabilities = options.capabilities ?? { tools: { listChanged: true } };\n    this.instructions = options.instructions;\n    if (options.protocolVersions && options.protocolVersions.length === 0) {\n      // No answer exists for a client's initialize. Fail here, next to the\n      // mistake, rather than in a handshake nobody is watching.\n      throw new Error(\"MicroMcpServer: protocolVersions is empty — a server must speak at least one protocol revision.\");\n    }\n    this.protocolVersions = options.protocolVersions ? [...options.protocolVersions] : [MCP_PROTOCOL_VERSION];\n  }\n\n  attach(transport: Transport): () => void {\n    this.transports.add(transport);\n    return () => this.detach(transport);\n  }\n\n  detach(transport: Transport): void {\n    if (this.transports.delete(transport)) {\n      transport.close?.();\n    }\n  }\n\n  unregisterTool(name: string): void {\n    if (this.tools.delete(name)) {\n      this.scheduleListChangedNotification();\n    }\n  }\n\n  protected onToolsChanged(): void {\n    this.scheduleListChangedNotification();\n  }\n\n  /**\n   * Receive a JSON-RPC frame from a client (called by the transport).\n   * The transport is responsible for sending the response back.\n   */\n  async receive(transport: Transport, message: JsonRpcMessage): Promise<void> {\n    if (!(\"method\" in message)) return; // It's a response, not a request — ignore.\n\n    const isNotification = !(\"id\" in message);\n    if (isNotification) {\n      // Notifications are fire-and-forget. We ignore unknown methods.\n      return;\n    }\n\n    const request = message as JsonRpcRequest;\n    try {\n      const result = await this.handle(request, transport);\n      transport.send({ jsonrpc: \"2.0\", id: request.id, result });\n    } catch (err) {\n      transport.send({\n        jsonrpc: \"2.0\",\n        id: request.id,\n        error: this.toRpcError(err),\n      });\n    }\n  }\n\n  private async handle(request: JsonRpcRequest, transport: Transport): Promise<any> {\n    const { method, params } = request;\n    switch (method) {\n      case \"initialize\":\n        return {\n          protocolVersion: this.negotiate(params?.protocolVersion),\n          capabilities: this.capabilities,\n          serverInfo: this.info,\n          ...(this.instructions ? { instructions: this.instructions } : {}),\n        };\n\n      case \"tools/list\":\n        return { tools: this.listTools() };\n\n      case \"tools/call\": {\n        const name = params?.name;\n        const args = (params?.arguments ?? {}) as JsonObject;\n        if (typeof name !== \"string\") {\n          throw rpcError(JSONRPC_INVALID_PARAMS, \"tools/call requires `name`\");\n        }\n        const tool = this.tools.get(name);\n        if (!tool) {\n          throw rpcError(JSONRPC_METHOD_NOT_FOUND, this.missingToolMessage(name));\n        }\n        const result = await tool.handler(args, { transport });\n        return result satisfies CallToolResult;\n      }\n\n      case \"ping\":\n        return {};\n\n      default:\n        throw rpcError(JSONRPC_METHOD_NOT_FOUND, `Unsupported method: ${method}`);\n    }\n  }\n\n  /** The revision to answer `initialize` with: the one asked for if spoken, else the newest. */\n  private negotiate(requested: unknown): string {\n    return typeof requested === \"string\" && this.protocolVersions.includes(requested)\n      ? requested\n      : this.protocolVersions[0];\n  }\n\n  /**\n   * Tell the transports that SAW the old tool list that it changed.\n   *\n   * Changes in one tick coalesce into one notification. The recipients are the\n   * transports attached at the moment of a change, not at the moment the\n   * notification goes out: a transport attached afterwards never had the old\n   * list, so \"your list is stale\" is noise to it — and on stdio, where a host\n   * builds the server and attaches stdin/stdout in the same tick, it was the\n   * first frame a client received, before it had even sent `initialize`.\n   */\n  private scheduleListChangedNotification(): void {\n    if (this.transports.size === 0) return;\n    const scheduled = this.listChangedOwed.size > 0;\n    for (const t of this.transports) this.listChangedOwed.add(t);\n    if (scheduled) return;\n    queueMicrotask(() => {\n      const owed = this.listChangedOwed;\n      this.listChangedOwed = new Set();\n      for (const t of owed) {\n        // Detached since the change: it is not listening any more.\n        if (this.transports.has(t)) t.send({ jsonrpc: \"2.0\", method: \"notifications/tools/list_changed\" });\n      }\n    });\n  }\n\n  /** Send an application notification to every client, or one attached transport. */\n  notify(message: JsonRpcMessage, transport?: Transport): void {\n    if (transport) transport.send(message);\n    else this.broadcast(message);\n  }\n\n  private broadcast(message: JsonRpcMessage): void {\n    for (const t of this.transports) t.send(message);\n  }\n\n  private toRpcError(err: unknown): { code: number; message: string; data?: any } {\n    if (err && typeof err === \"object\" && \"code\" in err && \"message\" in err) {\n      return err as any;\n    }\n    return {\n      code: JSONRPC_INTERNAL_ERROR,\n      message: err instanceof Error ? err.message : String(err),\n    };\n  }\n}\n\nexport function rpcError(code: number, message: string, data?: any) {\n  return { code, message, ...(data !== undefined ? { data } : {}) };\n}\n\n/**\n * Helper to build a CallToolResult from a string or structured value.\n */\nexport function textResult(text: string, structured?: any): CallToolResult {\n  return {\n    content: [{ type: \"text\", text }],\n    ...(structured !== undefined ? { structuredContent: structured } : {}),\n  };\n}\n\nexport function errorResult(text: string): CallToolResult {\n  return { content: [{ type: \"text\", text }], isError: true };\n}\n\n// Internal helper so the JsonRpcId import isn't dropped by tsup\ntype _KeepIdImport = JsonRpcId;\n","import type { CallToolResult } from \"../mcp/types\";\nimport { emitActivity } from \"./registry\";\nimport type { AgentTarget } from \"./types\";\n\nexport type ActivityAgent = { id: string; name?: string; color?: string };\n\nexport type ActivityResolverContext<TArgs = Record<string, unknown>> = {\n  /** Tool name as registered. */\n  toolName: string;\n  /** Arguments the tool was called with. */\n  args: TArgs;\n  /** The CallToolResult the underlying handler produced. */\n  result: CallToolResult;\n};\n\n/**\n * Resolves an `AgentTarget` for an executed tool. Bridges declare one of\n * these per registration so the wrapper knows which surface / element /\n * screen the activity belongs to.\n *\n * The resolver runs AFTER the tool handler so it can inspect the result\n * (e.g. read a newly-created item id from `structuredContent`).\n */\nexport type ActivityTargetResolver<TArgs = Record<string, unknown>> = (\n  ctx: ActivityResolverContext<TArgs>,\n) => AgentTarget | null;\n\nexport type ToolHandler<TArgs = Record<string, unknown>> = (\n  args: TArgs,\n) => Promise<CallToolResult> | CallToolResult;\n\n/**\n * wrapToolWithActivity — decorate a bridge tool handler so every successful\n * call emits an `AgentActivityEvent`. Returns a new handler with the same shape.\n *\n * Usage in a bridge:\n *\n *   server.registerTool(\n *     definition,\n *     wrapToolWithActivity(\n *       handler,\n *       { agent, kind: \"whiteboard\", resolveTarget: ({ args }) => ({\n *           kind: \"whiteboard\", elementId: args.id as string,\n *         }) },\n *     ),\n *   );\n */\nexport function wrapToolWithActivity<TArgs = Record<string, unknown>>(\n  handler: ToolHandler<TArgs>,\n  options: {\n    toolName: string;\n    agent: ActivityAgent;\n    /** Optional fancy-screens screen id this bridge is scoped to. */\n    screenId?: string;\n    /** Default target kind if the resolver returns one without `kind`. */\n    kind: AgentTarget[\"kind\"];\n    /** Per-call resolver. Return `null` to skip emitting (e.g. for read-only tools). */\n    resolveTarget?: ActivityTargetResolver<TArgs>;\n    /** Optional ttl override. */\n    ttlMs?: number;\n    /**\n     * Build the `meta` broadcast to all relay peers. Defaults to the tool's full\n     * `structuredContent`. Override to REDACT sensitive fields before fan-out —\n     * e.g. the terminal bridge strips raw command/keystroke bytes so a command\n     * line (or its secrets) is never broadcast verbatim to every peer.\n     */\n    buildMeta?: (result: CallToolResult) => Record<string, unknown> | undefined;\n  },\n): ToolHandler<TArgs> {\n  return async (args) => {\n    const result = await handler(args);\n    if (result.isError) return result;\n\n    let target: AgentTarget | null;\n    if (options.resolveTarget) {\n      target = options.resolveTarget({ toolName: options.toolName, args, result });\n    } else {\n      target = { kind: options.kind, screenId: options.screenId };\n    }\n    if (!target) return result;\n\n    emitActivity({\n      agentId: options.agent.id,\n      agentName: options.agent.name,\n      agentColor: options.agent.color,\n      target: { ...target, kind: target.kind ?? options.kind, screenId: target.screenId ?? options.screenId },\n      action: options.toolName,\n      timestamp: Date.now(),\n      meta: options.buildMeta ? options.buildMeta(result) : extractMeta(result),\n      ttlMs: options.ttlMs,\n    });\n    return result;\n  };\n}\n\nfunction extractMeta(result: CallToolResult): Record<string, unknown> | undefined {\n  const sc = result.structuredContent;\n  if (sc && typeof sc === \"object\" && !Array.isArray(sc)) {\n    return sc as Record<string, unknown>;\n  }\n  return undefined;\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport { readHistory, redoOne, undoOne } from \"./undo-stack\";\n\nexport type UndoToolsOptions = {\n  /** Default agent id when the caller doesn't pass one. */\n  defaultAgentId?: string;\n};\n\n/**\n * Idempotent tracker so multiple bridges on the same server only register\n * agent_undo / agent_redo / agent_history once.\n */\nconst installedHosts = new WeakSet<ToolHost>();\n\n/**\n * The one owner every copy of the undo tools registers under. They are SHARED\n * on purpose — every bridge ensures them, and a host may also call\n * `registerUndoTools` itself — so all of those are the same registrant, and a\n * second registration replaces the first instead of being refused as a\n * collision. Anything else claiming `agent_undo` is still refused.\n */\nconst UNDO_TOOLS_OWNER = \"agent-undo\";\n\n/**\n * ensureUndoToolsRegistered — bridges call this on construction. Safe to\n * call repeatedly with the same server; subsequent calls are no-ops.\n */\nexport function ensureUndoToolsRegistered(host: ToolHost, options: UndoToolsOptions = {}): void {\n  if (installedHosts.has(host)) return;\n  installedHosts.add(host);\n  registerUndoTools(host, options);\n}\n\n/**\n * registerUndoTools — add agent_undo / agent_redo / agent_history to the\n * server. Returns a disposer that unregisters all three.\n */\nexport function registerUndoTools(host: ToolHost, options: UndoToolsOptions = {}): () => void {\n  const defaultAgent = options.defaultAgentId ?? \"agent\";\n  const disposers: Array<() => void> = [];\n  const agentOf = (args: any): string =>\n    typeof args?.agentId === \"string\" ? args.agentId : defaultAgent;\n\n  disposers.push(\n    host.registerTool(\n      {\n        name: \"agent_undo\",\n        description: \"Undo the most recent action on the agent's stack. Optional agentId targets a specific agent.\",\n        inputSchema: {\n          type: \"object\",\n          properties: { agentId: { type: \"string\" } },\n          additionalProperties: false,\n        },\n      },\n      async (args) => {\n        const entry = await undoOne(agentOf(args));\n        if (!entry) return errorResult(\"Nothing to undo.\");\n        return textResult(`Undid: ${entry.label}`, { entry: serialize(entry) });\n      },\n      { owner: UNDO_TOOLS_OWNER },\n    ),\n  );\n\n  disposers.push(\n    host.registerTool(\n      {\n        name: \"agent_redo\",\n        description: \"Redo the most recently undone action.\",\n        inputSchema: {\n          type: \"object\",\n          properties: { agentId: { type: \"string\" } },\n          additionalProperties: false,\n        },\n      },\n      async (args) => {\n        const entry = await redoOne(agentOf(args));\n        if (!entry) return errorResult(\"Nothing to redo.\");\n        return textResult(`Redid: ${entry.label}`, { entry: serialize(entry) });\n      },\n      { owner: UNDO_TOOLS_OWNER },\n    ),\n  );\n\n  disposers.push(\n    host.registerTool(\n      {\n        name: \"agent_history\",\n        description: \"List the agent's undo stack (oldest first). Useful for understanding what's reversible.\",\n        inputSchema: {\n          type: \"object\",\n          properties: { agentId: { type: \"string\" } },\n          additionalProperties: false,\n        },\n      },\n      async (args) => {\n        const history = readHistory(agentOf(args)).map(serialize);\n        const text = history.map((e) => `${new Date(e.timestamp).toISOString()} ${e.bridgeId} ${e.action}: ${e.label}`).join(\"\\n\");\n        return textResult(text || \"(empty)\", history);\n      },\n      { owner: UNDO_TOOLS_OWNER },\n    ),\n  );\n\n  return () => disposers.forEach((d) => d());\n}\n\nfunction serialize(entry: import(\"./undo-stack\").UndoEntry) {\n  return {\n    timestamp: entry.timestamp,\n    bridgeId: entry.bridgeId,\n    action: entry.action,\n    label: entry.label,\n  };\n}\n","import { textResult, errorResult } from \"../mcp/server\";\nimport type { ToolHost } from \"../mcp/tool-host\";\nimport type { JsonObject } from \"../mcp/types\";\nimport type { Bridge } from \"./types\";\nimport { wrapToolWithActivity } from \"../presence/wrap-tool-with-activity\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\nimport type { AgentTarget } from \"../presence/types\";\nimport type { CellValue, SheetData, SheetOp, WorkbookData } from \"@particle-academy/fancy-sheets\";\n\n/**\n * Cell writes funnel through fancy-sheets' own `reduceWorkbook` + `SheetOp` —\n * the same reducer that drives `<SheetWorkbook>` — so agent edits recalculate\n * formulas and land byte-identical to human edits, mirroring how the slides\n * bridge works. Types come straight from the package (no drift); the reducer\n * VALUE is lazy-imported inside the mutation handlers so the package barrel\n * never statically pulls this optional peer (see issue #3).\n */\n\nexport type SheetsBridgeAdapter = {\n  /** fancy-screens screen id (optional) so activity events know which screen the sheet lives in. */\n  screenId?: string;\n  /** Read the current workbook. */\n  getWorkbook: () => WorkbookData;\n  /** Replace the workbook. Host wires this to its onChange. */\n  setWorkbook: (next: WorkbookData) => void;\n  /** Optional: programmatically change the active cell. */\n  setActiveCell?: (sheetId: string, address: string) => void;\n};\n\nexport type SheetsBridgeOptions = {\n  adapter: SheetsBridgeAdapter;\n  agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\n/**\n * registerSheetsBridge — schema-aware MCP access to a fancy-sheets workbook.\n * Tools are sheet-aware (every mutator takes an explicit `sheet` id, defaulting\n * to the active sheet when omitted) so an agent can author multi-sheet docs.\n */\nexport function registerSheetsBridge(\n  host: ToolHost,\n  options: SheetsBridgeOptions,\n): Bridge {\n  const { adapter } = options;\n  const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n  const disposers: Array<() => void> = [];\n  // The bridge id is also its registrant identity on the host: the same bridge\n  // may re-register (a remount), a different one claiming a name is refused.\n  const bridgeId = \"sheets\";\n\n  // agent_undo / agent_redo / agent_history are registered whenever any bridge\n  // mounts, so undo availability doesn't hinge on which bridges are co-present.\n  ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n  const target = (sheetId: string, address?: string): AgentTarget => ({\n    kind: \"sheet\",\n    screenId: adapter.screenId,\n    elementId: address ? `${sheetId}!${address}` : sheetId,\n    label: address ? `${sheetId}!${address}` : sheetId,\n  });\n\n  const reg = (\n    name: string,\n    description: string,\n    properties: Record<string, unknown>,\n    required: string[],\n    handler: (args: JsonObject) => Promise<any> | any,\n    isMutation: boolean,\n    resolveTarget?: (args: JsonObject, result: any) => AgentTarget | null,\n  ) => {\n    const wrapped = async (args: JsonObject) => {\n      try {\n        return await handler(args);\n      } catch (e) {\n        return errorResult(e instanceof Error ? e.message : String(e));\n      }\n    };\n    const final = isMutation\n      ? wrapToolWithActivity(wrapped, {\n          toolName: name,\n          agent,\n          kind: \"sheet\",\n          screenId: adapter.screenId,\n          resolveTarget: ({ args, result }) =>\n            resolveTarget?.(args, result) ?? target(getSheetId(args)),\n        })\n      : wrapped;\n    disposers.push(\n      host.registerTool(\n        {\n          name,\n          description,\n          inputSchema: { type: \"object\", properties: properties as any, required, additionalProperties: false },\n        },\n        final as any,\n        { owner: bridgeId },\n      ),\n    );\n  };\n\n  function activeSheetId(): string {\n    return adapter.getWorkbook().activeSheetId;\n  }\n  function getSheetId(args: JsonObject): string {\n    return typeof args.sheet === \"string\" ? args.sheet : activeSheetId();\n  }\n  function getSheet(workbook: WorkbookData, sheetId: string): SheetData | undefined {\n    return workbook.sheets.find((s) => s.id === sheetId);\n  }\n\n  // ───────────── Read tools ─────────────\n\n  reg(\n    \"sheet_describe\",\n    \"Describe the workbook: every sheet's id, name, dimensions, cell count, active sheet. Call before reading or writing.\",\n    {},\n    [],\n    () => {\n      const wb = adapter.getWorkbook();\n      const summary = {\n        activeSheetId: wb.activeSheetId,\n        sheets: wb.sheets.map((s) => ({\n          id: s.id,\n          name: s.name,\n          cellCount: Object.keys(s.cells).length,\n          columnCount: Object.keys(s.columnWidths).length,\n          frozenRows: s.frozenRows,\n          frozenCols: s.frozenCols,\n        })),\n      };\n      const text = `Active: ${summary.activeSheetId}\\n` + summary.sheets\n        .map((s) => `${s.id} \"${s.name}\" — ${s.cellCount} cells`)\n        .join(\"\\n\");\n      return textResult(text, summary);\n    },\n    false,\n  );\n\n  reg(\n    \"sheet_get_cell\",\n    \"Read a single cell's raw + computed value.\",\n    {\n      sheet: { type: \"string\", description: \"Sheet id (defaults to active).\" },\n      address: { type: \"string\", description: \"A1-style address, e.g. \\\"B12\\\".\" },\n    },\n    [\"address\"],\n    (args) => {\n      const sheetId = getSheetId(args);\n      const address = String(args.address);\n      const sheet = getSheet(adapter.getWorkbook(), sheetId);\n      if (!sheet) return errorResult(`No sheet ${sheetId}`);\n      const cell = sheet.cells[address];\n      if (!cell) {\n        return textResult(`(empty)`, { sheet: sheetId, address, value: null });\n      }\n      return textResult(`${address} = ${JSON.stringify(cell.computedValue ?? cell.value)}`, { ...cell, sheet: sheetId, address });\n    },\n    false,\n  );\n\n  reg(\n    \"sheet_get_range\",\n    \"Read a rectangular range as a 2D array of values.\",\n    {\n      sheet: { type: \"string\" },\n      start: { type: \"string\", description: \"Top-left A1 address.\" },\n      end: { type: \"string\", description: \"Bottom-right A1 address.\" },\n    },\n    [\"start\", \"end\"],\n    (args) => {\n      const sheetId = getSheetId(args);\n      const sheet = getSheet(adapter.getWorkbook(), sheetId);\n      if (!sheet) return errorResult(`No sheet ${sheetId}`);\n      const grid = readRange(sheet, String(args.start), String(args.end));\n      return textResult(JSON.stringify(grid), { sheet: sheetId, start: args.start, end: args.end, values: grid });\n    },\n    false,\n  );\n\n  // ───────────── Mutation tools ─────────────\n\n  reg(\n    \"sheet_set_cell\",\n    \"Set a single cell's value. To set a formula, pass a string starting with '='.\",\n    {\n      sheet: { type: \"string\" },\n      address: { type: \"string\" },\n      value: { description: \"string | number | boolean | null. Strings starting with '=' are stored as formulas.\" },\n    },\n    [\"address\", \"value\"],\n    async (args) => {\n      const sheetId = getSheetId(args);\n      const address = String(args.address);\n      const value = args.value as CellValue;\n      const wb = adapter.getWorkbook();\n      if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n      const { reduceWorkbook } = await import(\"@particle-academy/fancy-sheets\");\n      adapter.setWorkbook(reduceWorkbook(wb, setCellOp(sheetId, address, value)));\n      return textResult(`${sheetId}!${address} ← ${JSON.stringify(value)}`, { sheet: sheetId, address, value });\n    },\n    true,\n    (args) => target(getSheetId(args), String(args.address ?? \"\")),\n  );\n\n  reg(\n    \"sheet_set_range\",\n    \"Set many cells atomically. `cells` is an object map of { \\\"A1\\\": value, \\\"B2\\\": value, ... }.\",\n    {\n      sheet: { type: \"string\" },\n      cells: { type: \"object\" },\n    },\n    [\"cells\"],\n    async (args) => {\n      const sheetId = getSheetId(args);\n      const wb = adapter.getWorkbook();\n      if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n      const cells = (args.cells && typeof args.cells === \"object\") ? args.cells as Record<string, CellValue> : {};\n      const { reduceWorkbook } = await import(\"@particle-academy/fancy-sheets\");\n      let next = wb;\n      for (const [addr, v] of Object.entries(cells)) next = reduceWorkbook(next, setCellOp(sheetId, addr, v));\n      adapter.setWorkbook(next);\n      return textResult(`Set ${Object.keys(cells).length} cells in ${sheetId}`, { sheet: sheetId, count: Object.keys(cells).length });\n    },\n    true,\n  );\n\n  reg(\n    \"sheet_add_sheet\",\n    \"Add a new sheet (tab) to the workbook.\",\n    { id: { type: \"string\" }, name: { type: \"string\" } },\n    [\"id\", \"name\"],\n    (args) => {\n      const wb = adapter.getWorkbook();\n      const id = String(args.id);\n      const name = String(args.name);\n      if (wb.sheets.find((s) => s.id === id)) return errorResult(`Sheet ${id} already exists`);\n      const next: WorkbookData = {\n        ...wb,\n        sheets: [\n          ...wb.sheets,\n          {\n            id, name, cells: {}, columnWidths: {}, mergedRegions: [],\n            columnFilters: {}, frozenRows: 0, frozenCols: 0,\n          },\n        ],\n      };\n      adapter.setWorkbook(next);\n      return textResult(`Added sheet ${id} (\"${name}\")`, { id, name });\n    },\n    true,\n    (args) => target(String(args.id ?? \"\")),\n  );\n\n  reg(\n    \"sheet_set_active\",\n    \"Switch to a different sheet tab.\",\n    { sheet: { type: \"string\" } },\n    [\"sheet\"],\n    (args) => {\n      const sheetId = String(args.sheet);\n      const wb = adapter.getWorkbook();\n      if (!getSheet(wb, sheetId)) return errorResult(`No sheet ${sheetId}`);\n      adapter.setWorkbook({ ...wb, activeSheetId: sheetId });\n      return textResult(`Active sheet → ${sheetId}`, { sheet: sheetId });\n    },\n    true,\n  );\n\n  reg(\n    \"sheet_set_active_cell\",\n    \"Move the active cell selection (host implements DOM focus + scroll).\",\n    { sheet: { type: \"string\" }, address: { type: \"string\" } },\n    [\"address\"],\n    (args) => {\n      if (!adapter.setActiveCell) return errorResult(\"Host did not provide setActiveCell.\");\n      const sheetId = getSheetId(args);\n      adapter.setActiveCell(sheetId, String(args.address));\n      return textResult(`Active cell → ${sheetId}!${args.address}`, { sheet: sheetId, address: args.address });\n    },\n    true,\n    (args) => target(getSheetId(args), String(args.address ?? \"\")),\n  );\n\n  return {\n    id: bridgeId,\n    title: \"Sheets\",\n    dispose: () => {\n      for (const d of disposers) d();\n    },\n  };\n}\n\n// ───────────── helpers ─────────────\n\n/** Build a `set_cell` op, treating a leading-\"=\" string as a formula — matching\n *  the in-app editor (value keeps the raw \"=…\"; formula drops the \"=\"). */\nfunction setCellOp(sheet: string, address: string, value: CellValue): SheetOp {\n  if (typeof value === \"string\" && value.startsWith(\"=\")) {\n    return { type: \"set_cell\", sheet, address, value, formula: value.slice(1) };\n  }\n  return { type: \"set_cell\", sheet, address, value };\n}\n\n/** Parse \"B12\" → { col: 1, row: 11 }. Letters are 1-based, rows 1-based. */\nfunction parseAddress(addr: string): { col: number; row: number } {\n  const m = /^([A-Za-z]+)(\\d+)$/.exec(addr.trim());\n  if (!m) throw new Error(`Bad address: ${addr}`);\n  const letters = m[1].toUpperCase();\n  let col = 0;\n  for (let i = 0; i < letters.length; i++) {\n    col = col * 26 + (letters.charCodeAt(i) - 64);\n  }\n  return { col: col - 1, row: parseInt(m[2], 10) - 1 };\n}\n\nfunction colToLetter(col: number): string {\n  let s = \"\";\n  let n = col + 1;\n  while (n > 0) {\n    const r = (n - 1) % 26;\n    s = String.fromCharCode(65 + r) + s;\n    n = Math.floor((n - 1) / 26);\n  }\n  return s;\n}\n\nfunction readRange(sheet: SheetData, startAddr: string, endAddr: string): CellValue[][] {\n  const start = parseAddress(startAddr);\n  const end = parseAddress(endAddr);\n  const r0 = Math.min(start.row, end.row);\n  const r1 = Math.max(start.row, end.row);\n  const c0 = Math.min(start.col, end.col);\n  const c1 = Math.max(start.col, end.col);\n  const grid: CellValue[][] = [];\n  for (let r = r0; r <= r1; r++) {\n    const row: CellValue[] = [];\n    for (let c = c0; c <= c1; c++) {\n      const addr = `${colToLetter(c)}${r + 1}`;\n      const cell = sheet.cells[addr];\n      row.push(cell?.computedValue ?? cell?.value ?? null);\n    }\n    grid.push(row);\n  }\n  return grid;\n}\n"]}