agents 0.2.22 → 0.2.24

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 (58) hide show
  1. package/README.md +5 -3
  2. package/dist/ai-chat-agent.d.ts +86 -13
  3. package/dist/ai-chat-agent.js +340 -74
  4. package/dist/ai-chat-agent.js.map +1 -1
  5. package/dist/{ai-chat-v5-migration-DBHGW4Hv.js → ai-chat-v5-migration-BSiGZmYU.js} +1 -1
  6. package/dist/{ai-chat-v5-migration-DBHGW4Hv.js.map → ai-chat-v5-migration-BSiGZmYU.js.map} +1 -1
  7. package/dist/ai-chat-v5-migration.js +1 -1
  8. package/dist/ai-react.d.ts +14 -9
  9. package/dist/ai-react.js +164 -29
  10. package/dist/ai-react.js.map +1 -1
  11. package/dist/{ai-types-D5YoPrBZ.d.ts → ai-types-81H_-Uxh.d.ts} +15 -7
  12. package/dist/{ai-types-B3aQaFv3.js → ai-types-CrMqkwc_.js} +5 -1
  13. package/dist/ai-types-CrMqkwc_.js.map +1 -0
  14. package/dist/ai-types.d.ts +1 -1
  15. package/dist/ai-types.js +1 -1
  16. package/dist/{client-BfiZ3HQd.js → client-B3SR12TQ.js} +2 -2
  17. package/dist/{client-BfiZ3HQd.js.map → client-B3SR12TQ.js.map} +1 -1
  18. package/dist/{client-CbWe9FBd.d.ts → client-BAQA84dr.d.ts} +2 -2
  19. package/dist/client-BZq9qau2.js +1093 -0
  20. package/dist/client-BZq9qau2.js.map +1 -0
  21. package/dist/client-CsaP9Irq.d.ts +1528 -0
  22. package/dist/client.d.ts +2 -2
  23. package/dist/client.js +2 -2
  24. package/dist/codemode/ai.js +5 -5
  25. package/dist/{do-oauth-client-provider-DGc5pP0l.d.ts → do-oauth-client-provider-C2CHH5x-.d.ts} +1 -1
  26. package/dist/{do-oauth-client-provider-CswoD5Lu.js → do-oauth-client-provider-CwqK5SXm.js} +2 -1
  27. package/dist/do-oauth-client-provider-CwqK5SXm.js.map +1 -0
  28. package/dist/{index-DhJCaDWd.d.ts → index-BUle9RiP.d.ts} +2 -2
  29. package/dist/{index-BQLBXqnQ.d.ts → index-Bx5KK3VJ.d.ts} +44 -17
  30. package/dist/index.d.ts +6 -6
  31. package/dist/index.js +5 -5
  32. package/dist/mcp/client.d.ts +4 -4
  33. package/dist/mcp/client.js +2 -1
  34. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  35. package/dist/mcp/do-oauth-client-provider.js +1 -1
  36. package/dist/mcp/index.d.ts +11 -11
  37. package/dist/mcp/index.js +21 -14
  38. package/dist/mcp/index.js.map +1 -1
  39. package/dist/mcp/x402.js +10 -6
  40. package/dist/mcp/x402.js.map +1 -1
  41. package/dist/{mcp-Dw5vDrY8.d.ts → mcp-BwPscEiF.d.ts} +1 -1
  42. package/dist/observability/index.d.ts +2 -2
  43. package/dist/observability/index.js +5 -5
  44. package/dist/{react-Bu7EB5xh.d.ts → react-CbwD4fBf.d.ts} +4 -4
  45. package/dist/react.d.ts +9 -9
  46. package/dist/react.js +2 -2
  47. package/dist/react.js.map +1 -1
  48. package/dist/{serializable-CymX8ovI.d.ts → serializable-faDkMCai.d.ts} +1 -1
  49. package/dist/serializable.d.ts +1 -1
  50. package/dist/{src-CwIW7tU2.js → src-D_KKH_4c.js} +99 -131
  51. package/dist/src-D_KKH_4c.js.map +1 -0
  52. package/package.json +7 -7
  53. package/dist/ai-types-B3aQaFv3.js.map +0 -1
  54. package/dist/client-DZhjV_XA.js +0 -719
  55. package/dist/client-DZhjV_XA.js.map +0 -1
  56. package/dist/client-GfgZTqrS.d.ts +0 -5283
  57. package/dist/do-oauth-client-provider-CswoD5Lu.js.map +0 -1
  58. package/dist/src-CwIW7tU2.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"x402.js","names":["decoded: PaymentPayload","result: CallToolResult","listTools: typeof _listTools"],"sources":["../../src/mcp/x402.ts"],"sourcesContent":["/**\n * X402 MCP Integration\n *\n * Based on:\n * - Coinbase's x402 (Apache 2.0): https://github.com/coinbase/x402\n * - @ethanniser and his work at https://github.com/ethanniser/x402-mcp\n */\n\nimport type {\n McpServer,\n RegisteredTool,\n ToolCallback\n} from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Client as MCPClient } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type {\n CallToolResultSchema,\n CompatibilityCallToolResultSchema,\n CallToolRequest,\n CallToolResult,\n ToolAnnotations\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ZodRawShape } from \"zod\";\nimport { base, baseSepolia, type Chain } from \"viem/chains\";\n\nimport { processPriceToAtomicAmount } from \"x402/shared\";\nimport { exact } from \"x402/schemes\";\nimport { useFacilitator } from \"x402/verify\";\nimport type {\n FacilitatorConfig,\n Network,\n PaymentPayload,\n PaymentRequirements,\n Wallet\n} from \"x402/types\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport { createWalletClient, http, type Account } from \"viem\";\nimport { createPaymentHeader } from \"x402/client\";\n\n/*\n ======= SERVER SIDE =======\n*/\n\nexport type X402Config = {\n network: Network;\n recipient: `0x${string}`;\n facilitator: FacilitatorConfig;\n version?: number;\n};\n\nexport interface X402AugmentedServer {\n paidTool<Args extends ZodRawShape>(\n name: string,\n description: string,\n priceUSD: number,\n paramsSchema: Args,\n annotations: ToolAnnotations,\n cb: ToolCallback<Args>\n ): RegisteredTool;\n}\n\nexport function withX402<T extends McpServer>(\n server: McpServer,\n cfg: X402Config\n): T & X402AugmentedServer {\n const { verify, settle } = useFacilitator(cfg.facilitator);\n const x402Version = cfg.version ?? 1;\n\n function paidTool<Args extends ZodRawShape>(\n name: string,\n description: string,\n priceUSD: number,\n paramsSchema: Args,\n annotations: ToolAnnotations,\n cb: ToolCallback<Args>\n ): RegisteredTool {\n return server.tool(\n name,\n description,\n paramsSchema,\n { ...annotations, paymentHint: true, paymentPriceUSD: priceUSD },\n (async (args, extra) => {\n // Build PaymentRequirements for this call\n const atomic = processPriceToAtomicAmount(priceUSD, cfg.network);\n if (\"error\" in atomic) {\n const payload = { x402Version, error: \"PRICE_COMPUTE_FAILED\" };\n return {\n isError: true,\n _meta: { \"x402/error\": payload },\n content: [{ type: \"text\", text: JSON.stringify(payload) }]\n } as const;\n }\n const { maxAmountRequired, asset } = atomic;\n const requirements = {\n scheme: \"exact\" as const,\n network: cfg.network,\n maxAmountRequired,\n payTo: cfg.recipient,\n asset: asset.address,\n maxTimeoutSeconds: 300,\n resource: `x402://${name}`,\n mimeType: \"application/json\" as const,\n description,\n extra: \"eip712\" in asset ? asset.eip712 : undefined\n };\n\n // Get token either from MCP _meta or from header\n const headers = extra?.requestInfo?.headers ?? {};\n const token =\n (extra?._meta?.[\"x402/payment\"] as string | undefined) ??\n headers[\"X-PAYMENT\"];\n\n const paymentRequired = (\n reason = \"PAYMENT_REQUIRED\",\n extraFields: Record<string, unknown> = {}\n ) => {\n const payload = {\n x402Version,\n error: reason,\n accepts: [requirements],\n ...extraFields\n };\n return {\n isError: true,\n _meta: { \"x402/error\": payload },\n content: [{ type: \"text\", text: JSON.stringify(payload) }]\n } as const;\n };\n\n if (!token || typeof token !== \"string\") return paymentRequired();\n\n // Decode & verify\n let decoded: PaymentPayload;\n try {\n decoded = exact.evm.decodePayment(token);\n decoded.x402Version = x402Version;\n } catch {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n const vr = await verify(decoded, requirements);\n if (!vr.isValid) {\n return paymentRequired(vr.invalidReason ?? \"INVALID_PAYMENT\", {\n payer: vr.payer\n });\n }\n\n // Execute tool\n let result: CallToolResult;\n let failed = false;\n try {\n result = await cb(args, extra);\n if (\n result &&\n typeof result === \"object\" &&\n \"isError\" in result &&\n result.isError\n ) {\n failed = true;\n }\n } catch (e) {\n failed = true;\n result = {\n isError: true,\n content: [\n { type: \"text\", text: `Tool execution failed: ${String(e)}` }\n ]\n };\n }\n\n // Settle only on success\n if (!failed) {\n try {\n const s = await settle(decoded, requirements);\n if (s.success) {\n result._meta ??= {};\n result._meta[\"x402/payment-response\"] = {\n success: true,\n transaction: s.transaction,\n network: s.network,\n payer: s.payer\n };\n } else {\n return paymentRequired(s.errorReason ?? \"SETTLEMENT_FAILED\");\n }\n } catch {\n return paymentRequired(\"SETTLEMENT_FAILED\");\n }\n }\n\n return result;\n }) as ToolCallback<Args>\n );\n }\n\n Object.defineProperty(server, \"paidTool\", {\n value: paidTool,\n writable: false,\n enumerable: false,\n configurable: true\n });\n\n // Tell TS the object now also has the paidTool method\n return server as T & X402AugmentedServer;\n}\n\n/*\n ======= CLIENT SIDE =======\n*/\n\nconst toChain = (network: Network): Chain => {\n switch (network) {\n case \"base\":\n return base;\n case \"base-sepolia\":\n return baseSepolia;\n default:\n throw new Error(`Unsupported network: ${network}`);\n }\n};\n\nexport interface X402AugmentedClient {\n callTool(\n x402ConfirmationCallback:\n | ((payment: PaymentRequirements[]) => Promise<boolean>)\n | null,\n params: CallToolRequest[\"params\"],\n resultSchema?:\n | typeof CallToolResultSchema\n | typeof CompatibilityCallToolResultSchema,\n options?: RequestOptions\n ): Promise<CallToolResult>;\n}\n\nexport type X402ClientConfig = {\n network: Network; // we only support base and base-sepolia for now\n account: Account;\n maxPaymentValue?: bigint;\n version?: number;\n confirmationCallback?: (payment: PaymentRequirements[]) => Promise<boolean>; // Confirmation callback for payment\n};\n\nexport function withX402Client<T extends MCPClient>(\n client: T,\n x402Config: X402ClientConfig\n): X402AugmentedClient & T {\n const { network, account, version } = x402Config;\n const wallet = createWalletClient({\n account,\n transport: http(),\n chain: toChain(network)\n });\n\n const maxPaymentValue = x402Config.maxPaymentValue ?? BigInt(0.1 * 10 ** 6); // 0.10 USDC\n\n const _listTools = client.listTools.bind(client);\n\n // Wrap the original method to include payment information in the description\n const listTools: typeof _listTools = async (params, options) => {\n const toolsRes = await _listTools(params, options);\n toolsRes.tools = toolsRes.tools.map((tool) => {\n let description = tool.description;\n if (tool.annotations?.paymentHint) {\n const cost = tool.annotations?.paymentPriceUSD\n ? `$${tool.annotations?.paymentPriceUSD}`\n : \"an unknown amount\";\n description += ` (This is a paid tool, you will be charged ${cost} for its execution)`;\n }\n return {\n ...tool,\n description\n };\n });\n\n // Wrap each tool to add payment support\n\n return toolsRes;\n };\n\n const _callTool = client.callTool.bind(client);\n\n const callToolWithPayment = async (\n x402ConfirmationCallback:\n | ((payment: PaymentRequirements[]) => Promise<boolean>)\n | null,\n params: CallToolRequest[\"params\"],\n resultSchema?:\n | typeof CallToolResultSchema\n | typeof CompatibilityCallToolResultSchema,\n options?: RequestOptions\n ): ReturnType<typeof client.callTool> => {\n // call the tool\n const res = await _callTool(params, resultSchema, options);\n console.log(\"res\", res);\n\n // If it errored and returned accepts, we need to confirm payment\n const maybeX402Error = res._meta?.[\"x402/error\"] as\n | { accepts: PaymentRequirements[] }\n | undefined;\n\n if (\n res.isError &&\n maybeX402Error &&\n maybeX402Error.accepts &&\n Array.isArray(maybeX402Error.accepts) &&\n maybeX402Error.accepts.length > 0\n ) {\n const accepts = maybeX402Error.accepts;\n const confirmationCallback =\n x402ConfirmationCallback ?? x402Config.confirmationCallback;\n\n // Use the x402 confirmation callback if provided\n if (confirmationCallback && !(await confirmationCallback(accepts))) {\n return {\n isError: true,\n content: [{ type: \"text\", text: \"User declined payment\" }]\n };\n }\n\n // Pick the first exact-scheme requirement that matches our network\n // (we're only setting one on the McpAgent side for now)\n const req =\n accepts.find((a) => a?.scheme === \"exact\" && a?.network === network) ??\n accepts[0];\n\n if (!req || req.scheme !== \"exact\") return res;\n\n const maxAmountRequired = BigInt(req.maxAmountRequired);\n if (maxAmountRequired > maxPaymentValue) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Payment exceeds client cap: ${maxAmountRequired} > ${maxPaymentValue}`\n }\n ]\n };\n }\n\n // Use x402/client to get the X-PAYMENT token\n const token = await createPaymentHeader(\n wallet as Wallet,\n version ?? 1,\n req\n );\n\n // Call the tool with the payment token\n return _callTool(\n {\n ...params,\n _meta: {\n ...params._meta,\n \"x402/payment\": token\n }\n },\n resultSchema,\n options\n );\n }\n\n return res;\n };\n\n const _client = client as X402AugmentedClient & T;\n _client.listTools = listTools;\n Object.defineProperty(_client, \"callTool\", {\n value: callToolWithPayment,\n writable: false,\n enumerable: false,\n configurable: true\n });\n\n return _client;\n}\n"],"mappings":";;;;;;;;AA4DA,SAAgB,SACd,QACA,KACyB;CACzB,MAAM,EAAE,QAAQ,WAAW,eAAe,IAAI,YAAY;CAC1D,MAAM,cAAc,IAAI,WAAW;CAEnC,SAAS,SACP,MACA,aACA,UACA,cACA,aACA,IACgB;AAChB,SAAO,OAAO,KACZ,MACA,aACA,cACA;GAAE,GAAG;GAAa,aAAa;GAAM,iBAAiB;GAAU,GAC/D,OAAO,MAAM,UAAU;GAEtB,MAAM,SAAS,2BAA2B,UAAU,IAAI,QAAQ;AAChE,OAAI,WAAW,QAAQ;IACrB,MAAM,UAAU;KAAE;KAAa,OAAO;KAAwB;AAC9D,WAAO;KACL,SAAS;KACT,OAAO,EAAE,cAAc,SAAS;KAChC,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,KAAK,UAAU,QAAQ;MAAE,CAAC;KAC3D;;GAEH,MAAM,EAAE,mBAAmB,UAAU;GACrC,MAAM,eAAe;IACnB,QAAQ;IACR,SAAS,IAAI;IACb;IACA,OAAO,IAAI;IACX,OAAO,MAAM;IACb,mBAAmB;IACnB,UAAU,UAAU;IACpB,UAAU;IACV;IACA,OAAO,YAAY,QAAQ,MAAM,SAAS;IAC3C;GAGD,MAAM,UAAU,OAAO,aAAa,WAAW,EAAE;GACjD,MAAM,QACH,OAAO,QAAQ,mBAChB,QAAQ;GAEV,MAAM,mBACJ,SAAS,oBACT,cAAuC,EAAE,KACtC;IACH,MAAM,UAAU;KACd;KACA,OAAO;KACP,SAAS,CAAC,aAAa;KACvB,GAAG;KACJ;AACD,WAAO;KACL,SAAS;KACT,OAAO,EAAE,cAAc,SAAS;KAChC,SAAS,CAAC;MAAE,MAAM;MAAQ,MAAM,KAAK,UAAU,QAAQ;MAAE,CAAC;KAC3D;;AAGH,OAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO,iBAAiB;GAGjE,IAAIA;AACJ,OAAI;AACF,cAAU,MAAM,IAAI,cAAc,MAAM;AACxC,YAAQ,cAAc;WAChB;AACN,WAAO,gBAAgB,kBAAkB;;GAG3C,MAAM,KAAK,MAAM,OAAO,SAAS,aAAa;AAC9C,OAAI,CAAC,GAAG,QACN,QAAO,gBAAgB,GAAG,iBAAiB,mBAAmB,EAC5D,OAAO,GAAG,OACX,CAAC;GAIJ,IAAIC;GACJ,IAAI,SAAS;AACb,OAAI;AACF,aAAS,MAAM,GAAG,MAAM,MAAM;AAC9B,QACE,UACA,OAAO,WAAW,YAClB,aAAa,UACb,OAAO,QAEP,UAAS;YAEJ,GAAG;AACV,aAAS;AACT,aAAS;KACP,SAAS;KACT,SAAS,CACP;MAAE,MAAM;MAAQ,MAAM,0BAA0B,OAAO,EAAE;MAAI,CAC9D;KACF;;AAIH,OAAI,CAAC,OACH,KAAI;IACF,MAAM,IAAI,MAAM,OAAO,SAAS,aAAa;AAC7C,QAAI,EAAE,SAAS;AACb,YAAO,UAAU,EAAE;AACnB,YAAO,MAAM,2BAA2B;MACtC,SAAS;MACT,aAAa,EAAE;MACf,SAAS,EAAE;MACX,OAAO,EAAE;MACV;UAED,QAAO,gBAAgB,EAAE,eAAe,oBAAoB;WAExD;AACN,WAAO,gBAAgB,oBAAoB;;AAI/C,UAAO;KAEV;;AAGH,QAAO,eAAe,QAAQ,YAAY;EACxC,OAAO;EACP,UAAU;EACV,YAAY;EACZ,cAAc;EACf,CAAC;AAGF,QAAO;;AAOT,MAAM,WAAW,YAA4B;AAC3C,SAAQ,SAAR;EACE,KAAK,OACH,QAAO;EACT,KAAK,eACH,QAAO;EACT,QACE,OAAM,IAAI,MAAM,wBAAwB,UAAU;;;AAyBxD,SAAgB,eACd,QACA,YACyB;CACzB,MAAM,EAAE,SAAS,SAAS,YAAY;CACtC,MAAM,SAAS,mBAAmB;EAChC;EACA,WAAW,MAAM;EACjB,OAAO,QAAQ,QAAQ;EACxB,CAAC;CAEF,MAAM,kBAAkB,WAAW,mBAAmB,OAAO,KAAM,MAAM,EAAE;CAE3E,MAAM,aAAa,OAAO,UAAU,KAAK,OAAO;CAGhD,MAAMC,YAA+B,OAAO,QAAQ,YAAY;EAC9D,MAAM,WAAW,MAAM,WAAW,QAAQ,QAAQ;AAClD,WAAS,QAAQ,SAAS,MAAM,KAAK,SAAS;GAC5C,IAAI,cAAc,KAAK;AACvB,OAAI,KAAK,aAAa,aAAa;IACjC,MAAM,OAAO,KAAK,aAAa,kBAC3B,IAAI,KAAK,aAAa,oBACtB;AACJ,mBAAe,8CAA8C,KAAK;;AAEpE,UAAO;IACL,GAAG;IACH;IACD;IACD;AAIF,SAAO;;CAGT,MAAM,YAAY,OAAO,SAAS,KAAK,OAAO;CAE9C,MAAM,sBAAsB,OAC1B,0BAGA,QACA,cAGA,YACuC;EAEvC,MAAM,MAAM,MAAM,UAAU,QAAQ,cAAc,QAAQ;AAC1D,UAAQ,IAAI,OAAO,IAAI;EAGvB,MAAM,iBAAiB,IAAI,QAAQ;AAInC,MACE,IAAI,WACJ,kBACA,eAAe,WACf,MAAM,QAAQ,eAAe,QAAQ,IACrC,eAAe,QAAQ,SAAS,GAChC;GACA,MAAM,UAAU,eAAe;GAC/B,MAAM,uBACJ,4BAA4B,WAAW;AAGzC,OAAI,wBAAwB,CAAE,MAAM,qBAAqB,QAAQ,CAC/D,QAAO;IACL,SAAS;IACT,SAAS,CAAC;KAAE,MAAM;KAAQ,MAAM;KAAyB,CAAC;IAC3D;GAKH,MAAM,MACJ,QAAQ,MAAM,MAAM,GAAG,WAAW,WAAW,GAAG,YAAY,QAAQ,IACpE,QAAQ;AAEV,OAAI,CAAC,OAAO,IAAI,WAAW,QAAS,QAAO;GAE3C,MAAM,oBAAoB,OAAO,IAAI,kBAAkB;AACvD,OAAI,oBAAoB,gBACtB,QAAO;IACL,SAAS;IACT,SAAS,CACP;KACE,MAAM;KACN,MAAM,+BAA+B,kBAAkB,KAAK;KAC7D,CACF;IACF;GAIH,MAAM,QAAQ,MAAM,oBAClB,QACA,WAAW,GACX,IACD;AAGD,UAAO,UACL;IACE,GAAG;IACH,OAAO;KACL,GAAG,OAAO;KACV,gBAAgB;KACjB;IACF,EACD,cACA,QACD;;AAGH,SAAO;;CAGT,MAAM,UAAU;AAChB,SAAQ,YAAY;AACpB,QAAO,eAAe,SAAS,YAAY;EACzC,OAAO;EACP,UAAU;EACV,YAAY;EACZ,cAAc;EACf,CAAC;AAEF,QAAO"}
1
+ {"version":3,"file":"x402.js","names":["decoded: PaymentPayload","result: CallToolResult","listTools: typeof _listTools"],"sources":["../../src/mcp/x402.ts"],"sourcesContent":["/**\n * X402 MCP Integration\n *\n * Based on:\n * - Coinbase's x402 (Apache 2.0): https://github.com/coinbase/x402\n * - @ethanniser and his work at https://github.com/ethanniser/x402-mcp\n */\n\nimport type {\n McpServer,\n RegisteredTool,\n ToolCallback\n} from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { Client as MCPClient } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type {\n CallToolResultSchema,\n CompatibilityCallToolResultSchema,\n CallToolRequest,\n CallToolResult,\n ToolAnnotations\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { ZodRawShape } from \"zod\";\nimport { base, baseSepolia, type Chain } from \"viem/chains\";\n\nimport { processPriceToAtomicAmount } from \"x402/shared\";\nimport { exact } from \"x402/schemes\";\nimport { useFacilitator } from \"x402/verify\";\nimport type {\n FacilitatorConfig,\n Network,\n PaymentPayload,\n PaymentRequirements,\n Wallet\n} from \"x402/types\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport { createWalletClient, http, type Account } from \"viem\";\nimport { createPaymentHeader } from \"x402/client\";\n\n/*\n ======= SERVER SIDE =======\n*/\n\nexport type X402Config = {\n network: Network;\n recipient: `0x${string}`;\n facilitator: FacilitatorConfig;\n version?: number;\n};\n\nexport interface X402AugmentedServer {\n paidTool<Args extends ZodRawShape>(\n name: string,\n description: string,\n priceUSD: number,\n paramsSchema: Args,\n annotations: ToolAnnotations,\n cb: ToolCallback<Args>\n ): RegisteredTool;\n}\n\nexport function withX402<T extends McpServer>(\n server: McpServer,\n cfg: X402Config\n): T & X402AugmentedServer {\n const { verify, settle } = useFacilitator(cfg.facilitator);\n const x402Version = cfg.version ?? 1;\n\n function paidTool<Args extends ZodRawShape>(\n name: string,\n description: string,\n priceUSD: number,\n paramsSchema: Args,\n annotations: ToolAnnotations,\n cb: ToolCallback<Args>\n ): RegisteredTool {\n return server.registerTool(\n name,\n {\n description,\n inputSchema: paramsSchema,\n annotations,\n _meta: {\n \"agents-x402/paymentRequired\": true,\n \"agents-x402/priceUSD\": priceUSD\n }\n },\n (async (args, extra) => {\n // Build PaymentRequirements for this call\n const atomic = processPriceToAtomicAmount(priceUSD, cfg.network);\n if (\"error\" in atomic) {\n const payload = { x402Version, error: \"PRICE_COMPUTE_FAILED\" };\n return {\n isError: true,\n _meta: { \"x402/error\": payload },\n content: [{ type: \"text\", text: JSON.stringify(payload) }]\n } as const;\n }\n const { maxAmountRequired, asset } = atomic;\n const requirements = {\n scheme: \"exact\" as const,\n network: cfg.network,\n maxAmountRequired,\n payTo: cfg.recipient,\n asset: asset.address,\n maxTimeoutSeconds: 300,\n resource: `x402://${name}`,\n mimeType: \"application/json\" as const,\n description,\n extra: \"eip712\" in asset ? asset.eip712 : undefined\n };\n\n // Get token either from MCP _meta or from header\n const headers = extra?.requestInfo?.headers ?? {};\n const token =\n (extra?._meta?.[\"x402/payment\"] as string | undefined) ??\n headers[\"X-PAYMENT\"];\n\n const paymentRequired = (\n reason = \"PAYMENT_REQUIRED\",\n extraFields: Record<string, unknown> = {}\n ) => {\n const payload = {\n x402Version,\n error: reason,\n accepts: [requirements],\n ...extraFields\n };\n return {\n isError: true,\n _meta: { \"x402/error\": payload },\n content: [{ type: \"text\", text: JSON.stringify(payload) }]\n } as const;\n };\n\n if (!token || typeof token !== \"string\") return paymentRequired();\n\n // Decode & verify\n let decoded: PaymentPayload;\n try {\n decoded = exact.evm.decodePayment(token);\n decoded.x402Version = x402Version;\n } catch {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n const vr = await verify(decoded, requirements);\n if (!vr.isValid) {\n return paymentRequired(vr.invalidReason ?? \"INVALID_PAYMENT\", {\n payer: vr.payer\n });\n }\n\n // Execute tool\n let result: CallToolResult;\n let failed = false;\n try {\n result = await cb(args, extra);\n if (\n result &&\n typeof result === \"object\" &&\n \"isError\" in result &&\n result.isError\n ) {\n failed = true;\n }\n } catch (e) {\n failed = true;\n result = {\n isError: true,\n content: [\n { type: \"text\", text: `Tool execution failed: ${String(e)}` }\n ]\n };\n }\n\n // Settle only on success\n if (!failed) {\n try {\n const s = await settle(decoded, requirements);\n if (s.success) {\n result._meta ??= {};\n result._meta[\"x402/payment-response\"] = {\n success: true,\n transaction: s.transaction,\n network: s.network,\n payer: s.payer\n };\n } else {\n return paymentRequired(s.errorReason ?? \"SETTLEMENT_FAILED\");\n }\n } catch {\n return paymentRequired(\"SETTLEMENT_FAILED\");\n }\n }\n\n return result;\n }) as ToolCallback<Args>\n );\n }\n\n Object.defineProperty(server, \"paidTool\", {\n value: paidTool,\n writable: false,\n enumerable: false,\n configurable: true\n });\n\n // Tell TS the object now also has the paidTool method\n return server as T & X402AugmentedServer;\n}\n\n/*\n ======= CLIENT SIDE =======\n*/\n\nconst toChain = (network: Network): Chain => {\n switch (network) {\n case \"base\":\n return base;\n case \"base-sepolia\":\n return baseSepolia;\n default:\n throw new Error(`Unsupported network: ${network}`);\n }\n};\n\nexport interface X402AugmentedClient {\n callTool(\n x402ConfirmationCallback:\n | ((payment: PaymentRequirements[]) => Promise<boolean>)\n | null,\n params: CallToolRequest[\"params\"],\n resultSchema?:\n | typeof CallToolResultSchema\n | typeof CompatibilityCallToolResultSchema,\n options?: RequestOptions\n ): Promise<CallToolResult>;\n}\n\nexport type X402ClientConfig = {\n network: Network; // we only support base and base-sepolia for now\n account: Account;\n maxPaymentValue?: bigint;\n version?: number;\n confirmationCallback?: (payment: PaymentRequirements[]) => Promise<boolean>; // Confirmation callback for payment\n};\n\nexport function withX402Client<T extends MCPClient>(\n client: T,\n x402Config: X402ClientConfig\n): X402AugmentedClient & T {\n const { network, account, version } = x402Config;\n const wallet = createWalletClient({\n account,\n transport: http(),\n chain: toChain(network)\n });\n\n const maxPaymentValue = x402Config.maxPaymentValue ?? BigInt(0.1 * 10 ** 6); // 0.10 USDC\n\n const _listTools = client.listTools.bind(client);\n\n // Wrap the original method to include payment information in the description\n const listTools: typeof _listTools = async (params, options) => {\n const toolsRes = await _listTools(params, options);\n toolsRes.tools = toolsRes.tools.map((tool) => {\n let description = tool.description;\n // Check _meta for payment information (agents-x402/ is our extension for pre-advertising prices)\n if (tool._meta?.[\"agents-x402/paymentRequired\"]) {\n const cost = tool._meta?.[\"agents-x402/priceUSD\"]\n ? `$${tool._meta?.[\"agents-x402/priceUSD\"]}`\n : \"an unknown amount\";\n description += ` (This is a paid tool, you will be charged ${cost} for its execution)`;\n }\n return {\n ...tool,\n description\n };\n });\n\n // Wrap each tool to add payment support\n\n return toolsRes;\n };\n\n const _callTool = client.callTool.bind(client);\n\n const callToolWithPayment = async (\n x402ConfirmationCallback:\n | ((payment: PaymentRequirements[]) => Promise<boolean>)\n | null,\n params: CallToolRequest[\"params\"],\n resultSchema?:\n | typeof CallToolResultSchema\n | typeof CompatibilityCallToolResultSchema,\n options?: RequestOptions\n ): ReturnType<typeof client.callTool> => {\n // call the tool\n const res = await _callTool(params, resultSchema, options);\n console.log(\"res\", res);\n\n // If it errored and returned accepts, we need to confirm payment\n const maybeX402Error = res._meta?.[\"x402/error\"] as\n | { accepts: PaymentRequirements[] }\n | undefined;\n\n if (\n res.isError &&\n maybeX402Error &&\n maybeX402Error.accepts &&\n Array.isArray(maybeX402Error.accepts) &&\n maybeX402Error.accepts.length > 0\n ) {\n const accepts = maybeX402Error.accepts;\n const confirmationCallback =\n x402ConfirmationCallback ?? x402Config.confirmationCallback;\n\n // Use the x402 confirmation callback if provided\n if (confirmationCallback && !(await confirmationCallback(accepts))) {\n return {\n isError: true,\n content: [{ type: \"text\", text: \"User declined payment\" }]\n };\n }\n\n // Pick the first exact-scheme requirement that matches our network\n // (we're only setting one on the McpAgent side for now)\n const req =\n accepts.find((a) => a?.scheme === \"exact\" && a?.network === network) ??\n accepts[0];\n\n if (!req || req.scheme !== \"exact\") return res;\n\n const maxAmountRequired = BigInt(req.maxAmountRequired);\n if (maxAmountRequired > maxPaymentValue) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Payment exceeds client cap: ${maxAmountRequired} > ${maxPaymentValue}`\n }\n ]\n };\n }\n\n // Use x402/client to get the X-PAYMENT token\n const token = await createPaymentHeader(\n wallet as Wallet,\n version ?? 1,\n req\n );\n\n // Call the tool with the payment token\n return _callTool(\n {\n ...params,\n _meta: {\n ...params._meta,\n \"x402/payment\": token\n }\n },\n resultSchema,\n options\n );\n }\n\n return res;\n };\n\n const _client = client as X402AugmentedClient & T;\n _client.listTools = listTools;\n Object.defineProperty(_client, \"callTool\", {\n value: callToolWithPayment,\n writable: false,\n enumerable: false,\n configurable: true\n });\n\n return _client;\n}\n"],"mappings":"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"}
@@ -58,4 +58,4 @@ type MCPObservabilityEvent =
58
58
  | BaseEvent<"mcp:client:discover", {}>;
59
59
  //#endregion
60
60
  export { BaseEvent as n, MCPObservabilityEvent as t };
61
- //# sourceMappingURL=mcp-Dw5vDrY8.d.ts.map
61
+ //# sourceMappingURL=mcp-BwPscEiF.d.ts.map
@@ -1,3 +1,3 @@
1
- import "../mcp-Dw5vDrY8.js";
2
- import { n as ObservabilityEvent, r as genericObservability, t as Observability } from "../index-DhJCaDWd.js";
1
+ import "../mcp-BwPscEiF.js";
2
+ import { n as ObservabilityEvent, r as genericObservability, t as Observability } from "../index-BUle9RiP.js";
3
3
  export { Observability, ObservabilityEvent, genericObservability };
@@ -1,7 +1,7 @@
1
- import "../ai-types-B3aQaFv3.js";
2
- import "../client-BfiZ3HQd.js";
3
- import "../client-DZhjV_XA.js";
4
- import "../do-oauth-client-provider-CswoD5Lu.js";
5
- import { f as genericObservability } from "../src-CwIW7tU2.js";
1
+ import "../ai-types-CrMqkwc_.js";
2
+ import "../client-B3SR12TQ.js";
3
+ import "../client-BZq9qau2.js";
4
+ import "../do-oauth-client-provider-CwqK5SXm.js";
5
+ import { f as genericObservability } from "../src-D_KKH_4c.js";
6
6
 
7
7
  export { genericObservability };
@@ -1,6 +1,6 @@
1
- import { m as MCPServersState, t as Agent } from "./index-BQLBXqnQ.js";
2
- import { n as RPCMethod, t as Method } from "./serializable-CymX8ovI.js";
3
- import { i as StreamOptions } from "./client-CbWe9FBd.js";
1
+ import { m as MCPServersState, t as Agent } from "./index-Bx5KK3VJ.js";
2
+ import { n as RPCMethod, t as Method } from "./serializable-faDkMCai.js";
3
+ import { i as StreamOptions } from "./client-BAQA84dr.js";
4
4
  import { PartySocket } from "partysocket";
5
5
  import { usePartySocket } from "partysocket/react";
6
6
 
@@ -110,4 +110,4 @@ declare function useAgent<
110
110
  };
111
111
  //#endregion
112
112
  export { useAgent as n, UseAgentOptions as t };
113
- //# sourceMappingURL=react-Bu7EB5xh.d.ts.map
113
+ //# sourceMappingURL=react-CbwD4fBf.d.ts.map
package/dist/react.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import "./client-GfgZTqrS.js";
2
- import "./mcp-Dw5vDrY8.js";
3
- import "./do-oauth-client-provider-DGc5pP0l.js";
4
- import "./index-DhJCaDWd.js";
5
- import "./ai-types-D5YoPrBZ.js";
6
- import "./index-BQLBXqnQ.js";
7
- import "./serializable-CymX8ovI.js";
8
- import "./client-CbWe9FBd.js";
9
- import { n as useAgent, t as UseAgentOptions } from "./react-Bu7EB5xh.js";
1
+ import "./client-CsaP9Irq.js";
2
+ import "./mcp-BwPscEiF.js";
3
+ import "./do-oauth-client-provider-C2CHH5x-.js";
4
+ import "./index-BUle9RiP.js";
5
+ import "./ai-types-81H_-Uxh.js";
6
+ import "./index-Bx5KK3VJ.js";
7
+ import "./serializable-faDkMCai.js";
8
+ import "./client-BAQA84dr.js";
9
+ import { n as useAgent, t as UseAgentOptions } from "./react-CbwD4fBf.js";
10
10
  export { UseAgentOptions, useAgent };
package/dist/react.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as MessageType } from "./ai-types-B3aQaFv3.js";
1
+ import { t as MessageType } from "./ai-types-CrMqkwc_.js";
2
2
  import { use, useCallback, useEffect, useMemo, useRef } from "react";
3
3
  import { usePartySocket } from "partysocket/react";
4
4
 
@@ -61,7 +61,7 @@ function createCacheKey(agentNamespace, name, deps) {
61
61
  }
62
62
  function useAgent(options) {
63
63
  const agentNamespace = camelCaseToKebabCase(options.agent);
64
- const { query, queryDeps, cacheTtl,...restOptions } = options;
64
+ const { query, queryDeps, cacheTtl, ...restOptions } = options;
65
65
  const pendingCallsRef = useRef(/* @__PURE__ */ new Map());
66
66
  const cacheKey = useMemo(() => {
67
67
  const deps = queryDeps || [];
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":["resolvedQuery: QueryObject | undefined","parsedMessage: Record<string, unknown>","request: RPCRequest"],"sources":["../src/react.tsx"],"sourcesContent":["import type { PartySocket } from \"partysocket\";\nimport { usePartySocket } from \"partysocket/react\";\nimport { useCallback, useRef, use, useMemo, useEffect } from \"react\";\nimport type { Agent, MCPServersState, RPCRequest, RPCResponse } from \"./\";\nimport type { StreamOptions } from \"./client\";\nimport type { Method, RPCMethod } from \"./serializable\";\nimport { MessageType } from \"./ai-types\";\n\n/**\n * Convert a camelCase string to a kebab-case string\n * @param str The string to convert\n * @returns The kebab-case string\n */\nfunction camelCaseToKebabCase(str: string): string {\n // If string is all uppercase, convert to lowercase\n if (str === str.toUpperCase() && str !== str.toLowerCase()) {\n return str.toLowerCase().replace(/_/g, \"-\");\n }\n\n // Otherwise handle camelCase to kebab-case\n let kebabified = str.replace(\n /[A-Z]/g,\n (letter) => `-${letter.toLowerCase()}`\n );\n kebabified = kebabified.startsWith(\"-\") ? kebabified.slice(1) : kebabified;\n // Convert any remaining underscores to hyphens and remove trailing -'s\n return kebabified.replace(/_/g, \"-\").replace(/-$/, \"\");\n}\n\ntype QueryObject = Record<string, string | null>;\n\nconst queryCache = new Map<\n unknown[],\n {\n promise: Promise<QueryObject>;\n refCount: number;\n expiresAt: number;\n cacheTtl?: number;\n }\n>();\n\nfunction arraysEqual(a: unknown[], b: unknown[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) return false;\n }\n return true;\n}\n\nfunction findCacheEntry(\n targetKey: unknown[]\n): Promise<QueryObject> | undefined {\n for (const [existingKey, entry] of queryCache.entries()) {\n if (arraysEqual(existingKey, targetKey)) {\n // Check if entry has expired\n if (Date.now() > entry.expiresAt) {\n queryCache.delete(existingKey);\n return undefined;\n }\n entry.refCount++;\n return entry.promise;\n }\n }\n return undefined;\n}\n\nfunction setCacheEntry(\n key: unknown[],\n value: Promise<QueryObject>,\n cacheTtl?: number\n): void {\n // Remove any existing entry with matching members\n for (const [existingKey] of queryCache.entries()) {\n if (arraysEqual(existingKey, key)) {\n queryCache.delete(existingKey);\n break;\n }\n }\n\n const expiresAt = cacheTtl\n ? Date.now() + cacheTtl\n : Date.now() + 5 * 60 * 1000; // Default 5 minutes\n queryCache.set(key, { promise: value, refCount: 1, expiresAt, cacheTtl });\n}\n\nfunction decrementCacheEntry(targetKey: unknown[]): boolean {\n for (const [existingKey, entry] of queryCache.entries()) {\n if (arraysEqual(existingKey, targetKey)) {\n entry.refCount--;\n if (entry.refCount <= 0) {\n queryCache.delete(existingKey);\n }\n return true;\n }\n }\n return false;\n}\n\nfunction createCacheKey(\n agentNamespace: string,\n name: string | undefined,\n deps: unknown[]\n): unknown[] {\n return [agentNamespace, name || \"default\", ...deps];\n}\n\n/**\n * Options for the useAgent hook\n * @template State Type of the Agent's state\n */\nexport type UseAgentOptions<State = unknown> = Omit<\n Parameters<typeof usePartySocket>[0],\n \"party\" | \"room\" | \"query\"\n> & {\n /** Name of the agent to connect to */\n agent: string;\n /** Name of the specific Agent instance */\n name?: string;\n /** Query parameters - can be static object or async function */\n query?: QueryObject | (() => Promise<QueryObject>);\n /** Dependencies for async query caching */\n queryDeps?: unknown[];\n /** Cache TTL in milliseconds for auth tokens/time-sensitive data */\n cacheTtl?: number;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n /** Called when MCP server state is updated */\n onMcpUpdate?: (mcpServers: MCPServersState) => void;\n};\n\ntype AllOptional<T> = T extends [infer A, ...infer R]\n ? undefined extends A\n ? AllOptional<R>\n : false\n : true; // no params means optional by default\n\ntype RPCMethods<T> = {\n [K in keyof T as T[K] extends RPCMethod<T[K]> ? K : never]: RPCMethod<T[K]>;\n};\n\ntype OptionalParametersMethod<T extends RPCMethod> =\n AllOptional<Parameters<T>> extends true ? T : never;\n\n// all methods of the Agent, excluding the ones that are declared in the base Agent class\n// biome-ignore lint: suppressions/parse\ntype AgentMethods<T> = Omit<RPCMethods<T>, keyof Agent<any, any>>;\n\ntype OptionalAgentMethods<T> = {\n [K in keyof AgentMethods<T> as AgentMethods<T>[K] extends OptionalParametersMethod<\n AgentMethods<T>[K]\n >\n ? K\n : never]: OptionalParametersMethod<AgentMethods<T>[K]>;\n};\n\ntype RequiredAgentMethods<T> = Omit<\n AgentMethods<T>,\n keyof OptionalAgentMethods<T>\n>;\n\ntype AgentPromiseReturnType<T, K extends keyof AgentMethods<T>> =\n // biome-ignore lint: suppressions/parse\n ReturnType<AgentMethods<T>[K]> extends Promise<any>\n ? ReturnType<AgentMethods<T>[K]>\n : Promise<ReturnType<AgentMethods<T>[K]>>;\n\ntype OptionalArgsAgentMethodCall<AgentT> = <\n K extends keyof OptionalAgentMethods<AgentT>\n>(\n method: K,\n args?: Parameters<OptionalAgentMethods<AgentT>[K]>,\n streamOptions?: StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype RequiredArgsAgentMethodCall<AgentT> = <\n K extends keyof RequiredAgentMethods<AgentT>\n>(\n method: K,\n args: Parameters<RequiredAgentMethods<AgentT>[K]>,\n streamOptions?: StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype AgentMethodCall<AgentT> = OptionalArgsAgentMethodCall<AgentT> &\n RequiredArgsAgentMethodCall<AgentT>;\n\ntype UntypedAgentMethodCall = <T = unknown>(\n method: string,\n args?: unknown[],\n streamOptions?: StreamOptions\n) => Promise<T>;\n\ntype AgentStub<T> = {\n [K in keyof AgentMethods<T>]: (\n ...args: Parameters<AgentMethods<T>[K]>\n ) => AgentPromiseReturnType<AgentMethods<T>, K>;\n};\n\n// we neet to use Method instead of RPCMethod here for retro-compatibility\ntype UntypedAgentStub = Record<string, Method>;\n\n/**\n * React hook for connecting to an Agent\n */\nexport function useAgent<State = unknown>(\n options: UseAgentOptions<State>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n};\nexport function useAgent<\n AgentT extends {\n get state(): State;\n },\n State\n>(\n options: UseAgentOptions<State>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: AgentMethodCall<AgentT>;\n stub: AgentStub<AgentT>;\n};\nexport function useAgent<State>(\n options: UseAgentOptions<unknown>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall | AgentMethodCall<unknown>;\n stub: UntypedAgentStub;\n} {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n const { query, queryDeps, cacheTtl, ...restOptions } = options;\n\n // Keep track of pending RPC calls\n const pendingCallsRef = useRef(\n new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n }\n >()\n );\n\n // Handle both sync and async query patterns\n const cacheKey = useMemo(() => {\n const deps = queryDeps || [];\n return createCacheKey(agentNamespace, options.name, deps);\n }, [agentNamespace, options.name, queryDeps]);\n\n const queryPromise = useMemo(() => {\n if (!query || typeof query !== \"function\") {\n return null;\n }\n\n const existingPromise = findCacheEntry(cacheKey);\n if (existingPromise) {\n return existingPromise;\n }\n\n const promise = query().catch((error) => {\n console.error(\n `[useAgent] Query failed for agent \"${options.agent}\":`,\n error\n );\n decrementCacheEntry(cacheKey); // Remove failed promise from cache\n throw error; // Re-throw for Suspense error boundary\n });\n\n setCacheEntry(cacheKey, promise, cacheTtl);\n\n return promise;\n }, [cacheKey, query, options.agent, cacheTtl]);\n\n let resolvedQuery: QueryObject | undefined;\n\n if (query) {\n if (typeof query === \"function\") {\n // Use React's use() to resolve the promise\n const queryResult = use(queryPromise!);\n\n // Check for non-primitive values and warn\n if (queryResult) {\n for (const [key, value] of Object.entries(queryResult)) {\n if (\n value !== null &&\n value !== undefined &&\n typeof value !== \"string\" &&\n typeof value !== \"number\" &&\n typeof value !== \"boolean\"\n ) {\n console.warn(\n `[useAgent] Query parameter \"${key}\" is an object and will be converted to \"[object Object]\". ` +\n \"Query parameters should be string, number, boolean, or null.\"\n );\n }\n }\n resolvedQuery = queryResult;\n }\n } else {\n // Sync query - use directly\n resolvedQuery = query;\n }\n }\n\n // Cleanup cache on unmount\n useEffect(() => {\n return () => {\n if (queryPromise) {\n decrementCacheEntry(cacheKey);\n }\n };\n }, [cacheKey, queryPromise]);\n\n const agent = usePartySocket({\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n query: resolvedQuery,\n ...restOptions,\n onMessage: (message) => {\n if (typeof message.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(message.data);\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return options.onMessage?.(message);\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_MCP_SERVERS) {\n options.onMcpUpdate?.(parsedMessage.mcp as MCPServersState);\n return;\n }\n if (parsedMessage.type === MessageType.RPC) {\n const response = parsedMessage as RPCResponse;\n const pending = pendingCallsRef.current.get(response.id);\n if (!pending) return;\n\n if (!response.success) {\n pending.reject(new Error(response.error));\n pendingCallsRef.current.delete(response.id);\n pending.stream?.onError?.(response.error);\n return;\n }\n\n // Handle streaming responses\n if (\"done\" in response) {\n if (response.done) {\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n pending.stream?.onDone?.(response.result);\n } else {\n pending.stream?.onChunk?.(response.result);\n }\n } else {\n // Non-streaming response\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n }\n return;\n }\n }\n options.onMessage?.(message);\n }\n }) as PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n };\n // Create the call method\n const call = useCallback(\n <T = unknown,>(\n method: string,\n args: unknown[] = [],\n streamOptions?: StreamOptions\n ): Promise<T> => {\n return new Promise((resolve, reject) => {\n const id = Math.random().toString(36).slice(2);\n pendingCallsRef.current.set(id, {\n reject,\n resolve: resolve as (value: unknown) => void,\n stream: streamOptions\n });\n\n const request: RPCRequest = {\n args,\n id,\n method,\n type: MessageType.RPC\n };\n\n agent.send(JSON.stringify(request));\n });\n },\n [agent]\n );\n\n agent.setState = (state: State) => {\n agent.send(JSON.stringify({ state, type: MessageType.CF_AGENT_STATE }));\n options.onStateUpdate?.(state, \"client\");\n };\n\n agent.call = call;\n agent.agent = agentNamespace;\n agent.name = options.name || \"default\";\n // biome-ignore lint: suppressions/parse\n agent.stub = new Proxy<any>(\n {},\n {\n get: (_target, method) => {\n return (...args: unknown[]) => {\n return call(method as string, args);\n };\n }\n }\n );\n\n // warn if agent isn't in lowercase\n if (agent.agent !== agent.agent.toLowerCase()) {\n console.warn(\n `Agent name: ${agent.agent} should probably be in lowercase. Received: ${agent.agent}`\n );\n }\n\n return agent;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"react.js","names":["resolvedQuery: QueryObject | undefined","parsedMessage: Record<string, unknown>","request: RPCRequest"],"sources":["../src/react.tsx"],"sourcesContent":["import type { PartySocket } from \"partysocket\";\nimport { usePartySocket } from \"partysocket/react\";\nimport { useCallback, useRef, use, useMemo, useEffect } from \"react\";\nimport type { Agent, MCPServersState, RPCRequest, RPCResponse } from \"./\";\nimport type { StreamOptions } from \"./client\";\nimport type { Method, RPCMethod } from \"./serializable\";\nimport { MessageType } from \"./ai-types\";\n\n/**\n * Convert a camelCase string to a kebab-case string\n * @param str The string to convert\n * @returns The kebab-case string\n */\nfunction camelCaseToKebabCase(str: string): string {\n // If string is all uppercase, convert to lowercase\n if (str === str.toUpperCase() && str !== str.toLowerCase()) {\n return str.toLowerCase().replace(/_/g, \"-\");\n }\n\n // Otherwise handle camelCase to kebab-case\n let kebabified = str.replace(\n /[A-Z]/g,\n (letter) => `-${letter.toLowerCase()}`\n );\n kebabified = kebabified.startsWith(\"-\") ? kebabified.slice(1) : kebabified;\n // Convert any remaining underscores to hyphens and remove trailing -'s\n return kebabified.replace(/_/g, \"-\").replace(/-$/, \"\");\n}\n\ntype QueryObject = Record<string, string | null>;\n\nconst queryCache = new Map<\n unknown[],\n {\n promise: Promise<QueryObject>;\n refCount: number;\n expiresAt: number;\n cacheTtl?: number;\n }\n>();\n\nfunction arraysEqual(a: unknown[], b: unknown[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n\n for (let i = 0; i < a.length; i++) {\n if (!Object.is(a[i], b[i])) return false;\n }\n return true;\n}\n\nfunction findCacheEntry(\n targetKey: unknown[]\n): Promise<QueryObject> | undefined {\n for (const [existingKey, entry] of queryCache.entries()) {\n if (arraysEqual(existingKey, targetKey)) {\n // Check if entry has expired\n if (Date.now() > entry.expiresAt) {\n queryCache.delete(existingKey);\n return undefined;\n }\n entry.refCount++;\n return entry.promise;\n }\n }\n return undefined;\n}\n\nfunction setCacheEntry(\n key: unknown[],\n value: Promise<QueryObject>,\n cacheTtl?: number\n): void {\n // Remove any existing entry with matching members\n for (const [existingKey] of queryCache.entries()) {\n if (arraysEqual(existingKey, key)) {\n queryCache.delete(existingKey);\n break;\n }\n }\n\n const expiresAt = cacheTtl\n ? Date.now() + cacheTtl\n : Date.now() + 5 * 60 * 1000; // Default 5 minutes\n queryCache.set(key, { promise: value, refCount: 1, expiresAt, cacheTtl });\n}\n\nfunction decrementCacheEntry(targetKey: unknown[]): boolean {\n for (const [existingKey, entry] of queryCache.entries()) {\n if (arraysEqual(existingKey, targetKey)) {\n entry.refCount--;\n if (entry.refCount <= 0) {\n queryCache.delete(existingKey);\n }\n return true;\n }\n }\n return false;\n}\n\nfunction createCacheKey(\n agentNamespace: string,\n name: string | undefined,\n deps: unknown[]\n): unknown[] {\n return [agentNamespace, name || \"default\", ...deps];\n}\n\n/**\n * Options for the useAgent hook\n * @template State Type of the Agent's state\n */\nexport type UseAgentOptions<State = unknown> = Omit<\n Parameters<typeof usePartySocket>[0],\n \"party\" | \"room\" | \"query\"\n> & {\n /** Name of the agent to connect to */\n agent: string;\n /** Name of the specific Agent instance */\n name?: string;\n /** Query parameters - can be static object or async function */\n query?: QueryObject | (() => Promise<QueryObject>);\n /** Dependencies for async query caching */\n queryDeps?: unknown[];\n /** Cache TTL in milliseconds for auth tokens/time-sensitive data */\n cacheTtl?: number;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n /** Called when MCP server state is updated */\n onMcpUpdate?: (mcpServers: MCPServersState) => void;\n};\n\ntype AllOptional<T> = T extends [infer A, ...infer R]\n ? undefined extends A\n ? AllOptional<R>\n : false\n : true; // no params means optional by default\n\ntype RPCMethods<T> = {\n [K in keyof T as T[K] extends RPCMethod<T[K]> ? K : never]: RPCMethod<T[K]>;\n};\n\ntype OptionalParametersMethod<T extends RPCMethod> =\n AllOptional<Parameters<T>> extends true ? T : never;\n\n// all methods of the Agent, excluding the ones that are declared in the base Agent class\n// biome-ignore lint: suppressions/parse\ntype AgentMethods<T> = Omit<RPCMethods<T>, keyof Agent<any, any>>;\n\ntype OptionalAgentMethods<T> = {\n [K in keyof AgentMethods<T> as AgentMethods<T>[K] extends OptionalParametersMethod<\n AgentMethods<T>[K]\n >\n ? K\n : never]: OptionalParametersMethod<AgentMethods<T>[K]>;\n};\n\ntype RequiredAgentMethods<T> = Omit<\n AgentMethods<T>,\n keyof OptionalAgentMethods<T>\n>;\n\ntype AgentPromiseReturnType<T, K extends keyof AgentMethods<T>> =\n // biome-ignore lint: suppressions/parse\n ReturnType<AgentMethods<T>[K]> extends Promise<any>\n ? ReturnType<AgentMethods<T>[K]>\n : Promise<ReturnType<AgentMethods<T>[K]>>;\n\ntype OptionalArgsAgentMethodCall<AgentT> = <\n K extends keyof OptionalAgentMethods<AgentT>\n>(\n method: K,\n args?: Parameters<OptionalAgentMethods<AgentT>[K]>,\n streamOptions?: StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype RequiredArgsAgentMethodCall<AgentT> = <\n K extends keyof RequiredAgentMethods<AgentT>\n>(\n method: K,\n args: Parameters<RequiredAgentMethods<AgentT>[K]>,\n streamOptions?: StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype AgentMethodCall<AgentT> = OptionalArgsAgentMethodCall<AgentT> &\n RequiredArgsAgentMethodCall<AgentT>;\n\ntype UntypedAgentMethodCall = <T = unknown>(\n method: string,\n args?: unknown[],\n streamOptions?: StreamOptions\n) => Promise<T>;\n\ntype AgentStub<T> = {\n [K in keyof AgentMethods<T>]: (\n ...args: Parameters<AgentMethods<T>[K]>\n ) => AgentPromiseReturnType<AgentMethods<T>, K>;\n};\n\n// we neet to use Method instead of RPCMethod here for retro-compatibility\ntype UntypedAgentStub = Record<string, Method>;\n\n/**\n * React hook for connecting to an Agent\n */\nexport function useAgent<State = unknown>(\n options: UseAgentOptions<State>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n};\nexport function useAgent<\n AgentT extends {\n get state(): State;\n },\n State\n>(\n options: UseAgentOptions<State>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: AgentMethodCall<AgentT>;\n stub: AgentStub<AgentT>;\n};\nexport function useAgent<State>(\n options: UseAgentOptions<unknown>\n): PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall | AgentMethodCall<unknown>;\n stub: UntypedAgentStub;\n} {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n const { query, queryDeps, cacheTtl, ...restOptions } = options;\n\n // Keep track of pending RPC calls\n const pendingCallsRef = useRef(\n new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n }\n >()\n );\n\n // Handle both sync and async query patterns\n const cacheKey = useMemo(() => {\n const deps = queryDeps || [];\n return createCacheKey(agentNamespace, options.name, deps);\n }, [agentNamespace, options.name, queryDeps]);\n\n const queryPromise = useMemo(() => {\n if (!query || typeof query !== \"function\") {\n return null;\n }\n\n const existingPromise = findCacheEntry(cacheKey);\n if (existingPromise) {\n return existingPromise;\n }\n\n const promise = query().catch((error) => {\n console.error(\n `[useAgent] Query failed for agent \"${options.agent}\":`,\n error\n );\n decrementCacheEntry(cacheKey); // Remove failed promise from cache\n throw error; // Re-throw for Suspense error boundary\n });\n\n setCacheEntry(cacheKey, promise, cacheTtl);\n\n return promise;\n }, [cacheKey, query, options.agent, cacheTtl]);\n\n let resolvedQuery: QueryObject | undefined;\n\n if (query) {\n if (typeof query === \"function\") {\n // Use React's use() to resolve the promise\n const queryResult = use(queryPromise!);\n\n // Check for non-primitive values and warn\n if (queryResult) {\n for (const [key, value] of Object.entries(queryResult)) {\n if (\n value !== null &&\n value !== undefined &&\n typeof value !== \"string\" &&\n typeof value !== \"number\" &&\n typeof value !== \"boolean\"\n ) {\n console.warn(\n `[useAgent] Query parameter \"${key}\" is an object and will be converted to \"[object Object]\". ` +\n \"Query parameters should be string, number, boolean, or null.\"\n );\n }\n }\n resolvedQuery = queryResult;\n }\n } else {\n // Sync query - use directly\n resolvedQuery = query;\n }\n }\n\n // Cleanup cache on unmount\n useEffect(() => {\n return () => {\n if (queryPromise) {\n decrementCacheEntry(cacheKey);\n }\n };\n }, [cacheKey, queryPromise]);\n\n const agent = usePartySocket({\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n query: resolvedQuery,\n ...restOptions,\n onMessage: (message) => {\n if (typeof message.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(message.data);\n } catch (_error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return options.onMessage?.(message);\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_MCP_SERVERS) {\n options.onMcpUpdate?.(parsedMessage.mcp as MCPServersState);\n return;\n }\n if (parsedMessage.type === MessageType.RPC) {\n const response = parsedMessage as RPCResponse;\n const pending = pendingCallsRef.current.get(response.id);\n if (!pending) return;\n\n if (!response.success) {\n pending.reject(new Error(response.error));\n pendingCallsRef.current.delete(response.id);\n pending.stream?.onError?.(response.error);\n return;\n }\n\n // Handle streaming responses\n if (\"done\" in response) {\n if (response.done) {\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n pending.stream?.onDone?.(response.result);\n } else {\n pending.stream?.onChunk?.(response.result);\n }\n } else {\n // Non-streaming response\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n }\n return;\n }\n }\n options.onMessage?.(message);\n }\n }) as PartySocket & {\n agent: string;\n name: string;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n };\n // Create the call method\n const call = useCallback(\n <T = unknown,>(\n method: string,\n args: unknown[] = [],\n streamOptions?: StreamOptions\n ): Promise<T> => {\n return new Promise((resolve, reject) => {\n const id = Math.random().toString(36).slice(2);\n pendingCallsRef.current.set(id, {\n reject,\n resolve: resolve as (value: unknown) => void,\n stream: streamOptions\n });\n\n const request: RPCRequest = {\n args,\n id,\n method,\n type: MessageType.RPC\n };\n\n agent.send(JSON.stringify(request));\n });\n },\n [agent]\n );\n\n agent.setState = (state: State) => {\n agent.send(JSON.stringify({ state, type: MessageType.CF_AGENT_STATE }));\n options.onStateUpdate?.(state, \"client\");\n };\n\n agent.call = call;\n agent.agent = agentNamespace;\n agent.name = options.name || \"default\";\n // biome-ignore lint: suppressions/parse\n agent.stub = new Proxy<any>(\n {},\n {\n get: (_target, method) => {\n return (...args: unknown[]) => {\n return call(method as string, args);\n };\n }\n }\n );\n\n // warn if agent isn't in lowercase\n if (agent.agent !== agent.agent.toLowerCase()) {\n console.warn(\n `Agent name: ${agent.agent} should probably be in lowercase. Received: ${agent.agent}`\n );\n }\n\n return agent;\n}\n"],"mappings":";;;;;;;;;;AAaA,SAAS,qBAAqB,KAAqB;AAEjD,KAAI,QAAQ,IAAI,aAAa,IAAI,QAAQ,IAAI,aAAa,CACxD,QAAO,IAAI,aAAa,CAAC,QAAQ,MAAM,IAAI;CAI7C,IAAI,aAAa,IAAI,QACnB,WACC,WAAW,IAAI,OAAO,aAAa,GACrC;AACD,cAAa,WAAW,WAAW,IAAI,GAAG,WAAW,MAAM,EAAE,GAAG;AAEhE,QAAO,WAAW,QAAQ,MAAM,IAAI,CAAC,QAAQ,MAAM,GAAG;;AAKxD,MAAM,6BAAa,IAAI,KAQpB;AAEH,SAAS,YAAY,GAAc,GAAuB;AACxD,KAAI,MAAM,EAAG,QAAO;AACpB,KAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAElC,MAAK,IAAI,IAAI,GAAG,IAAI,EAAE,QAAQ,IAC5B,KAAI,CAAC,OAAO,GAAG,EAAE,IAAI,EAAE,GAAG,CAAE,QAAO;AAErC,QAAO;;AAGT,SAAS,eACP,WACkC;AAClC,MAAK,MAAM,CAAC,aAAa,UAAU,WAAW,SAAS,CACrD,KAAI,YAAY,aAAa,UAAU,EAAE;AAEvC,MAAI,KAAK,KAAK,GAAG,MAAM,WAAW;AAChC,cAAW,OAAO,YAAY;AAC9B;;AAEF,QAAM;AACN,SAAO,MAAM;;;AAMnB,SAAS,cACP,KACA,OACA,UACM;AAEN,MAAK,MAAM,CAAC,gBAAgB,WAAW,SAAS,CAC9C,KAAI,YAAY,aAAa,IAAI,EAAE;AACjC,aAAW,OAAO,YAAY;AAC9B;;CAIJ,MAAM,YAAY,WACd,KAAK,KAAK,GAAG,WACb,KAAK,KAAK,GAAG,MAAS;AAC1B,YAAW,IAAI,KAAK;EAAE,SAAS;EAAO,UAAU;EAAG;EAAW;EAAU,CAAC;;AAG3E,SAAS,oBAAoB,WAA+B;AAC1D,MAAK,MAAM,CAAC,aAAa,UAAU,WAAW,SAAS,CACrD,KAAI,YAAY,aAAa,UAAU,EAAE;AACvC,QAAM;AACN,MAAI,MAAM,YAAY,EACpB,YAAW,OAAO,YAAY;AAEhC,SAAO;;AAGX,QAAO;;AAGT,SAAS,eACP,gBACA,MACA,MACW;AACX,QAAO;EAAC;EAAgB,QAAQ;EAAW,GAAG;EAAK;;AA2HrD,SAAgB,SACd,SAOA;CACA,MAAM,iBAAiB,qBAAqB,QAAQ,MAAM;CAC1D,MAAM,EAAE,OAAO,WAAW,UAAU,GAAG,gBAAgB;CAGvD,MAAM,kBAAkB,uBACtB,IAAI,KAOD,CACJ;CAGD,MAAM,WAAW,cAAc;EAC7B,MAAM,OAAO,aAAa,EAAE;AAC5B,SAAO,eAAe,gBAAgB,QAAQ,MAAM,KAAK;IACxD;EAAC;EAAgB,QAAQ;EAAM;EAAU,CAAC;CAE7C,MAAM,eAAe,cAAc;AACjC,MAAI,CAAC,SAAS,OAAO,UAAU,WAC7B,QAAO;EAGT,MAAM,kBAAkB,eAAe,SAAS;AAChD,MAAI,gBACF,QAAO;EAGT,MAAM,UAAU,OAAO,CAAC,OAAO,UAAU;AACvC,WAAQ,MACN,sCAAsC,QAAQ,MAAM,KACpD,MACD;AACD,uBAAoB,SAAS;AAC7B,SAAM;IACN;AAEF,gBAAc,UAAU,SAAS,SAAS;AAE1C,SAAO;IACN;EAAC;EAAU;EAAO,QAAQ;EAAO;EAAS,CAAC;CAE9C,IAAIA;AAEJ,KAAI,MACF,KAAI,OAAO,UAAU,YAAY;EAE/B,MAAM,cAAc,IAAI,aAAc;AAGtC,MAAI,aAAa;AACf,QAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,YAAY,CACpD,KACE,UAAU,QACV,UAAU,UACV,OAAO,UAAU,YACjB,OAAO,UAAU,YACjB,OAAO,UAAU,UAEjB,SAAQ,KACN,+BAA+B,IAAI,yHAEpC;AAGL,mBAAgB;;OAIlB,iBAAgB;AAKpB,iBAAgB;AACd,eAAa;AACX,OAAI,aACF,qBAAoB,SAAS;;IAGhC,CAAC,UAAU,aAAa,CAAC;CAE5B,MAAM,QAAQ,eAAe;EAC3B,OAAO;EACP,QAAQ;EACR,MAAM,QAAQ,QAAQ;EACtB,OAAO;EACP,GAAG;EACH,YAAY,YAAY;AACtB,OAAI,OAAO,QAAQ,SAAS,UAAU;IACpC,IAAIC;AACJ,QAAI;AACF,qBAAgB,KAAK,MAAM,QAAQ,KAAK;aACjC,QAAQ;AAGf,YAAO,QAAQ,YAAY,QAAQ;;AAErC,QAAI,cAAc,SAAS,YAAY,gBAAgB;AACrD,aAAQ,gBAAgB,cAAc,OAAgB,SAAS;AAC/D;;AAEF,QAAI,cAAc,SAAS,YAAY,sBAAsB;AAC3D,aAAQ,cAAc,cAAc,IAAuB;AAC3D;;AAEF,QAAI,cAAc,SAAS,YAAY,KAAK;KAC1C,MAAM,WAAW;KACjB,MAAM,UAAU,gBAAgB,QAAQ,IAAI,SAAS,GAAG;AACxD,SAAI,CAAC,QAAS;AAEd,SAAI,CAAC,SAAS,SAAS;AACrB,cAAQ,OAAO,IAAI,MAAM,SAAS,MAAM,CAAC;AACzC,sBAAgB,QAAQ,OAAO,SAAS,GAAG;AAC3C,cAAQ,QAAQ,UAAU,SAAS,MAAM;AACzC;;AAIF,SAAI,UAAU,SACZ,KAAI,SAAS,MAAM;AACjB,cAAQ,QAAQ,SAAS,OAAO;AAChC,sBAAgB,QAAQ,OAAO,SAAS,GAAG;AAC3C,cAAQ,QAAQ,SAAS,SAAS,OAAO;WAEzC,SAAQ,QAAQ,UAAU,SAAS,OAAO;UAEvC;AAEL,cAAQ,QAAQ,SAAS,OAAO;AAChC,sBAAgB,QAAQ,OAAO,SAAS,GAAG;;AAE7C;;;AAGJ,WAAQ,YAAY,QAAQ;;EAE/B,CAAC;CAQF,MAAM,OAAO,aAET,QACA,OAAkB,EAAE,EACpB,kBACe;AACf,SAAO,IAAI,SAAS,SAAS,WAAW;GACtC,MAAM,KAAK,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE;AAC9C,mBAAgB,QAAQ,IAAI,IAAI;IAC9B;IACS;IACT,QAAQ;IACT,CAAC;GAEF,MAAMC,UAAsB;IAC1B;IACA;IACA;IACA,MAAM,YAAY;IACnB;AAED,SAAM,KAAK,KAAK,UAAU,QAAQ,CAAC;IACnC;IAEJ,CAAC,MAAM,CACR;AAED,OAAM,YAAY,UAAiB;AACjC,QAAM,KAAK,KAAK,UAAU;GAAE;GAAO,MAAM,YAAY;GAAgB,CAAC,CAAC;AACvE,UAAQ,gBAAgB,OAAO,SAAS;;AAG1C,OAAM,OAAO;AACb,OAAM,QAAQ;AACd,OAAM,OAAO,QAAQ,QAAQ;AAE7B,OAAM,OAAO,IAAI,MACf,EAAE,EACF,EACE,MAAM,SAAS,WAAW;AACxB,UAAQ,GAAG,SAAoB;AAC7B,UAAO,KAAK,QAAkB,KAAK;;IAGxC,CACF;AAGD,KAAI,MAAM,UAAU,MAAM,MAAM,aAAa,CAC3C,SAAQ,KACN,eAAe,MAAM,MAAM,8CAA8C,MAAM,QAChF;AAGH,QAAO"}
@@ -36,4 +36,4 @@ export {
36
36
  SerializableReturnValue as r,
37
37
  Method as t
38
38
  };
39
- //# sourceMappingURL=serializable-CymX8ovI.d.ts.map
39
+ //# sourceMappingURL=serializable-faDkMCai.d.ts.map
@@ -3,5 +3,5 @@ import {
3
3
  n as RPCMethod,
4
4
  r as SerializableReturnValue,
5
5
  t as Method
6
- } from "./serializable-CymX8ovI.js";
6
+ } from "./serializable-faDkMCai.js";
7
7
  export { Method, RPCMethod, SerializableReturnValue, SerializableValue };
@@ -1,7 +1,7 @@
1
- import { t as MessageType } from "./ai-types-B3aQaFv3.js";
2
- import { r as camelCaseToKebabCase } from "./client-BfiZ3HQd.js";
3
- import { i as DisposableStore, r as MCPClientConnection, t as MCPClientManager } from "./client-DZhjV_XA.js";
4
- import { t as DurableObjectOAuthClientProvider } from "./do-oauth-client-provider-CswoD5Lu.js";
1
+ import { t as MessageType } from "./ai-types-CrMqkwc_.js";
2
+ import { r as camelCaseToKebabCase } from "./client-B3SR12TQ.js";
3
+ import { i as DisposableStore, r as MCPConnectionState, t as MCPClientManager } from "./client-BZq9qau2.js";
4
+ import { t as DurableObjectOAuthClientProvider } from "./do-oauth-client-provider-CwqK5SXm.js";
5
5
  import { AsyncLocalStorage } from "node:async_hooks";
6
6
  import { parseCronExpression } from "cron-schedule";
7
7
  import { nanoid } from "nanoid";
@@ -153,9 +153,8 @@ var Agent = class Agent extends Server {
153
153
  super(ctx, env);
154
154
  this._state = DEFAULT_STATE;
155
155
  this._disposables = new DisposableStore();
156
- this._mcpStateRestored = false;
156
+ this._destroyed = false;
157
157
  this._ParentClass = Object.getPrototypeOf(this).constructor;
158
- this.mcp = new MCPClientManager(this._ParentClass.name, "0.0.1");
159
158
  this.initialState = DEFAULT_STATE;
160
159
  this.observability = genericObservability;
161
160
  this._flushingQueue = false;
@@ -193,27 +192,37 @@ var Agent = class Agent extends Server {
193
192
  }
194
193
  });
195
194
  if (row.type === "cron") {
195
+ if (this._destroyed) return;
196
196
  const nextExecutionTime = getNextCronTime(row.cron);
197
197
  const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1e3);
198
198
  this.sql`
199
199
  UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}
200
200
  `;
201
- } else this.sql`
201
+ } else {
202
+ if (this._destroyed) return;
203
+ this.sql`
202
204
  DELETE FROM cf_agents_schedules WHERE id = ${row.id}
203
205
  `;
206
+ }
204
207
  }
208
+ if (this._destroyed) return;
205
209
  await this._scheduleNextAlarm();
206
210
  };
207
211
  if (!wrappedClasses.has(this.constructor)) {
208
212
  this._autoWrapCustomMethods();
209
213
  wrappedClasses.add(this.constructor);
210
214
  }
211
- this._disposables.add(this.mcp.onConnected(async () => {
212
- this.broadcastMcpServers();
213
- }));
214
- this._disposables.add(this.mcp.onObservabilityEvent((event) => {
215
- this.observability?.emit(event);
216
- }));
215
+ this.sql`
216
+ CREATE TABLE IF NOT EXISTS cf_agents_mcp_servers (
217
+ id TEXT PRIMARY KEY NOT NULL,
218
+ name TEXT NOT NULL,
219
+ server_url TEXT NOT NULL,
220
+ callback_url TEXT NOT NULL,
221
+ client_id TEXT,
222
+ auth_url TEXT,
223
+ server_options TEXT
224
+ )
225
+ `;
217
226
  this.sql`
218
227
  CREATE TABLE IF NOT EXISTS cf_agents_state (
219
228
  id TEXT PRIMARY KEY NOT NULL,
@@ -228,34 +237,25 @@ var Agent = class Agent extends Server {
228
237
  created_at INTEGER DEFAULT (unixepoch())
229
238
  )
230
239
  `;
231
- this.ctx.blockConcurrencyWhile(async () => {
232
- return this._tryCatch(async () => {
233
- this.sql`
234
- CREATE TABLE IF NOT EXISTS cf_agents_schedules (
235
- id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),
236
- callback TEXT,
237
- payload TEXT,
238
- type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron')),
239
- time INTEGER,
240
- delayInSeconds INTEGER,
241
- cron TEXT,
242
- created_at INTEGER DEFAULT (unixepoch())
243
- )
244
- `;
245
- await this.alarm();
246
- });
247
- });
248
240
  this.sql`
249
- CREATE TABLE IF NOT EXISTS cf_agents_mcp_servers (
250
- id TEXT PRIMARY KEY NOT NULL,
251
- name TEXT NOT NULL,
252
- server_url TEXT NOT NULL,
253
- callback_url TEXT NOT NULL,
254
- client_id TEXT,
255
- auth_url TEXT,
256
- server_options TEXT
241
+ CREATE TABLE IF NOT EXISTS cf_agents_schedules (
242
+ id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),
243
+ callback TEXT,
244
+ payload TEXT,
245
+ type TEXT NOT NULL CHECK(type IN ('scheduled', 'delayed', 'cron')),
246
+ time INTEGER,
247
+ delayInSeconds INTEGER,
248
+ cron TEXT,
249
+ created_at INTEGER DEFAULT (unixepoch())
257
250
  )
258
251
  `;
252
+ this.mcp = new MCPClientManager(this._ParentClass.name, "0.0.1", { storage: this.ctx.storage });
253
+ this._disposables.add(this.mcp.onServerStateChanged(async () => {
254
+ this.broadcastMcpServers();
255
+ }));
256
+ this._disposables.add(this.mcp.onObservabilityEvent((event) => {
257
+ this.observability?.emit(event);
258
+ }));
259
259
  const _onRequest = this.onRequest.bind(this);
260
260
  this.onRequest = (request) => {
261
261
  return agentContext.run({
@@ -264,17 +264,9 @@ var Agent = class Agent extends Server {
264
264
  request,
265
265
  email: void 0
266
266
  }, async () => {
267
- await this._ensureMcpStateRestored();
268
- if (this.mcp.isCallbackRequest(request)) {
269
- const result = await this.mcp.handleCallbackRequest(request);
270
- this.broadcastMcpServers();
271
- if (result.authSuccess) this.mcp.establishConnection(result.serverId).catch((error) => {
272
- console.error("Background connection failed:", error);
273
- }).finally(() => {
274
- this.broadcastMcpServers();
275
- });
276
- return this.handleOAuthCallbackResponse(result, request);
277
- }
267
+ await this.mcp.ensureJsonSchema();
268
+ const oauthResponse = await this.handleMcpOAuthCallback(request);
269
+ if (oauthResponse) return oauthResponse;
278
270
  return this._tryCatch(() => _onRequest(request));
279
271
  });
280
272
  };
@@ -286,6 +278,7 @@ var Agent = class Agent extends Server {
286
278
  request: void 0,
287
279
  email: void 0
288
280
  }, async () => {
281
+ await this.mcp.ensureJsonSchema();
289
282
  if (typeof message !== "string") return this._tryCatch(() => _onMessage(connection, message));
290
283
  let parsed;
291
284
  try {
@@ -350,7 +343,7 @@ var Agent = class Agent extends Server {
350
343
  connection,
351
344
  request: ctx$1.request,
352
345
  email: void 0
353
- }, () => {
346
+ }, async () => {
354
347
  if (this.state) connection.send(JSON.stringify({
355
348
  state: this.state,
356
349
  type: MessageType.CF_AGENT_STATE
@@ -378,7 +371,7 @@ var Agent = class Agent extends Server {
378
371
  email: void 0
379
372
  }, async () => {
380
373
  await this._tryCatch(async () => {
381
- await this._ensureMcpStateRestored();
374
+ await this.mcp.restoreConnectionsFromStorage(this.name);
382
375
  this.broadcastMcpServers();
383
376
  return _onStart(props);
384
377
  });
@@ -785,7 +778,7 @@ var Agent = class Agent extends Server {
785
778
  async _scheduleNextAlarm() {
786
779
  const result = this.sql`
787
780
  SELECT time FROM cf_agents_schedules
788
- WHERE time > ${Math.floor(Date.now() / 1e3)}
781
+ WHERE time >= ${Math.floor(Date.now() / 1e3)}
789
782
  ORDER BY time ASC
790
783
  LIMIT 1
791
784
  `;
@@ -799,15 +792,18 @@ var Agent = class Agent extends Server {
799
792
  * Destroy the Agent, removing all state and scheduled tasks
800
793
  */
801
794
  async destroy() {
795
+ this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
802
796
  this.sql`DROP TABLE IF EXISTS cf_agents_state`;
803
797
  this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;
804
- this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
805
798
  this.sql`DROP TABLE IF EXISTS cf_agents_queues`;
806
799
  await this.ctx.storage.deleteAlarm();
807
800
  await this.ctx.storage.deleteAll();
808
801
  this._disposables.dispose();
809
- await this.mcp.dispose?.();
810
- this.ctx.abort("destroyed");
802
+ await this.mcp.dispose();
803
+ this._destroyed = true;
804
+ setTimeout(() => {
805
+ this.ctx.abort("destroyed");
806
+ }, 0);
811
807
  this.observability?.emit({
812
808
  displayMessage: "Agent destroyed",
813
809
  id: nanoid(),
@@ -823,43 +819,6 @@ var Agent = class Agent extends Server {
823
819
  _isCallable(method) {
824
820
  return callableMetadata.has(this[method]);
825
821
  }
826
- async _ensureMcpStateRestored() {
827
- if (this._mcpStateRestored) return;
828
- this._mcpStateRestored = true;
829
- const servers = this.sql`
830
- SELECT id, name, server_url, client_id, auth_url, callback_url, server_options
831
- FROM cf_agents_mcp_servers
832
- `;
833
- if (!servers || !Array.isArray(servers) || servers.length === 0) return;
834
- for (const server of servers) if (server.callback_url) this.mcp.registerCallbackUrl(`${server.callback_url}/${server.id}`);
835
- for (const server of servers) if (!!server.auth_url) {
836
- const authProvider = new DurableObjectOAuthClientProvider(this.ctx.storage, this.name, server.callback_url);
837
- authProvider.serverId = server.id;
838
- if (server.client_id) authProvider.clientId = server.client_id;
839
- const parsedOptions = server.server_options ? JSON.parse(server.server_options) : void 0;
840
- const conn = new MCPClientConnection(new URL(server.server_url), {
841
- name: this.name,
842
- version: "1.0.0"
843
- }, {
844
- client: parsedOptions?.client ?? {},
845
- transport: {
846
- ...parsedOptions?.transport ?? {},
847
- type: parsedOptions?.transport?.type ?? "auto",
848
- authProvider
849
- }
850
- });
851
- conn.connectionState = "authenticating";
852
- this.mcp.mcpConnections[server.id] = conn;
853
- } else {
854
- const parsedOptions = server.server_options ? JSON.parse(server.server_options) : void 0;
855
- this._connectToMcpServerInternal(server.name, server.server_url, server.callback_url, parsedOptions, {
856
- id: server.id,
857
- oauthClientId: server.client_id ?? void 0
858
- }).catch((error) => {
859
- console.error(`Error restoring ${server.id}:`, error);
860
- });
861
- }
862
- }
863
822
  /**
864
823
  * Connect to a new MCP Server
865
824
  *
@@ -868,7 +827,8 @@ var Agent = class Agent extends Server {
868
827
  * @param callbackHost Base host for the agent, used for the redirect URI. If not provided, will be derived from the current request.
869
828
  * @param agentsPrefix agents routing prefix if not using `agents`
870
829
  * @param options MCP client and transport options
871
- * @returns authUrl
830
+ * @returns Server id and state - either "authenticating" with authUrl, or "ready"
831
+ * @throws If connection or discovery fails
872
832
  */
873
833
  async addMcpServer(serverName, url, callbackHost, agentsPrefix = "agents", options) {
874
834
  let resolvedCallbackHost = callbackHost;
@@ -879,29 +839,10 @@ var Agent = class Agent extends Server {
879
839
  resolvedCallbackHost = `${requestUrl.protocol}//${requestUrl.host}`;
880
840
  }
881
841
  const callbackUrl = `${resolvedCallbackHost}/${agentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;
882
- const result = await this._connectToMcpServerInternal(serverName, url, callbackUrl, options);
883
- this.sql`
884
- INSERT
885
- OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)
886
- VALUES (
887
- ${result.id},
888
- ${serverName},
889
- ${url},
890
- ${result.clientId ?? null},
891
- ${result.authUrl ?? null},
892
- ${callbackUrl},
893
- ${options ? JSON.stringify(options) : null}
894
- );
895
- `;
896
- this.broadcastMcpServers();
897
- return result;
898
- }
899
- async _connectToMcpServerInternal(_serverName, url, callbackUrl, options, reconnect) {
842
+ await this.mcp.ensureJsonSchema();
843
+ const id = nanoid(8);
900
844
  const authProvider = new DurableObjectOAuthClientProvider(this.ctx.storage, this.name, callbackUrl);
901
- if (reconnect) {
902
- authProvider.serverId = reconnect.id;
903
- if (reconnect.oauthClientId) authProvider.clientId = reconnect.oauthClientId;
904
- }
845
+ authProvider.serverId = id;
905
846
  const transportType = options?.transport?.type ?? "auto";
906
847
  let headerTransportOpts = {};
907
848
  if (options?.transport?.headers) headerTransportOpts = {
@@ -911,28 +852,33 @@ var Agent = class Agent extends Server {
911
852
  }) },
912
853
  requestInit: { headers: options?.transport?.headers }
913
854
  };
914
- const { id, authUrl, clientId } = await this.mcp.connect(url, {
855
+ await this.mcp.registerServer(id, {
856
+ url,
857
+ name: serverName,
858
+ callbackUrl,
915
859
  client: options?.client,
916
- reconnect,
917
860
  transport: {
918
861
  ...headerTransportOpts,
919
862
  authProvider,
920
863
  type: transportType
921
864
  }
922
865
  });
866
+ const result = await this.mcp.connectToServer(id);
867
+ if (result.state === MCPConnectionState.FAILED) throw new Error(`Failed to connect to MCP server at ${url}: ${result.error}`);
868
+ if (result.state === MCPConnectionState.AUTHENTICATING) return {
869
+ id,
870
+ state: result.state,
871
+ authUrl: result.authUrl
872
+ };
873
+ const discoverResult = await this.mcp.discoverIfConnected(id);
874
+ if (discoverResult && !discoverResult.success) throw new Error(`Failed to discover MCP server capabilities: ${discoverResult.error}`);
923
875
  return {
924
- authUrl,
925
- clientId,
926
- id
876
+ id,
877
+ state: MCPConnectionState.READY
927
878
  };
928
879
  }
929
880
  async removeMcpServer(id) {
930
- this.mcp.closeConnection(id);
931
- this.mcp.unregisterCallbackUrl(id);
932
- this.sql`
933
- DELETE FROM cf_agents_mcp_servers WHERE id = ${id};
934
- `;
935
- this.broadcastMcpServers();
881
+ await this.mcp.removeServer(id);
936
882
  }
937
883
  getMcpServers() {
938
884
  const mcpState = {
@@ -941,18 +887,18 @@ var Agent = class Agent extends Server {
941
887
  servers: {},
942
888
  tools: this.mcp.listTools()
943
889
  };
944
- const servers = this.sql`
945
- SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
946
- `;
890
+ const servers = this.mcp.listServers();
947
891
  if (servers && Array.isArray(servers) && servers.length > 0) for (const server of servers) {
948
892
  const serverConn = this.mcp.mcpConnections[server.id];
893
+ let defaultState = "not-connected";
894
+ if (!serverConn && server.auth_url) defaultState = "authenticating";
949
895
  mcpState.servers[server.id] = {
950
896
  auth_url: server.auth_url,
951
897
  capabilities: serverConn?.serverCapabilities ?? null,
952
898
  instructions: serverConn?.instructions ?? null,
953
899
  name: server.name,
954
900
  server_url: server.server_url,
955
- state: serverConn?.connectionState ?? "authenticating"
901
+ state: serverConn?.connectionState ?? defaultState
956
902
  };
957
903
  }
958
904
  return mcpState;
@@ -964,6 +910,28 @@ var Agent = class Agent extends Server {
964
910
  }));
965
911
  }
966
912
  /**
913
+ * Handle MCP OAuth callback request if it's an OAuth callback.
914
+ *
915
+ * This method encapsulates the entire OAuth callback flow:
916
+ * 1. Checks if the request is an MCP OAuth callback
917
+ * 2. Processes the OAuth code exchange
918
+ * 3. Establishes the connection if successful
919
+ * 4. Broadcasts MCP server state updates
920
+ * 5. Returns the appropriate HTTP response
921
+ *
922
+ * @param request The incoming HTTP request
923
+ * @returns Response if this was an OAuth callback, null otherwise
924
+ */
925
+ async handleMcpOAuthCallback(request) {
926
+ if (!this.mcp.isCallbackRequest(request)) return null;
927
+ const result = await this.mcp.handleCallbackRequest(request);
928
+ if (result.authSuccess) this.mcp.establishConnection(result.serverId).catch((error) => {
929
+ console.error("[Agent handleMcpOAuthCallback] Connection establishment failed:", error);
930
+ });
931
+ this.broadcastMcpServers();
932
+ return this.handleOAuthCallbackResponse(result, request);
933
+ }
934
+ /**
967
935
  * Handle OAuth callback response using MCPClientManager configuration
968
936
  * @param result OAuth callback result
969
937
  * @param request The original request (needed for base URL)
@@ -1213,4 +1181,4 @@ var StreamingResponse = class {
1213
1181
 
1214
1182
  //#endregion
1215
1183
  export { createCatchAllEmailResolver as a, getCurrentAgent as c, unstable_callable as d, genericObservability as f, createAddressBasedEmailResolver as i, routeAgentEmail as l, StreamingResponse as n, createHeaderBasedEmailResolver as o, callable as r, getAgentByName as s, Agent as t, routeAgentRequest as u };
1216
- //# sourceMappingURL=src-CwIW7tU2.js.map
1184
+ //# sourceMappingURL=src-D_KKH_4c.js.map