@particle-academy/agent-integrations 0.43.0 → 0.45.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 (180) hide show
  1. package/README.md +32 -0
  2. package/dist/bridges/artboard.d.cts +3 -3
  3. package/dist/bridges/artboard.d.ts +3 -3
  4. package/dist/bridges/catalog.d.cts +3 -3
  5. package/dist/bridges/catalog.d.ts +3 -3
  6. package/dist/bridges/charts.d.cts +3 -3
  7. package/dist/bridges/charts.d.ts +3 -3
  8. package/dist/bridges/cms.d.cts +3 -3
  9. package/dist/bridges/cms.d.ts +3 -3
  10. package/dist/bridges/code.d.cts +3 -3
  11. package/dist/bridges/code.d.ts +3 -3
  12. package/dist/bridges/doc.d.cts +3 -3
  13. package/dist/bridges/doc.d.ts +3 -3
  14. package/dist/bridges/features.d.cts +3 -3
  15. package/dist/bridges/features.d.ts +3 -3
  16. package/dist/bridges/files.d.cts +3 -3
  17. package/dist/bridges/files.d.ts +3 -3
  18. package/dist/bridges/flow.d.cts +3 -3
  19. package/dist/bridges/flow.d.ts +3 -3
  20. package/dist/bridges/forms.d.cts +3 -3
  21. package/dist/bridges/forms.d.ts +3 -3
  22. package/dist/bridges/git.d.cts +3 -3
  23. package/dist/bridges/git.d.ts +3 -3
  24. package/dist/bridges/grid.d.cts +3 -3
  25. package/dist/bridges/grid.d.ts +3 -3
  26. package/dist/bridges/map.d.cts +3 -3
  27. package/dist/bridges/map.d.ts +3 -3
  28. package/dist/bridges/passkeys.d.cts +3 -3
  29. package/dist/bridges/passkeys.d.ts +3 -3
  30. package/dist/bridges/scene.d.cts +3 -3
  31. package/dist/bridges/scene.d.ts +3 -3
  32. package/dist/bridges/screens.d.cts +3 -3
  33. package/dist/bridges/screens.d.ts +3 -3
  34. package/dist/bridges/sheets.d.cts +3 -3
  35. package/dist/bridges/sheets.d.ts +3 -3
  36. package/dist/bridges/slides.d.cts +3 -3
  37. package/dist/bridges/slides.d.ts +3 -3
  38. package/dist/bridges/terminal.d.cts +3 -3
  39. package/dist/bridges/terminal.d.ts +3 -3
  40. package/dist/bridges/tui.d.cts +2 -2
  41. package/dist/bridges/tui.d.ts +2 -2
  42. package/dist/bridges/whiteboard.d.cts +3 -3
  43. package/dist/bridges/whiteboard.d.ts +3 -3
  44. package/dist/bridges-artboard.cjs.map +1 -1
  45. package/dist/bridges-artboard.js +2 -2
  46. package/dist/bridges-catalog.cjs.map +1 -1
  47. package/dist/bridges-catalog.js +3 -3
  48. package/dist/bridges-charts.cjs.map +1 -1
  49. package/dist/bridges-charts.js +3 -3
  50. package/dist/bridges-cms.cjs.map +1 -1
  51. package/dist/bridges-cms.js +4 -4
  52. package/dist/bridges-code.cjs.map +1 -1
  53. package/dist/bridges-code.js +3 -3
  54. package/dist/bridges-doc.cjs.map +1 -1
  55. package/dist/bridges-doc.js +3 -3
  56. package/dist/bridges-features.cjs.map +1 -1
  57. package/dist/bridges-features.js +3 -3
  58. package/dist/bridges-files.cjs.map +1 -1
  59. package/dist/bridges-files.js +3 -3
  60. package/dist/bridges-flow.cjs.map +1 -1
  61. package/dist/bridges-flow.js +2 -2
  62. package/dist/bridges-forms.cjs.map +1 -1
  63. package/dist/bridges-forms.js +3 -3
  64. package/dist/bridges-git.cjs.map +1 -1
  65. package/dist/bridges-git.js +3 -3
  66. package/dist/bridges-grid.cjs.map +1 -1
  67. package/dist/bridges-grid.js +3 -3
  68. package/dist/bridges-map.cjs.map +1 -1
  69. package/dist/bridges-map.js +3 -3
  70. package/dist/bridges-passkeys.cjs.map +1 -1
  71. package/dist/bridges-passkeys.js +3 -3
  72. package/dist/bridges-scene.cjs.map +1 -1
  73. package/dist/bridges-scene.js +3 -3
  74. package/dist/bridges-screens.cjs.map +1 -1
  75. package/dist/bridges-screens.js +3 -3
  76. package/dist/bridges-sheets.cjs.map +1 -1
  77. package/dist/bridges-sheets.js +3 -3
  78. package/dist/bridges-slides.cjs.map +1 -1
  79. package/dist/bridges-slides.js +3 -3
  80. package/dist/bridges-terminal.cjs.map +1 -1
  81. package/dist/bridges-terminal.js +3 -3
  82. package/dist/bridges-tui.cjs.map +1 -1
  83. package/dist/bridges-tui.js +2 -2
  84. package/dist/bridges-whiteboard.cjs.map +1 -1
  85. package/dist/bridges-whiteboard.js +3 -3
  86. package/dist/{chunk-5W6YOXLT.js → chunk-36MKPTVD.js} +4 -4
  87. package/dist/{chunk-5W6YOXLT.js.map → chunk-36MKPTVD.js.map} +1 -1
  88. package/dist/{chunk-SXVRIIXW.js → chunk-3HVYUMQF.js} +4 -4
  89. package/dist/{chunk-SXVRIIXW.js.map → chunk-3HVYUMQF.js.map} +1 -1
  90. package/dist/{chunk-MZ74LLDS.js → chunk-3UUF5KKZ.js} +4 -4
  91. package/dist/{chunk-MZ74LLDS.js.map → chunk-3UUF5KKZ.js.map} +1 -1
  92. package/dist/{chunk-WEXMZMJH.js → chunk-3WVXAB3D.js} +3 -3
  93. package/dist/{chunk-WEXMZMJH.js.map → chunk-3WVXAB3D.js.map} +1 -1
  94. package/dist/{chunk-Z4L2GOAK.js → chunk-5ZWNCHZS.js} +4 -4
  95. package/dist/{chunk-Z4L2GOAK.js.map → chunk-5ZWNCHZS.js.map} +1 -1
  96. package/dist/{chunk-TEB5U6Y5.js → chunk-7NVATRLE.js} +4 -4
  97. package/dist/{chunk-TEB5U6Y5.js.map → chunk-7NVATRLE.js.map} +1 -1
  98. package/dist/{chunk-PUMQDV67.js → chunk-AXWMWYH5.js} +4 -4
  99. package/dist/{chunk-PUMQDV67.js.map → chunk-AXWMWYH5.js.map} +1 -1
  100. package/dist/{chunk-NKAH67JK.js → chunk-CS3CHGYC.js} +4 -4
  101. package/dist/{chunk-NKAH67JK.js.map → chunk-CS3CHGYC.js.map} +1 -1
  102. package/dist/{chunk-QJYRWEXD.js → chunk-CZV3WUW5.js} +35 -8
  103. package/dist/chunk-CZV3WUW5.js.map +1 -0
  104. package/dist/{chunk-PCFRBVKS.js → chunk-FCXSR7I5.js} +4 -4
  105. package/dist/{chunk-PCFRBVKS.js.map → chunk-FCXSR7I5.js.map} +1 -1
  106. package/dist/{chunk-NIFPRC7P.js → chunk-GVTBMJU6.js} +4 -4
  107. package/dist/{chunk-NIFPRC7P.js.map → chunk-GVTBMJU6.js.map} +1 -1
  108. package/dist/{chunk-E2I3YVKC.js → chunk-JLHVQWOV.js} +3 -3
  109. package/dist/{chunk-E2I3YVKC.js.map → chunk-JLHVQWOV.js.map} +1 -1
  110. package/dist/{chunk-2LSU3NFO.js → chunk-LQB42OSA.js} +4 -4
  111. package/dist/{chunk-2LSU3NFO.js.map → chunk-LQB42OSA.js.map} +1 -1
  112. package/dist/{chunk-VJD3Y7E5.js → chunk-MIDZWKIF.js} +4 -4
  113. package/dist/{chunk-VJD3Y7E5.js.map → chunk-MIDZWKIF.js.map} +1 -1
  114. package/dist/{chunk-QOANLXSW.js → chunk-OZBUPO4K.js} +110 -8
  115. package/dist/chunk-OZBUPO4K.js.map +1 -0
  116. package/dist/{chunk-LOD77NCD.js → chunk-PWYEW6NL.js} +4 -4
  117. package/dist/{chunk-LOD77NCD.js.map → chunk-PWYEW6NL.js.map} +1 -1
  118. package/dist/{chunk-HVDHT7DM.js → chunk-R4XXOGQH.js} +3 -3
  119. package/dist/{chunk-HVDHT7DM.js.map → chunk-R4XXOGQH.js.map} +1 -1
  120. package/dist/{chunk-7LLMILTM.js → chunk-RVMM4BHK.js} +4 -4
  121. package/dist/{chunk-7LLMILTM.js.map → chunk-RVMM4BHK.js.map} +1 -1
  122. package/dist/{chunk-NIXOY473.js → chunk-SWWJUOCY.js} +3 -3
  123. package/dist/{chunk-NIXOY473.js.map → chunk-SWWJUOCY.js.map} +1 -1
  124. package/dist/{chunk-EIBV76IB.js → chunk-VFWFT3OK.js} +4 -4
  125. package/dist/{chunk-EIBV76IB.js.map → chunk-VFWFT3OK.js.map} +1 -1
  126. package/dist/{chunk-2Q4EGZHJ.js → chunk-VMRUW4B4.js} +4 -4
  127. package/dist/{chunk-2Q4EGZHJ.js.map → chunk-VMRUW4B4.js.map} +1 -1
  128. package/dist/{chunk-GT63LSPJ.js → chunk-VOCUGTZB.js} +4 -4
  129. package/dist/{chunk-GT63LSPJ.js.map → chunk-VOCUGTZB.js.map} +1 -1
  130. package/dist/{chunk-N5VOPV64.js → chunk-Z5NL5D4J.js} +4 -4
  131. package/dist/{chunk-N5VOPV64.js.map → chunk-Z5NL5D4J.js.map} +1 -1
  132. package/dist/components-shared-whiteboard.cjs +33 -6
  133. package/dist/components-shared-whiteboard.cjs.map +1 -1
  134. package/dist/components-shared-whiteboard.js +3 -3
  135. package/dist/index.cjs +33 -6
  136. package/dist/index.cjs.map +1 -1
  137. package/dist/index.d.cts +7 -7
  138. package/dist/index.d.ts +7 -7
  139. package/dist/index.js +27 -27
  140. package/dist/mcp/index.d.cts +5 -5
  141. package/dist/mcp/index.d.ts +5 -5
  142. package/dist/mcp/stdio.d.cts +94 -0
  143. package/dist/mcp/stdio.d.ts +94 -0
  144. package/dist/mcp-stdio.cjs +120 -0
  145. package/dist/mcp-stdio.cjs.map +1 -0
  146. package/dist/mcp-stdio.js +117 -0
  147. package/dist/mcp-stdio.js.map +1 -0
  148. package/dist/mcp.cjs +33 -6
  149. package/dist/mcp.cjs.map +1 -1
  150. package/dist/mcp.js +1 -1
  151. package/dist/presence/index.d.cts +1 -1
  152. package/dist/presence/index.d.ts +1 -1
  153. package/dist/relay-server/index.d.cts +44 -2
  154. package/dist/relay-server/index.d.ts +44 -2
  155. package/dist/relay-server-cli.cjs +108 -6
  156. package/dist/relay-server-cli.cjs.map +1 -1
  157. package/dist/relay-server-cli.js +1 -1
  158. package/dist/relay-server.cjs +108 -6
  159. package/dist/relay-server.cjs.map +1 -1
  160. package/dist/relay-server.js +1 -1
  161. package/dist/{server-BJNF7pQe.d.cts → server-BIcA3ZtK.d.cts} +32 -3
  162. package/dist/{server-Dt97UxuD.d.ts → server-DnUyeavY.d.ts} +32 -3
  163. package/dist/sharing/index.d.cts +3 -3
  164. package/dist/sharing/index.d.ts +3 -3
  165. package/dist/sheets-adapter.d.cts +3 -3
  166. package/dist/sheets-adapter.d.ts +3 -3
  167. package/dist/{tool-host-BpEBqf5u.d.cts → tool-host-LVBgCN5m.d.cts} +1 -1
  168. package/dist/{tool-host-xY5F-eqG.d.ts → tool-host-Wo0pkY83.d.ts} +1 -1
  169. package/dist/{types-DSwsNTBG.d.ts → types-BxNRKSVd.d.ts} +1 -1
  170. package/dist/{types-C58ZXs4K.d.cts → types-C2DtnHIn.d.cts} +25 -1
  171. package/dist/{types-C58ZXs4K.d.ts → types-C2DtnHIn.d.ts} +25 -1
  172. package/dist/{types-C4NaIW6B.d.cts → types-EcElKOlk.d.cts} +1 -1
  173. package/dist/undo/index.d.cts +2 -2
  174. package/dist/undo/index.d.ts +2 -2
  175. package/dist/undo.cjs.map +1 -1
  176. package/dist/undo.js +3 -3
  177. package/docs/relay-protocol.md +33 -0
  178. package/package.json +13 -2
  179. package/dist/chunk-QJYRWEXD.js.map +0 -1
  180. package/dist/chunk-QOANLXSW.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mcp/server.ts","../src/presence/wrap-tool-with-activity.ts","../src/undo/undo-tools.ts","../src/bridges/map.ts"],"names":["emitActivity","undoOne","redoOne","readHistory","pushUndoEntry"],"mappings":"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","file":"bridges-map.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\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 private notifyListChangedScheduled = false;\n\n readonly info: ServerInfo;\n readonly capabilities: ServerCapabilities;\n readonly instructions?: 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 }\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: MCP_PROTOCOL_VERSION,\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 private scheduleListChangedNotification(): void {\n if (this.notifyListChangedScheduled) return;\n this.notifyListChangedScheduled = true;\n queueMicrotask(() => {\n this.notifyListChangedScheduled = false;\n this.broadcast({ jsonrpc: \"2.0\", method: \"notifications/tools/list_changed\" });\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 * 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 ),\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 ),\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 ),\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","// Loose types so this bridge builds standalone without a hard dep on\n// @particle-academy/fancy-map. Hosts that use fancy-map pass its own\n// MapMarker / MapView values straight through — the shapes match.\ntype LatLng = { lat: number; lng: number };\ntype MapView = { center: LatLng; zoom: number; bearing?: number; pitch?: number };\ntype MapMarker = {\n id: string;\n position: LatLng;\n label?: string;\n color?: string;\n icon?: string;\n draggable?: boolean;\n data?: Record<string, unknown>;\n};\n\nimport { 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 type { AgentTarget as MapAgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * Adapter the host provides — getters/setters over the SAME controlled state it\n * passes to fancy-map's `<Map>` (view, markers, selection), plus optional\n * `fitBounds` (from the map's onReady handle) and `setFollow` (drives the map's\n * `follow` prop so an agent can make the camera track a moving marker).\n */\nexport type MapBridgeAdapter = {\n getView: () => MapView;\n setView: (next: MapView) => void;\n getMarkers: () => MapMarker[];\n setMarkers: (next: MapMarker[] | ((prev: MapMarker[]) => MapMarker[])) => void;\n getSelected: () => string | null;\n setSelected: (id: string | null) => void;\n /** Fit the camera to points (wire to the `MapHandle.fitBounds` from `<Map onReady>`). */\n fitBounds?: (points: LatLng[], padding?: number) => void;\n /** Make the camera follow a marker as it moves (drives the map's `follow` prop). */\n setFollow?: (id: string | null) => void;\n};\n\nexport type MapBridgeOptions = {\n adapter: MapBridgeAdapter;\n /** Identity tagged onto agent-authored markers. */\n agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\nconst num = (v: unknown, fallback?: number): number =>\n typeof v === \"number\" && Number.isFinite(v) ? v : fallback ?? 0;\nconst str = (v: unknown, fallback = \"\"): string => (typeof v === \"string\" ? v : fallback);\nconst newId = (prefix: string) =>\n `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;\n\n/**\n * registerMapBridge — an MCP tool set over a fancy-map `<Map>`'s controlled\n * state, so a human and an agent cohabit one map. The agent moves the camera,\n * drops/updates/removes markers, selects, fits bounds, and follows a live\n * track; every mutation broadcasts AgentActivity (for presence) and pushes an\n * undo entry (so the human can step the agent back). Mirrors the whiteboard /\n * flow bridges in shape.\n */\nexport function registerMapBridge(host: ToolHost, options: MapBridgeOptions): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const disposers: Array<() => void> = [];\n\n // Register agent_undo / agent_redo / agent_history once per host. Idempotent.\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const mTarget = (args: any, result: any): MapAgentTarget => ({\n kind: \"map\",\n elementId:\n (result?.structuredContent?.id as string | undefined) ?? (args?.id as string | undefined),\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 resolveTarget?: (args: JsonObject, result: any) => MapAgentTarget | 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 = resolveTarget\n ? wrapToolWithActivity(wrapped, {\n toolName: name,\n agent: { id: agent.id, name: agent.name, color: agent.color },\n kind: \"map\",\n resolveTarget: ({ args, result }) => resolveTarget(args, result),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: {\n type: \"object\",\n properties: properties as any,\n required,\n additionalProperties: false,\n },\n },\n final as any,\n ),\n );\n };\n\n // ───────────── Read ─────────────\n\n reg(\"map_get_state\", \"Get the map's camera, markers, and current selection.\", {}, [], () => {\n const state = {\n view: adapter.getView(),\n markers: adapter.getMarkers(),\n selectedId: adapter.getSelected(),\n };\n return textResult(JSON.stringify(state, null, 2), state);\n });\n\n // ───────────── Camera ─────────────\n\n reg(\n \"map_set_view\",\n \"Move the camera to an absolute position. Any omitted field is left unchanged.\",\n {\n lat: { type: \"number\", description: \"New center latitude.\" },\n lng: { type: \"number\", description: \"New center longitude.\" },\n zoom: { type: \"number\", description: \"New zoom level (higher = closer).\" },\n },\n [],\n (args) => {\n const prev = adapter.getView();\n const next: MapView = {\n center: {\n lat: args.lat !== undefined ? num(args.lat) : prev.center.lat,\n lng: args.lng !== undefined ? num(args.lng) : prev.center.lng,\n },\n zoom: args.zoom !== undefined ? num(args.zoom) : prev.zoom,\n };\n adapter.setView(next);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_set_view\",\n label: `Moved camera to ${next.center.lat.toFixed(4)},${next.center.lng.toFixed(4)} z${next.zoom}`,\n undo: () => adapter.setView(prev),\n redo: () => adapter.setView(next),\n });\n return textResult(`Camera → ${next.center.lat.toFixed(4)},${next.center.lng.toFixed(4)} z${next.zoom}`, next);\n },\n mTarget,\n );\n\n reg(\n \"map_pan\",\n \"Pan the camera by a relative offset in degrees (positive dLat = north, positive dLng = east).\",\n { dLat: { type: \"number\" }, dLng: { type: \"number\" } },\n [],\n (args) => {\n const prev = adapter.getView();\n const next: MapView = {\n ...prev,\n center: { lat: prev.center.lat + num(args.dLat), lng: prev.center.lng + num(args.dLng) },\n };\n adapter.setView(next);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_pan\",\n label: \"Panned camera\",\n undo: () => adapter.setView(prev),\n redo: () => adapter.setView(next),\n });\n return textResult(`Panned to ${next.center.lat.toFixed(4)},${next.center.lng.toFixed(4)}`, next);\n },\n mTarget,\n );\n\n reg(\n \"map_zoom\",\n \"Zoom the camera by a relative delta (e.g. +1 zooms in one level, -2 out two).\",\n { delta: { type: \"number\" } },\n [\"delta\"],\n (args) => {\n const prev = adapter.getView();\n const next: MapView = { ...prev, zoom: prev.zoom + num(args.delta) };\n adapter.setView(next);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_zoom\",\n label: `Zoom → ${next.zoom}`,\n undo: () => adapter.setView(prev),\n redo: () => adapter.setView(next),\n });\n return textResult(`Zoom → ${next.zoom}`, next);\n },\n );\n\n reg(\n \"map_fit_bounds\",\n \"Fit the camera to enclose points. Pass `points`, or omit to fit all current markers.\",\n {\n points: {\n type: \"array\",\n description: \"Points to enclose, e.g. [{lat,lng},…].\",\n items: {\n type: \"object\",\n properties: { lat: { type: \"number\" }, lng: { type: \"number\" } },\n required: [\"lat\", \"lng\"],\n },\n },\n padding: { type: \"number\", description: \"Padding in pixels (default 40).\" },\n },\n [],\n (args) => {\n if (!adapter.fitBounds) {\n return errorResult(\"Host did not wire fitBounds (pass the <Map onReady> handle's fitBounds).\");\n }\n const points: LatLng[] = Array.isArray(args.points)\n ? (args.points as any[]).map((p) => ({ lat: num(p?.lat), lng: num(p?.lng) }))\n : adapter.getMarkers().map((m) => m.position);\n if (!points.length) {\n return errorResult(\"No points to fit (map has no markers).\");\n }\n adapter.fitBounds(points, args.padding !== undefined ? num(args.padding) : undefined);\n return textResult(`Fit camera to ${points.length} point(s).`);\n },\n );\n\n // ───────────── Markers ─────────────\n\n reg(\n \"map_add_marker\",\n \"Drop a marker. `id` is optional (auto-generated); `icon` is an emoji or 1–2 chars.\",\n {\n id: { type: \"string\" },\n lat: { type: \"number\" },\n lng: { type: \"number\" },\n label: { type: \"string\" },\n color: { type: \"string\", description: \"CSS color, e.g. #2563eb.\" },\n icon: { type: \"string\", description: \"Emoji / short text in the pin.\" },\n draggable: { type: \"boolean\" },\n data: { type: \"object\", description: \"Arbitrary JSON payload carried with the marker.\" },\n },\n [\"lat\", \"lng\"],\n (args) => {\n const id = args.id ? str(args.id) : newId(\"m\");\n if (adapter.getMarkers().some((m) => m.id === id)) {\n return errorResult(`A marker with id ${id} already exists — use map_update_marker.`);\n }\n const marker: MapMarker = {\n id,\n position: { lat: num(args.lat), lng: num(args.lng) },\n ...(args.label !== undefined ? { label: str(args.label) } : {}),\n ...(args.color !== undefined ? { color: str(args.color) } : {}),\n ...(args.icon !== undefined ? { icon: str(args.icon) } : {}),\n ...(args.draggable !== undefined ? { draggable: !!args.draggable } : {}),\n ...(args.data && typeof args.data === \"object\"\n ? { data: args.data as Record<string, unknown> }\n : {}),\n };\n adapter.setMarkers((all) => [...all, marker]);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_add_marker\",\n label: `Added marker ${id}`,\n undo: () => adapter.setMarkers((all) => all.filter((m) => m.id !== id)),\n redo: () => adapter.setMarkers((all) => [...all, marker]),\n });\n return textResult(`Added marker ${id} at ${marker.position.lat.toFixed(4)},${marker.position.lng.toFixed(4)}`, marker);\n },\n mTarget,\n );\n\n reg(\n \"map_update_marker\",\n \"Update a marker. Only provided fields change — update lat/lng repeatedly to drive a live track.\",\n {\n id: { type: \"string\" },\n lat: { type: \"number\" },\n lng: { type: \"number\" },\n label: { type: \"string\" },\n color: { type: \"string\" },\n icon: { type: \"string\" },\n draggable: { type: \"boolean\" },\n },\n [\"id\"],\n (args) => {\n const id = str(args.id);\n const prev = adapter.getMarkers().find((m) => m.id === id);\n if (!prev) {\n return errorResult(`No marker with id ${id}`);\n }\n const next: MapMarker = {\n ...prev,\n position: {\n lat: args.lat !== undefined ? num(args.lat) : prev.position.lat,\n lng: args.lng !== undefined ? num(args.lng) : prev.position.lng,\n },\n ...(args.label !== undefined ? { label: str(args.label) } : {}),\n ...(args.color !== undefined ? { color: str(args.color) } : {}),\n ...(args.icon !== undefined ? { icon: str(args.icon) } : {}),\n ...(args.draggable !== undefined ? { draggable: !!args.draggable } : {}),\n };\n adapter.setMarkers((all) => all.map((m) => (m.id === id ? next : m)));\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_update_marker\",\n label: `Updated marker ${id}`,\n undo: () => adapter.setMarkers((all) => all.map((m) => (m.id === id ? prev : m))),\n redo: () => adapter.setMarkers((all) => all.map((m) => (m.id === id ? next : m))),\n });\n return textResult(`Updated marker ${id}`, next);\n },\n mTarget,\n );\n\n reg(\n \"map_remove_marker\",\n \"Remove a marker by id.\",\n { id: { type: \"string\" } },\n [\"id\"],\n (args) => {\n const id = str(args.id);\n const prev = adapter.getMarkers().find((m) => m.id === id);\n if (!prev) {\n return errorResult(`No marker with id ${id}`);\n }\n adapter.setMarkers((all) => all.filter((m) => m.id !== id));\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_remove_marker\",\n label: `Removed marker ${id}`,\n undo: () => adapter.setMarkers((all) => [...all, prev]),\n redo: () => adapter.setMarkers((all) => all.filter((m) => m.id !== id)),\n });\n return textResult(`Removed marker ${id}`);\n },\n mTarget,\n );\n\n reg(\n \"map_select\",\n \"Select a marker (or pass no id / null to clear the selection).\",\n { id: { type: \"string\" } },\n [],\n (args) => {\n const prev = adapter.getSelected();\n const id = args.id === undefined || args.id === null ? null : str(args.id);\n if (id !== null && !adapter.getMarkers().some((m) => m.id === id)) {\n return errorResult(`No marker with id ${id}`);\n }\n adapter.setSelected(id);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_select\",\n label: id ? `Selected ${id}` : \"Cleared selection\",\n undo: () => adapter.setSelected(prev),\n redo: () => adapter.setSelected(id),\n });\n return textResult(id ? `Selected marker ${id}` : \"Cleared selection\", { selectedId: id });\n },\n mTarget,\n );\n\n // ───────────── Live tracking (camera follow) ─────────────\n\n reg(\n \"map_start_track\",\n \"Make the camera follow a marker as its position updates (live tracking). Requires the host to wire setFollow.\",\n { id: { type: \"string\" } },\n [\"id\"],\n (args) => {\n if (!adapter.setFollow) {\n return errorResult(\"Host did not wire setFollow (pass the map's `follow` setter).\");\n }\n const id = str(args.id);\n if (!adapter.getMarkers().some((m) => m.id === id)) {\n return errorResult(`No marker with id ${id}`);\n }\n adapter.setFollow(id);\n return textResult(`Camera now following ${id}`, { follow: id });\n },\n mTarget,\n );\n\n reg(\n \"map_stop_track\",\n \"Stop following any marker (releases the camera). Requires the host to wire setFollow.\",\n {},\n [],\n () => {\n if (!adapter.setFollow) {\n return errorResult(\"Host did not wire setFollow.\");\n }\n adapter.setFollow(null);\n return textResult(\"Camera released (no longer following).\", { follow: null });\n },\n );\n\n return {\n id: \"map\",\n title: \"Map\",\n dispose: () => {\n for (const d of disposers) d();\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/mcp/server.ts","../src/presence/wrap-tool-with-activity.ts","../src/undo/undo-tools.ts","../src/bridges/map.ts"],"names":["emitActivity","undoOne","redoOne","readHistory","pushUndoEntry"],"mappings":"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","file":"bridges-map.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 * 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 ),\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 ),\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 ),\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","// Loose types so this bridge builds standalone without a hard dep on\n// @particle-academy/fancy-map. Hosts that use fancy-map pass its own\n// MapMarker / MapView values straight through — the shapes match.\ntype LatLng = { lat: number; lng: number };\ntype MapView = { center: LatLng; zoom: number; bearing?: number; pitch?: number };\ntype MapMarker = {\n id: string;\n position: LatLng;\n label?: string;\n color?: string;\n icon?: string;\n draggable?: boolean;\n data?: Record<string, unknown>;\n};\n\nimport { 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 type { AgentTarget as MapAgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * Adapter the host provides — getters/setters over the SAME controlled state it\n * passes to fancy-map's `<Map>` (view, markers, selection), plus optional\n * `fitBounds` (from the map's onReady handle) and `setFollow` (drives the map's\n * `follow` prop so an agent can make the camera track a moving marker).\n */\nexport type MapBridgeAdapter = {\n getView: () => MapView;\n setView: (next: MapView) => void;\n getMarkers: () => MapMarker[];\n setMarkers: (next: MapMarker[] | ((prev: MapMarker[]) => MapMarker[])) => void;\n getSelected: () => string | null;\n setSelected: (id: string | null) => void;\n /** Fit the camera to points (wire to the `MapHandle.fitBounds` from `<Map onReady>`). */\n fitBounds?: (points: LatLng[], padding?: number) => void;\n /** Make the camera follow a marker as it moves (drives the map's `follow` prop). */\n setFollow?: (id: string | null) => void;\n};\n\nexport type MapBridgeOptions = {\n adapter: MapBridgeAdapter;\n /** Identity tagged onto agent-authored markers. */\n agent?: { id: string; name?: string; color?: string };\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\nconst num = (v: unknown, fallback?: number): number =>\n typeof v === \"number\" && Number.isFinite(v) ? v : fallback ?? 0;\nconst str = (v: unknown, fallback = \"\"): string => (typeof v === \"string\" ? v : fallback);\nconst newId = (prefix: string) =>\n `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 7)}`;\n\n/**\n * registerMapBridge — an MCP tool set over a fancy-map `<Map>`'s controlled\n * state, so a human and an agent cohabit one map. The agent moves the camera,\n * drops/updates/removes markers, selects, fits bounds, and follows a live\n * track; every mutation broadcasts AgentActivity (for presence) and pushes an\n * undo entry (so the human can step the agent back). Mirrors the whiteboard /\n * flow bridges in shape.\n */\nexport function registerMapBridge(host: ToolHost, options: MapBridgeOptions): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const disposers: Array<() => void> = [];\n\n // Register agent_undo / agent_redo / agent_history once per host. Idempotent.\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const mTarget = (args: any, result: any): MapAgentTarget => ({\n kind: \"map\",\n elementId:\n (result?.structuredContent?.id as string | undefined) ?? (args?.id as string | undefined),\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 resolveTarget?: (args: JsonObject, result: any) => MapAgentTarget | 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 = resolveTarget\n ? wrapToolWithActivity(wrapped, {\n toolName: name,\n agent: { id: agent.id, name: agent.name, color: agent.color },\n kind: \"map\",\n resolveTarget: ({ args, result }) => resolveTarget(args, result),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: {\n type: \"object\",\n properties: properties as any,\n required,\n additionalProperties: false,\n },\n },\n final as any,\n ),\n );\n };\n\n // ───────────── Read ─────────────\n\n reg(\"map_get_state\", \"Get the map's camera, markers, and current selection.\", {}, [], () => {\n const state = {\n view: adapter.getView(),\n markers: adapter.getMarkers(),\n selectedId: adapter.getSelected(),\n };\n return textResult(JSON.stringify(state, null, 2), state);\n });\n\n // ───────────── Camera ─────────────\n\n reg(\n \"map_set_view\",\n \"Move the camera to an absolute position. Any omitted field is left unchanged.\",\n {\n lat: { type: \"number\", description: \"New center latitude.\" },\n lng: { type: \"number\", description: \"New center longitude.\" },\n zoom: { type: \"number\", description: \"New zoom level (higher = closer).\" },\n },\n [],\n (args) => {\n const prev = adapter.getView();\n const next: MapView = {\n center: {\n lat: args.lat !== undefined ? num(args.lat) : prev.center.lat,\n lng: args.lng !== undefined ? num(args.lng) : prev.center.lng,\n },\n zoom: args.zoom !== undefined ? num(args.zoom) : prev.zoom,\n };\n adapter.setView(next);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_set_view\",\n label: `Moved camera to ${next.center.lat.toFixed(4)},${next.center.lng.toFixed(4)} z${next.zoom}`,\n undo: () => adapter.setView(prev),\n redo: () => adapter.setView(next),\n });\n return textResult(`Camera → ${next.center.lat.toFixed(4)},${next.center.lng.toFixed(4)} z${next.zoom}`, next);\n },\n mTarget,\n );\n\n reg(\n \"map_pan\",\n \"Pan the camera by a relative offset in degrees (positive dLat = north, positive dLng = east).\",\n { dLat: { type: \"number\" }, dLng: { type: \"number\" } },\n [],\n (args) => {\n const prev = adapter.getView();\n const next: MapView = {\n ...prev,\n center: { lat: prev.center.lat + num(args.dLat), lng: prev.center.lng + num(args.dLng) },\n };\n adapter.setView(next);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_pan\",\n label: \"Panned camera\",\n undo: () => adapter.setView(prev),\n redo: () => adapter.setView(next),\n });\n return textResult(`Panned to ${next.center.lat.toFixed(4)},${next.center.lng.toFixed(4)}`, next);\n },\n mTarget,\n );\n\n reg(\n \"map_zoom\",\n \"Zoom the camera by a relative delta (e.g. +1 zooms in one level, -2 out two).\",\n { delta: { type: \"number\" } },\n [\"delta\"],\n (args) => {\n const prev = adapter.getView();\n const next: MapView = { ...prev, zoom: prev.zoom + num(args.delta) };\n adapter.setView(next);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_zoom\",\n label: `Zoom → ${next.zoom}`,\n undo: () => adapter.setView(prev),\n redo: () => adapter.setView(next),\n });\n return textResult(`Zoom → ${next.zoom}`, next);\n },\n );\n\n reg(\n \"map_fit_bounds\",\n \"Fit the camera to enclose points. Pass `points`, or omit to fit all current markers.\",\n {\n points: {\n type: \"array\",\n description: \"Points to enclose, e.g. [{lat,lng},…].\",\n items: {\n type: \"object\",\n properties: { lat: { type: \"number\" }, lng: { type: \"number\" } },\n required: [\"lat\", \"lng\"],\n },\n },\n padding: { type: \"number\", description: \"Padding in pixels (default 40).\" },\n },\n [],\n (args) => {\n if (!adapter.fitBounds) {\n return errorResult(\"Host did not wire fitBounds (pass the <Map onReady> handle's fitBounds).\");\n }\n const points: LatLng[] = Array.isArray(args.points)\n ? (args.points as any[]).map((p) => ({ lat: num(p?.lat), lng: num(p?.lng) }))\n : adapter.getMarkers().map((m) => m.position);\n if (!points.length) {\n return errorResult(\"No points to fit (map has no markers).\");\n }\n adapter.fitBounds(points, args.padding !== undefined ? num(args.padding) : undefined);\n return textResult(`Fit camera to ${points.length} point(s).`);\n },\n );\n\n // ───────────── Markers ─────────────\n\n reg(\n \"map_add_marker\",\n \"Drop a marker. `id` is optional (auto-generated); `icon` is an emoji or 1–2 chars.\",\n {\n id: { type: \"string\" },\n lat: { type: \"number\" },\n lng: { type: \"number\" },\n label: { type: \"string\" },\n color: { type: \"string\", description: \"CSS color, e.g. #2563eb.\" },\n icon: { type: \"string\", description: \"Emoji / short text in the pin.\" },\n draggable: { type: \"boolean\" },\n data: { type: \"object\", description: \"Arbitrary JSON payload carried with the marker.\" },\n },\n [\"lat\", \"lng\"],\n (args) => {\n const id = args.id ? str(args.id) : newId(\"m\");\n if (adapter.getMarkers().some((m) => m.id === id)) {\n return errorResult(`A marker with id ${id} already exists — use map_update_marker.`);\n }\n const marker: MapMarker = {\n id,\n position: { lat: num(args.lat), lng: num(args.lng) },\n ...(args.label !== undefined ? { label: str(args.label) } : {}),\n ...(args.color !== undefined ? { color: str(args.color) } : {}),\n ...(args.icon !== undefined ? { icon: str(args.icon) } : {}),\n ...(args.draggable !== undefined ? { draggable: !!args.draggable } : {}),\n ...(args.data && typeof args.data === \"object\"\n ? { data: args.data as Record<string, unknown> }\n : {}),\n };\n adapter.setMarkers((all) => [...all, marker]);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_add_marker\",\n label: `Added marker ${id}`,\n undo: () => adapter.setMarkers((all) => all.filter((m) => m.id !== id)),\n redo: () => adapter.setMarkers((all) => [...all, marker]),\n });\n return textResult(`Added marker ${id} at ${marker.position.lat.toFixed(4)},${marker.position.lng.toFixed(4)}`, marker);\n },\n mTarget,\n );\n\n reg(\n \"map_update_marker\",\n \"Update a marker. Only provided fields change — update lat/lng repeatedly to drive a live track.\",\n {\n id: { type: \"string\" },\n lat: { type: \"number\" },\n lng: { type: \"number\" },\n label: { type: \"string\" },\n color: { type: \"string\" },\n icon: { type: \"string\" },\n draggable: { type: \"boolean\" },\n },\n [\"id\"],\n (args) => {\n const id = str(args.id);\n const prev = adapter.getMarkers().find((m) => m.id === id);\n if (!prev) {\n return errorResult(`No marker with id ${id}`);\n }\n const next: MapMarker = {\n ...prev,\n position: {\n lat: args.lat !== undefined ? num(args.lat) : prev.position.lat,\n lng: args.lng !== undefined ? num(args.lng) : prev.position.lng,\n },\n ...(args.label !== undefined ? { label: str(args.label) } : {}),\n ...(args.color !== undefined ? { color: str(args.color) } : {}),\n ...(args.icon !== undefined ? { icon: str(args.icon) } : {}),\n ...(args.draggable !== undefined ? { draggable: !!args.draggable } : {}),\n };\n adapter.setMarkers((all) => all.map((m) => (m.id === id ? next : m)));\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_update_marker\",\n label: `Updated marker ${id}`,\n undo: () => adapter.setMarkers((all) => all.map((m) => (m.id === id ? prev : m))),\n redo: () => adapter.setMarkers((all) => all.map((m) => (m.id === id ? next : m))),\n });\n return textResult(`Updated marker ${id}`, next);\n },\n mTarget,\n );\n\n reg(\n \"map_remove_marker\",\n \"Remove a marker by id.\",\n { id: { type: \"string\" } },\n [\"id\"],\n (args) => {\n const id = str(args.id);\n const prev = adapter.getMarkers().find((m) => m.id === id);\n if (!prev) {\n return errorResult(`No marker with id ${id}`);\n }\n adapter.setMarkers((all) => all.filter((m) => m.id !== id));\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_remove_marker\",\n label: `Removed marker ${id}`,\n undo: () => adapter.setMarkers((all) => [...all, prev]),\n redo: () => adapter.setMarkers((all) => all.filter((m) => m.id !== id)),\n });\n return textResult(`Removed marker ${id}`);\n },\n mTarget,\n );\n\n reg(\n \"map_select\",\n \"Select a marker (or pass no id / null to clear the selection).\",\n { id: { type: \"string\" } },\n [],\n (args) => {\n const prev = adapter.getSelected();\n const id = args.id === undefined || args.id === null ? null : str(args.id);\n if (id !== null && !adapter.getMarkers().some((m) => m.id === id)) {\n return errorResult(`No marker with id ${id}`);\n }\n adapter.setSelected(id);\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: \"map\",\n action: \"map_select\",\n label: id ? `Selected ${id}` : \"Cleared selection\",\n undo: () => adapter.setSelected(prev),\n redo: () => adapter.setSelected(id),\n });\n return textResult(id ? `Selected marker ${id}` : \"Cleared selection\", { selectedId: id });\n },\n mTarget,\n );\n\n // ───────────── Live tracking (camera follow) ─────────────\n\n reg(\n \"map_start_track\",\n \"Make the camera follow a marker as its position updates (live tracking). Requires the host to wire setFollow.\",\n { id: { type: \"string\" } },\n [\"id\"],\n (args) => {\n if (!adapter.setFollow) {\n return errorResult(\"Host did not wire setFollow (pass the map's `follow` setter).\");\n }\n const id = str(args.id);\n if (!adapter.getMarkers().some((m) => m.id === id)) {\n return errorResult(`No marker with id ${id}`);\n }\n adapter.setFollow(id);\n return textResult(`Camera now following ${id}`, { follow: id });\n },\n mTarget,\n );\n\n reg(\n \"map_stop_track\",\n \"Stop following any marker (releases the camera). Requires the host to wire setFollow.\",\n {},\n [],\n () => {\n if (!adapter.setFollow) {\n return errorResult(\"Host did not wire setFollow.\");\n }\n adapter.setFollow(null);\n return textResult(\"Camera released (no longer following).\", { follow: null });\n },\n );\n\n return {\n id: \"map\",\n title: \"Map\",\n dispose: () => {\n for (const d of disposers) d();\n },\n };\n}\n"]}
@@ -1,7 +1,7 @@
1
- export { registerMapBridge } from './chunk-MZ74LLDS.js';
2
- import './chunk-HVDHT7DM.js';
1
+ export { registerMapBridge } from './chunk-3UUF5KKZ.js';
2
+ import './chunk-R4XXOGQH.js';
3
3
  import './chunk-2VENWGLZ.js';
4
4
  import './chunk-C3TYI5TJ.js';
5
- import './chunk-QJYRWEXD.js';
5
+ import './chunk-CZV3WUW5.js';
6
6
  //# sourceMappingURL=bridges-map.js.map
7
7
  //# sourceMappingURL=bridges-map.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mcp/server.ts","../src/presence/wrap-tool-with-activity.ts","../src/undo/undo-tools.ts","../src/bridges/passkeys.ts"],"names":["emitActivity","undoOne","redoOne","readHistory","pushUndoEntry"],"mappings":"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","file":"bridges-passkeys.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\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 private notifyListChangedScheduled = false;\n\n readonly info: ServerInfo;\n readonly capabilities: ServerCapabilities;\n readonly instructions?: 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 }\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: MCP_PROTOCOL_VERSION,\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 private scheduleListChangedNotification(): void {\n if (this.notifyListChangedScheduled) return;\n this.notifyListChangedScheduled = true;\n queueMicrotask(() => {\n this.notifyListChangedScheduled = false;\n this.broadcast({ jsonrpc: \"2.0\", method: \"notifications/tools/list_changed\" });\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 * 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 ),\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 ),\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 ),\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 type { AgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * Bridge for `@particle-academy/fancy-passkeys-ui` — the **management** half of\n * a passkey (WebAuthn) surface, and only that half.\n *\n * ## The absence is the design\n *\n * There is **no tool here that completes an authentication or registration\n * ceremony**, and there must never be one. Not `passkey_authenticate`, not\n * `passkey_sign_in`, not `passkey_complete`, not a \"headless\" variant behind a\n * flag.\n *\n * The reason is construction, not policy. `navigator.credentials.get()` requires\n * a user gesture and a biometric or PIN — both things only the person at the\n * keyboard has. An agent-drivable passkey login would be a bypass of the exact\n * property that makes a passkey worth more than a password: that possession of\n * the credential cannot be delegated, replayed, or phished. A bridge offering\n * one would quietly turn a phishing-resistant factor back into a bearer token.\n *\n * So the boundary sits where the cryptography already puts it, and the tool set\n * is drawn to match: **read the management surface, rename, propose, ask the\n * human to start a ceremony.** `bridges/__tests__/passkeys.test.ts` asserts the\n * registered tool names against a closed list, so \"finishing\" this bridge with a\n * sign-in tool fails CI rather than shipping.\n *\n * ## What it does do\n *\n * passkey_list the user's credentials (whitelisted fields only)\n * passkey_status browser support + what the surface currently shows\n * passkey_rename relabel one credential, by credential ID (undoable)\n * passkey_revoke **STAGES** a revoke for the human to confirm\n * passkey_begin_enrollment opens the enrollment prompt; returns immediately\n *\n * `passkey_revoke` never revokes. Revoking a passkey is destructive and revoking\n * the last one is a lockout, so the confirming click comes from the human at the\n * surface — there is deliberately **no `pendingMode: false`**, no `confirm: true`\n * argument, and no host hook that turns staging off. On this bridge staging is\n * not a mode.\n *\n * The adapter type is declared LOCALLY (like `features` / `catalog`) so the\n * bridge builds and type-checks with the sibling package absent. A host wiring a\n * live `PasskeyManager` satisfies it structurally, with no import.\n */\n\n/**\n * One credential as the bridge is willing to describe it — the `PasskeySummary`\n * shape both passkey backends already serialise.\n *\n * Everything the server stores that is NOT on this list — the COSE public key,\n * the user handle, the signature counter, the attestation statement and trust\n * path — is absent on purpose, and {@link toSummary} re-projects onto exactly\n * these keys rather than trusting the adapter to have withheld them. A host that\n * hands `list()` its raw ORM model (the obvious thing to do) therefore cannot\n * leak credential material through an MCP tool by accident.\n */\nexport type PasskeySummaryLike = {\n /** base64url credential ID — the handle every action here is keyed by. */\n id: string;\n /** Human-chosen label, or null when the user never named it. */\n name: string | null;\n /** ISO-8601. */\n createdAt: string;\n /** ISO-8601, or null when never used to sign in. */\n lastUsedAt: string | null;\n /** Transport hints (\"internal\", \"hybrid\", \"usb\", …). */\n transports: string[];\n /** True for a synced passkey (BE/BS flags); false means this device only. */\n backedUp: boolean;\n /** Authenticator model id. Stored, never a trust decision. */\n aaguid: string;\n /** ISO-8601 when the signature counter regressed — a suspected clone. */\n clonedAt: string | null;\n};\n\n/** What the browser can do, as the three `./client` predicates report it. */\nexport type PasskeySupport = {\n supported: boolean;\n /** Touch ID / Windows Hello present? `null` while unknown. */\n platformAuthenticator?: boolean | null;\n /** Can the browser offer a passkey from a username field? `null` while unknown. */\n conditionalUi?: boolean | null;\n};\n\n/** A read of what the management surface is currently showing. */\nexport type PasskeySurfaceState = {\n status?: \"idle\" | \"busy\" | \"error\";\n /** `{ code, message }` as carried in surface state — never an Error. */\n error?: { code: string; message: string } | null;\n /** The revoke awaiting a human's confirmation, if any. */\n pendingRevoke?: { id: string; isLastPasskey: boolean } | null;\n /** Credential ID currently being renamed, if any. */\n renamingId?: string | null;\n};\n\n/**\n * Host-provided access to the management surface. Mirrors the props a\n * `PasskeyManager` is already wired with, so a host usually passes the same four\n * callbacks it passed the component.\n */\nexport type PasskeyBridgeAdapter = {\n /** Stable id for this surface instance. Surfaces in activity logs. */\n id?: string;\n title?: string;\n screenId?: string;\n\n /** The signed-in user's credentials. */\n list(): PasskeySummaryLike[] | Promise<PasskeySummaryLike[]>;\n\n /** Relabel one credential. Cosmetic, reversible, and undoable here. */\n rename(input: { id: string; name: string }): void | Promise<void>;\n\n /**\n * **Stage** a revoke for human confirmation — the `pendingRevoke` the surface\n * renders a confirm/cancel dialog for. It must NOT revoke; a host that wires\n * this to a delete call has removed the human from the loop the bridge was\n * built around.\n */\n proposeRevoke(input: { id: string }): PasskeyProposal | Promise<PasskeyProposal>;\n\n /**\n * Open the enrollment prompt on the human's screen and return immediately.\n * The ceremony completes on their authenticator or not at all.\n */\n beginEnrollment?(input: { name?: string }): void | Promise<void>;\n\n /** Browser capability flags, if the host tracks them. */\n support?(): PasskeySupport | Promise<PasskeySupport>;\n\n /** What the surface currently shows. */\n state?(): PasskeySurfaceState | Promise<PasskeySurfaceState>;\n};\n\nexport type PasskeyProposal = { staged: true; isLastPasskey: boolean };\n\nexport type PasskeyBridgeOptions = {\n adapter: PasskeyBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n /**\n * Also route `passkey_rename` through {@link confirm}. Off by default: a\n * rename is cosmetic, reversible and pushed onto the undo stack. Worth turning\n * on where the label itself carries trust — a rogue credential relabelled\n * \"Glenn's iPhone\" survives a human's audit of the list.\n */\n confirmRename?: boolean;\n /**\n * Host confirmation hook for renames, when {@link confirmRename} is on.\n *\n * Note there is no revoke case: a revoke is staged into the surface and\n * confirmed there, never through a hook the agent's own host supplies.\n */\n confirm?: (req: { action: \"passkey_rename\"; id: string; name: string }) => boolean | Promise<boolean>;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\nconst str = (v: unknown, fallback = \"\"): string => (typeof v === \"string\" ? v : fallback);\n\n/**\n * Project an adapter record onto exactly the public summary fields.\n *\n * Deliberately a whitelist and not a `delete` of known-bad keys: a blacklist has\n * to be updated every time a backend grows a column, and the failure mode of\n * forgetting is silently publishing credential material to every agent in the\n * session.\n */\nfunction toSummary(record: PasskeySummaryLike): PasskeySummaryLike {\n return {\n id: str(record?.id),\n name: typeof record?.name === \"string\" ? record.name : null,\n createdAt: str(record?.createdAt),\n lastUsedAt: typeof record?.lastUsedAt === \"string\" ? record.lastUsedAt : null,\n transports: Array.isArray(record?.transports) ? record.transports.map((t) => String(t)) : [],\n backedUp: record?.backedUp === true,\n aaguid: str(record?.aaguid),\n clonedAt: typeof record?.clonedAt === \"string\" ? record.clonedAt : null,\n };\n}\n\n/**\n * The complete set of tools this bridge may ever register.\n *\n * Exported so the test suite — and anyone auditing what an agent can reach —\n * can assert the registered names against it rather than eyeballing the file.\n */\nexport const PASSKEY_BRIDGE_TOOLS = [\n \"passkey_list\",\n \"passkey_status\",\n \"passkey_rename\",\n \"passkey_revoke\",\n \"passkey_begin_enrollment\",\n] as const;\n\n/**\n * registerPasskeyBridge — MCP tools over a passkey **management** surface.\n *\n * Read the credential list, read browser support and surface state, rename a\n * credential, propose a revoke for the human to confirm, and ask for an\n * enrollment prompt. Nothing signs anyone in; see the file header for why that\n * is a property rather than a gap.\n */\nexport function registerPasskeyBridge(host: ToolHost, options: PasskeyBridgeOptions): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const surfaceId = adapter.id ?? \"passkeys\";\n const disposers: Array<() => void> = [];\n\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (elementId?: string, label?: string): AgentTarget => ({\n kind: \"custom\",\n screenId: adapter.screenId,\n elementId,\n label: label ?? surfaceId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<unknown> | unknown,\n resolveTarget: false | ((args: JsonObject) => AgentTarget),\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 = resolveTarget\n ? wrapToolWithActivity(wrapped as never, {\n toolName: name,\n agent,\n kind: \"custom\",\n screenId: adapter.screenId,\n resolveTarget: ({ args }) => resolveTarget(args as JsonObject),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: {\n type: \"object\",\n properties: properties as Record<string, never>,\n required,\n additionalProperties: false,\n },\n },\n final as never,\n ),\n );\n };\n\n const findById = async (id: string): Promise<PasskeySummaryLike | null> =>\n (await adapter.list()).map(toSummary).find((p) => p.id === id) ?? null;\n\n // ─── Read ────────────────────────────────────────────────────────────────\n\n reg(\n \"passkey_list\",\n \"List the signed-in user's passkeys: credential id, label, when it was added and last used, transports, whether it is a synced passkey, and whether the server flagged it as a possible clone. Read-only. Public keys, user handles and signature counters are never returned.\",\n {},\n [],\n async () => {\n const passkeys = (await adapter.list()).map(toSummary);\n return textResult(JSON.stringify(passkeys, null, 2), { passkeys, count: passkeys.length });\n },\n false,\n );\n\n reg(\n \"passkey_status\",\n \"Read what this browser can do (passkey support, a built-in authenticator, autofill sign-in) and what the management surface is currently showing (busy/error, a revoke awaiting confirmation, a rename in progress).\",\n {},\n [],\n async () => {\n const support = adapter.support ? await adapter.support() : null;\n const state = adapter.state ? await adapter.state() : null;\n const out = {\n support,\n state,\n // Said in the payload, not only in the docs: an agent reading this to\n // work out \"how do I sign the user in\" should find the answer here.\n canCompleteCeremony: false,\n note: \"A passkey ceremony needs a user gesture and a biometric or PIN. No tool on this bridge can perform one; ask the human to complete it on their device.\",\n };\n return textResult(JSON.stringify(out, null, 2), out);\n },\n false,\n );\n\n // ─── Rename (undoable) ───────────────────────────────────────────────────\n\n reg(\n \"passkey_rename\",\n \"Rename one passkey, by credential id (from passkey_list). Cosmetic and undoable with agent_undo.\",\n {\n id: { type: \"string\", description: \"base64url credential id.\" },\n name: { type: \"string\", description: \"New label, e.g. 'MacBook Touch ID'. Empty string clears it.\" },\n },\n [\"id\", \"name\"],\n async (args) => {\n const id = str(args.id);\n const name = str(args.name);\n if (!id) return errorResult(\"id is required.\");\n\n const existing = await findById(id);\n if (!existing) return errorResult(`No passkey with id ${id}.`);\n\n if (options.confirmRename) {\n if (!options.confirm) {\n return errorResult(\n \"passkey_rename requires confirmation (confirmRename), but the host wired no confirm hook.\",\n );\n }\n const ok = await options.confirm({ action: \"passkey_rename\", id, name });\n if (!ok) return errorResult(`Declined: rename ${id} (human did not confirm).`);\n }\n\n const previous = existing.name ?? \"\";\n await adapter.rename({ id, name });\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: surfaceId,\n action: \"passkey_rename\",\n label: `Renamed passkey to ${name || \"(unnamed)\"}`,\n undo: () => void adapter.rename({ id, name: previous }),\n redo: () => void adapter.rename({ id, name }),\n });\n\n return textResult(`Renamed passkey ${id} to ${name || \"(unnamed)\"}`, { id, name, previous });\n },\n (args) => target(str(args.id), `rename ${str(args.id)}`),\n );\n\n // ─── Revoke — PROPOSAL ONLY ──────────────────────────────────────────────\n\n reg(\n \"passkey_revoke\",\n \"PROPOSE revoking one passkey. This does NOT revoke it: the request is staged on the surface and the human confirms or cancels there. Revoking the last passkey can lock the user out, and the response says when that is the case so you can tell them before they confirm.\",\n { id: { type: \"string\", description: \"base64url credential id.\" } },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n if (!id) return errorResult(\"id is required.\");\n\n const existing = await findById(id);\n if (!existing) return errorResult(`No passkey with id ${id}.`);\n\n const proposal = await adapter.proposeRevoke({ id });\n const isLastPasskey = proposal?.isLastPasskey === true;\n const out = {\n id,\n name: existing.name,\n staged: true as const,\n awaitingHuman: true as const,\n isLastPasskey,\n };\n\n return textResult(\n isLastPasskey\n ? `Staged a revoke of ${existing.name ?? id}. This is the account's LAST passkey — confirming it removes passkey sign-in entirely. Waiting for the human to confirm or cancel.`\n : `Staged a revoke of ${existing.name ?? id}. Waiting for the human to confirm or cancel on the surface.`,\n out,\n );\n },\n (args) => target(str(args.id), `propose revoke ${str(args.id)}`),\n );\n\n // ─── Enrollment — opens the prompt, never completes it ───────────────────\n\n reg(\n \"passkey_begin_enrollment\",\n \"Ask the surface to start enrolling a new passkey. This only opens the prompt: the ceremony completes on the human's authenticator (Touch ID, Windows Hello, phone, security key) or it does not complete at all. Returns immediately.\",\n { name: { type: \"string\", description: \"Optional label to pre-fill for the new passkey.\" } },\n [],\n async (args) => {\n if (!adapter.beginEnrollment) return errorResult(\"Host did not wire beginEnrollment().\");\n const name = args.name === undefined ? undefined : str(args.name);\n await adapter.beginEnrollment(name === undefined ? {} : { name });\n const out = { awaitingHuman: true as const, ...(name === undefined ? {} : { name }) };\n return textResult(\n \"Enrollment prompt opened. The human has to complete it on their authenticator — there is no tool that can finish it for them.\",\n out,\n );\n },\n (args) => target(undefined, `begin enrollment${args.name ? ` (${str(args.name)})` : \"\"}`),\n );\n\n // ── There is deliberately NO tool below that completes a ceremony. ────────\n // No passkey_authenticate, no passkey_sign_in, no passkey_complete, no\n // passkey_assert. Do not \"finish\" this bridge by adding one — see the header,\n // and see the closed-tool-list test that will fail if you do.\n\n return {\n id: `passkeys:${surfaceId}`,\n title: adapter.title ?? \"Passkeys\",\n dispose: () => {\n for (const d of disposers.splice(0)) d();\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/mcp/server.ts","../src/presence/wrap-tool-with-activity.ts","../src/undo/undo-tools.ts","../src/bridges/passkeys.ts"],"names":["emitActivity","undoOne","redoOne","readHistory","pushUndoEntry"],"mappings":"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","file":"bridges-passkeys.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 * 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 ),\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 ),\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 ),\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 type { AgentTarget } from \"../presence/types\";\nimport { pushUndoEntry } from \"../undo/undo-stack\";\nimport { ensureUndoToolsRegistered } from \"../undo/undo-tools\";\n\n/**\n * Bridge for `@particle-academy/fancy-passkeys-ui` — the **management** half of\n * a passkey (WebAuthn) surface, and only that half.\n *\n * ## The absence is the design\n *\n * There is **no tool here that completes an authentication or registration\n * ceremony**, and there must never be one. Not `passkey_authenticate`, not\n * `passkey_sign_in`, not `passkey_complete`, not a \"headless\" variant behind a\n * flag.\n *\n * The reason is construction, not policy. `navigator.credentials.get()` requires\n * a user gesture and a biometric or PIN — both things only the person at the\n * keyboard has. An agent-drivable passkey login would be a bypass of the exact\n * property that makes a passkey worth more than a password: that possession of\n * the credential cannot be delegated, replayed, or phished. A bridge offering\n * one would quietly turn a phishing-resistant factor back into a bearer token.\n *\n * So the boundary sits where the cryptography already puts it, and the tool set\n * is drawn to match: **read the management surface, rename, propose, ask the\n * human to start a ceremony.** `bridges/__tests__/passkeys.test.ts` asserts the\n * registered tool names against a closed list, so \"finishing\" this bridge with a\n * sign-in tool fails CI rather than shipping.\n *\n * ## What it does do\n *\n * passkey_list the user's credentials (whitelisted fields only)\n * passkey_status browser support + what the surface currently shows\n * passkey_rename relabel one credential, by credential ID (undoable)\n * passkey_revoke **STAGES** a revoke for the human to confirm\n * passkey_begin_enrollment opens the enrollment prompt; returns immediately\n *\n * `passkey_revoke` never revokes. Revoking a passkey is destructive and revoking\n * the last one is a lockout, so the confirming click comes from the human at the\n * surface — there is deliberately **no `pendingMode: false`**, no `confirm: true`\n * argument, and no host hook that turns staging off. On this bridge staging is\n * not a mode.\n *\n * The adapter type is declared LOCALLY (like `features` / `catalog`) so the\n * bridge builds and type-checks with the sibling package absent. A host wiring a\n * live `PasskeyManager` satisfies it structurally, with no import.\n */\n\n/**\n * One credential as the bridge is willing to describe it — the `PasskeySummary`\n * shape both passkey backends already serialise.\n *\n * Everything the server stores that is NOT on this list — the COSE public key,\n * the user handle, the signature counter, the attestation statement and trust\n * path — is absent on purpose, and {@link toSummary} re-projects onto exactly\n * these keys rather than trusting the adapter to have withheld them. A host that\n * hands `list()` its raw ORM model (the obvious thing to do) therefore cannot\n * leak credential material through an MCP tool by accident.\n */\nexport type PasskeySummaryLike = {\n /** base64url credential ID — the handle every action here is keyed by. */\n id: string;\n /** Human-chosen label, or null when the user never named it. */\n name: string | null;\n /** ISO-8601. */\n createdAt: string;\n /** ISO-8601, or null when never used to sign in. */\n lastUsedAt: string | null;\n /** Transport hints (\"internal\", \"hybrid\", \"usb\", …). */\n transports: string[];\n /** True for a synced passkey (BE/BS flags); false means this device only. */\n backedUp: boolean;\n /** Authenticator model id. Stored, never a trust decision. */\n aaguid: string;\n /** ISO-8601 when the signature counter regressed — a suspected clone. */\n clonedAt: string | null;\n};\n\n/** What the browser can do, as the three `./client` predicates report it. */\nexport type PasskeySupport = {\n supported: boolean;\n /** Touch ID / Windows Hello present? `null` while unknown. */\n platformAuthenticator?: boolean | null;\n /** Can the browser offer a passkey from a username field? `null` while unknown. */\n conditionalUi?: boolean | null;\n};\n\n/** A read of what the management surface is currently showing. */\nexport type PasskeySurfaceState = {\n status?: \"idle\" | \"busy\" | \"error\";\n /** `{ code, message }` as carried in surface state — never an Error. */\n error?: { code: string; message: string } | null;\n /** The revoke awaiting a human's confirmation, if any. */\n pendingRevoke?: { id: string; isLastPasskey: boolean } | null;\n /** Credential ID currently being renamed, if any. */\n renamingId?: string | null;\n};\n\n/**\n * Host-provided access to the management surface. Mirrors the props a\n * `PasskeyManager` is already wired with, so a host usually passes the same four\n * callbacks it passed the component.\n */\nexport type PasskeyBridgeAdapter = {\n /** Stable id for this surface instance. Surfaces in activity logs. */\n id?: string;\n title?: string;\n screenId?: string;\n\n /** The signed-in user's credentials. */\n list(): PasskeySummaryLike[] | Promise<PasskeySummaryLike[]>;\n\n /** Relabel one credential. Cosmetic, reversible, and undoable here. */\n rename(input: { id: string; name: string }): void | Promise<void>;\n\n /**\n * **Stage** a revoke for human confirmation — the `pendingRevoke` the surface\n * renders a confirm/cancel dialog for. It must NOT revoke; a host that wires\n * this to a delete call has removed the human from the loop the bridge was\n * built around.\n */\n proposeRevoke(input: { id: string }): PasskeyProposal | Promise<PasskeyProposal>;\n\n /**\n * Open the enrollment prompt on the human's screen and return immediately.\n * The ceremony completes on their authenticator or not at all.\n */\n beginEnrollment?(input: { name?: string }): void | Promise<void>;\n\n /** Browser capability flags, if the host tracks them. */\n support?(): PasskeySupport | Promise<PasskeySupport>;\n\n /** What the surface currently shows. */\n state?(): PasskeySurfaceState | Promise<PasskeySurfaceState>;\n};\n\nexport type PasskeyProposal = { staged: true; isLastPasskey: boolean };\n\nexport type PasskeyBridgeOptions = {\n adapter: PasskeyBridgeAdapter;\n agent?: { id: string; name?: string; color?: string };\n /**\n * Also route `passkey_rename` through {@link confirm}. Off by default: a\n * rename is cosmetic, reversible and pushed onto the undo stack. Worth turning\n * on where the label itself carries trust — a rogue credential relabelled\n * \"Glenn's iPhone\" survives a human's audit of the list.\n */\n confirmRename?: boolean;\n /**\n * Host confirmation hook for renames, when {@link confirmRename} is on.\n *\n * Note there is no revoke case: a revoke is staged into the surface and\n * confirmed there, never through a hook the agent's own host supplies.\n */\n confirm?: (req: { action: \"passkey_rename\"; id: string; name: string }) => boolean | Promise<boolean>;\n};\n\nconst DEFAULT_AGENT = { id: \"agent\", name: \"Agent\", color: \"#a855f7\" };\n\nconst str = (v: unknown, fallback = \"\"): string => (typeof v === \"string\" ? v : fallback);\n\n/**\n * Project an adapter record onto exactly the public summary fields.\n *\n * Deliberately a whitelist and not a `delete` of known-bad keys: a blacklist has\n * to be updated every time a backend grows a column, and the failure mode of\n * forgetting is silently publishing credential material to every agent in the\n * session.\n */\nfunction toSummary(record: PasskeySummaryLike): PasskeySummaryLike {\n return {\n id: str(record?.id),\n name: typeof record?.name === \"string\" ? record.name : null,\n createdAt: str(record?.createdAt),\n lastUsedAt: typeof record?.lastUsedAt === \"string\" ? record.lastUsedAt : null,\n transports: Array.isArray(record?.transports) ? record.transports.map((t) => String(t)) : [],\n backedUp: record?.backedUp === true,\n aaguid: str(record?.aaguid),\n clonedAt: typeof record?.clonedAt === \"string\" ? record.clonedAt : null,\n };\n}\n\n/**\n * The complete set of tools this bridge may ever register.\n *\n * Exported so the test suite — and anyone auditing what an agent can reach —\n * can assert the registered names against it rather than eyeballing the file.\n */\nexport const PASSKEY_BRIDGE_TOOLS = [\n \"passkey_list\",\n \"passkey_status\",\n \"passkey_rename\",\n \"passkey_revoke\",\n \"passkey_begin_enrollment\",\n] as const;\n\n/**\n * registerPasskeyBridge — MCP tools over a passkey **management** surface.\n *\n * Read the credential list, read browser support and surface state, rename a\n * credential, propose a revoke for the human to confirm, and ask for an\n * enrollment prompt. Nothing signs anyone in; see the file header for why that\n * is a property rather than a gap.\n */\nexport function registerPasskeyBridge(host: ToolHost, options: PasskeyBridgeOptions): Bridge {\n const { adapter } = options;\n const agent = { ...DEFAULT_AGENT, ...(options.agent ?? {}) };\n const surfaceId = adapter.id ?? \"passkeys\";\n const disposers: Array<() => void> = [];\n\n ensureUndoToolsRegistered(host, { defaultAgentId: agent.id });\n\n const target = (elementId?: string, label?: string): AgentTarget => ({\n kind: \"custom\",\n screenId: adapter.screenId,\n elementId,\n label: label ?? surfaceId,\n });\n\n const reg = (\n name: string,\n description: string,\n properties: Record<string, unknown>,\n required: string[],\n handler: (args: JsonObject) => Promise<unknown> | unknown,\n resolveTarget: false | ((args: JsonObject) => AgentTarget),\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 = resolveTarget\n ? wrapToolWithActivity(wrapped as never, {\n toolName: name,\n agent,\n kind: \"custom\",\n screenId: adapter.screenId,\n resolveTarget: ({ args }) => resolveTarget(args as JsonObject),\n })\n : wrapped;\n disposers.push(\n host.registerTool(\n {\n name,\n description,\n inputSchema: {\n type: \"object\",\n properties: properties as Record<string, never>,\n required,\n additionalProperties: false,\n },\n },\n final as never,\n ),\n );\n };\n\n const findById = async (id: string): Promise<PasskeySummaryLike | null> =>\n (await adapter.list()).map(toSummary).find((p) => p.id === id) ?? null;\n\n // ─── Read ────────────────────────────────────────────────────────────────\n\n reg(\n \"passkey_list\",\n \"List the signed-in user's passkeys: credential id, label, when it was added and last used, transports, whether it is a synced passkey, and whether the server flagged it as a possible clone. Read-only. Public keys, user handles and signature counters are never returned.\",\n {},\n [],\n async () => {\n const passkeys = (await adapter.list()).map(toSummary);\n return textResult(JSON.stringify(passkeys, null, 2), { passkeys, count: passkeys.length });\n },\n false,\n );\n\n reg(\n \"passkey_status\",\n \"Read what this browser can do (passkey support, a built-in authenticator, autofill sign-in) and what the management surface is currently showing (busy/error, a revoke awaiting confirmation, a rename in progress).\",\n {},\n [],\n async () => {\n const support = adapter.support ? await adapter.support() : null;\n const state = adapter.state ? await adapter.state() : null;\n const out = {\n support,\n state,\n // Said in the payload, not only in the docs: an agent reading this to\n // work out \"how do I sign the user in\" should find the answer here.\n canCompleteCeremony: false,\n note: \"A passkey ceremony needs a user gesture and a biometric or PIN. No tool on this bridge can perform one; ask the human to complete it on their device.\",\n };\n return textResult(JSON.stringify(out, null, 2), out);\n },\n false,\n );\n\n // ─── Rename (undoable) ───────────────────────────────────────────────────\n\n reg(\n \"passkey_rename\",\n \"Rename one passkey, by credential id (from passkey_list). Cosmetic and undoable with agent_undo.\",\n {\n id: { type: \"string\", description: \"base64url credential id.\" },\n name: { type: \"string\", description: \"New label, e.g. 'MacBook Touch ID'. Empty string clears it.\" },\n },\n [\"id\", \"name\"],\n async (args) => {\n const id = str(args.id);\n const name = str(args.name);\n if (!id) return errorResult(\"id is required.\");\n\n const existing = await findById(id);\n if (!existing) return errorResult(`No passkey with id ${id}.`);\n\n if (options.confirmRename) {\n if (!options.confirm) {\n return errorResult(\n \"passkey_rename requires confirmation (confirmRename), but the host wired no confirm hook.\",\n );\n }\n const ok = await options.confirm({ action: \"passkey_rename\", id, name });\n if (!ok) return errorResult(`Declined: rename ${id} (human did not confirm).`);\n }\n\n const previous = existing.name ?? \"\";\n await adapter.rename({ id, name });\n pushUndoEntry(agent.id, {\n timestamp: Date.now(),\n bridgeId: surfaceId,\n action: \"passkey_rename\",\n label: `Renamed passkey to ${name || \"(unnamed)\"}`,\n undo: () => void adapter.rename({ id, name: previous }),\n redo: () => void adapter.rename({ id, name }),\n });\n\n return textResult(`Renamed passkey ${id} to ${name || \"(unnamed)\"}`, { id, name, previous });\n },\n (args) => target(str(args.id), `rename ${str(args.id)}`),\n );\n\n // ─── Revoke — PROPOSAL ONLY ──────────────────────────────────────────────\n\n reg(\n \"passkey_revoke\",\n \"PROPOSE revoking one passkey. This does NOT revoke it: the request is staged on the surface and the human confirms or cancels there. Revoking the last passkey can lock the user out, and the response says when that is the case so you can tell them before they confirm.\",\n { id: { type: \"string\", description: \"base64url credential id.\" } },\n [\"id\"],\n async (args) => {\n const id = str(args.id);\n if (!id) return errorResult(\"id is required.\");\n\n const existing = await findById(id);\n if (!existing) return errorResult(`No passkey with id ${id}.`);\n\n const proposal = await adapter.proposeRevoke({ id });\n const isLastPasskey = proposal?.isLastPasskey === true;\n const out = {\n id,\n name: existing.name,\n staged: true as const,\n awaitingHuman: true as const,\n isLastPasskey,\n };\n\n return textResult(\n isLastPasskey\n ? `Staged a revoke of ${existing.name ?? id}. This is the account's LAST passkey — confirming it removes passkey sign-in entirely. Waiting for the human to confirm or cancel.`\n : `Staged a revoke of ${existing.name ?? id}. Waiting for the human to confirm or cancel on the surface.`,\n out,\n );\n },\n (args) => target(str(args.id), `propose revoke ${str(args.id)}`),\n );\n\n // ─── Enrollment — opens the prompt, never completes it ───────────────────\n\n reg(\n \"passkey_begin_enrollment\",\n \"Ask the surface to start enrolling a new passkey. This only opens the prompt: the ceremony completes on the human's authenticator (Touch ID, Windows Hello, phone, security key) or it does not complete at all. Returns immediately.\",\n { name: { type: \"string\", description: \"Optional label to pre-fill for the new passkey.\" } },\n [],\n async (args) => {\n if (!adapter.beginEnrollment) return errorResult(\"Host did not wire beginEnrollment().\");\n const name = args.name === undefined ? undefined : str(args.name);\n await adapter.beginEnrollment(name === undefined ? {} : { name });\n const out = { awaitingHuman: true as const, ...(name === undefined ? {} : { name }) };\n return textResult(\n \"Enrollment prompt opened. The human has to complete it on their authenticator — there is no tool that can finish it for them.\",\n out,\n );\n },\n (args) => target(undefined, `begin enrollment${args.name ? ` (${str(args.name)})` : \"\"}`),\n );\n\n // ── There is deliberately NO tool below that completes a ceremony. ────────\n // No passkey_authenticate, no passkey_sign_in, no passkey_complete, no\n // passkey_assert. Do not \"finish\" this bridge by adding one — see the header,\n // and see the closed-tool-list test that will fail if you do.\n\n return {\n id: `passkeys:${surfaceId}`,\n title: adapter.title ?? \"Passkeys\",\n dispose: () => {\n for (const d of disposers.splice(0)) d();\n },\n };\n}\n"]}
@@ -1,7 +1,7 @@
1
- export { PASSKEY_BRIDGE_TOOLS, registerPasskeyBridge } from './chunk-LOD77NCD.js';
2
- import './chunk-HVDHT7DM.js';
1
+ export { PASSKEY_BRIDGE_TOOLS, registerPasskeyBridge } from './chunk-PWYEW6NL.js';
2
+ import './chunk-R4XXOGQH.js';
3
3
  import './chunk-2VENWGLZ.js';
4
4
  import './chunk-C3TYI5TJ.js';
5
- import './chunk-QJYRWEXD.js';
5
+ import './chunk-CZV3WUW5.js';
6
6
  //# sourceMappingURL=bridges-passkeys.js.map
7
7
  //# sourceMappingURL=bridges-passkeys.js.map