agents 0.12.3 → 0.12.4

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 (81) hide show
  1. package/dist/{agent-tool-types-DSteYkkS.d.ts → agent-tool-types-CM_50fcV.d.ts} +104 -87
  2. package/dist/agent-tool-types.d.ts +1 -1
  3. package/dist/agent-tools-BAdX1vdI.js.map +1 -1
  4. package/dist/{agent-tools-eGTCdVZX.d.ts → agent-tools-BylX6WXG.d.ts} +2 -2
  5. package/dist/agent-tools.d.ts +1 -1
  6. package/dist/agent-tools.js.map +1 -1
  7. package/dist/browser/ai.d.ts +2 -2
  8. package/dist/browser/ai.js +1 -1
  9. package/dist/browser/ai.js.map +1 -1
  10. package/dist/browser/index.d.ts +41 -10
  11. package/dist/browser/index.js +1 -1
  12. package/dist/browser/tanstack-ai.d.ts +2 -2
  13. package/dist/browser/tanstack-ai.js +1 -1
  14. package/dist/browser/tanstack-ai.js.map +1 -1
  15. package/dist/chat/index.d.ts +297 -148
  16. package/dist/chat/index.js +43 -14
  17. package/dist/chat/index.js.map +1 -1
  18. package/dist/{classPrivateFieldGet2-Bqby-AHD.js → classPrivateFieldGet2-CS51BNGR.js} +5 -5
  19. package/dist/cli/index.d.ts +1 -1
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/client-D1kFXo80.js.map +1 -1
  22. package/dist/client.d.ts +1 -1
  23. package/dist/client.js.map +1 -1
  24. package/dist/codemode/ai.d.ts +1 -1
  25. package/dist/{compaction-helpers-CSaqCmdE.js → compaction-helpers-DvcZnvQ1.js} +1 -1
  26. package/dist/{compaction-helpers-CSaqCmdE.js.map → compaction-helpers-DvcZnvQ1.js.map} +1 -1
  27. package/dist/{compaction-helpers-CzCq1-fF.d.ts → compaction-helpers-bYvP1o2S.d.ts} +10 -3
  28. package/dist/{do-oauth-client-provider-C38aWbFV.d.ts → do-oauth-client-provider-4OKQU9rT.d.ts} +1 -1
  29. package/dist/{email-X72-zjuq.d.ts → email-J0GGS3sa.d.ts} +1 -1
  30. package/dist/email.d.ts +2 -2
  31. package/dist/email.js.map +1 -1
  32. package/dist/experimental/memory/session/index.d.ts +126 -26
  33. package/dist/experimental/memory/session/index.js +13 -3
  34. package/dist/experimental/memory/session/index.js.map +1 -1
  35. package/dist/experimental/memory/utils/index.d.ts +41 -5
  36. package/dist/experimental/memory/utils/index.js +15 -5
  37. package/dist/experimental/memory/utils/index.js.map +1 -1
  38. package/dist/experimental/webmcp.d.ts +9 -3
  39. package/dist/experimental/webmcp.js.map +1 -1
  40. package/dist/{index-Biv6K70p.d.ts → index-DKey3P4s.d.ts} +26 -2
  41. package/dist/index.d.ts +48 -44
  42. package/dist/index.js +122 -85
  43. package/dist/index.js.map +1 -1
  44. package/dist/{internal_context-BvuGZieY.d.ts → internal_context-BZrMS0B5.d.ts} +1 -1
  45. package/dist/internal_context.d.ts +1 -1
  46. package/dist/mcp/client.d.ts +26 -2
  47. package/dist/mcp/do-oauth-client-provider.d.ts +10 -2
  48. package/dist/mcp/do-oauth-client-provider.js.map +1 -1
  49. package/dist/mcp/index.d.ts +54 -2
  50. package/dist/mcp/index.js +43 -19
  51. package/dist/mcp/index.js.map +1 -1
  52. package/dist/mcp/x402.d.ts +74 -17
  53. package/dist/mcp/x402.js.map +1 -1
  54. package/dist/observability/index.d.ts +16 -2
  55. package/dist/observability/index.js +1 -1
  56. package/dist/observability/index.js.map +1 -1
  57. package/dist/react.d.ts +2 -2
  58. package/dist/react.js.map +1 -1
  59. package/dist/{retries-fLD8cGNf.d.ts → retries-BVdRl5ZE.d.ts} +1 -1
  60. package/dist/retries.d.ts +1 -1
  61. package/dist/retries.js.map +1 -1
  62. package/dist/schedule.js.map +1 -1
  63. package/dist/serializable.d.ts +1 -1
  64. package/dist/{shared-Ch9slKdI.d.ts → shared-Cvj92byG.d.ts} +1 -1
  65. package/dist/{shared-C6l4ZKRN.js → shared-DzJYHisH.js} +3 -3
  66. package/dist/{shared-C6l4ZKRN.js.map → shared-DzJYHisH.js.map} +1 -1
  67. package/dist/sub-routing.d.ts +6 -6
  68. package/dist/sub-routing.js.map +1 -1
  69. package/dist/tool-output-truncation-CH-khbZ3.js +98 -0
  70. package/dist/tool-output-truncation-CH-khbZ3.js.map +1 -0
  71. package/dist/{types-DAHCZC_W.d.ts → types-_JjKmv-l.d.ts} +1 -1
  72. package/dist/types.d.ts +1 -1
  73. package/dist/types.js.map +1 -1
  74. package/dist/utils.js.map +1 -1
  75. package/dist/vite.js.map +1 -1
  76. package/dist/{workflow-types-DHs0L0KP.d.ts → workflow-types-Dkzg4hAx.d.ts} +1 -1
  77. package/dist/workflow-types.d.ts +1 -1
  78. package/dist/workflow-types.js.map +1 -1
  79. package/dist/workflows.d.ts +2 -2
  80. package/dist/workflows.js.map +1 -1
  81. package/package.json +9 -9
@@ -1,11 +1,33 @@
1
1
  import { ZodRawShape } from "zod";
2
2
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
- import { CallToolRequest, CallToolResult, CallToolResultSchema, CompatibilityCallToolResultSchema, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
4
- import { McpServer, RegisteredTool, ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
5
- import { FacilitatorConfig, FacilitatorConfig as FacilitatorConfig$1 } from "@x402/core/server";
3
+ import {
4
+ CallToolRequest,
5
+ CallToolResult,
6
+ CallToolResultSchema,
7
+ CompatibilityCallToolResultSchema,
8
+ ToolAnnotations
9
+ } from "@modelcontextprotocol/sdk/types.js";
10
+ import {
11
+ McpServer,
12
+ RegisteredTool,
13
+ ToolCallback
14
+ } from "@modelcontextprotocol/sdk/server/mcp.js";
15
+ import {
16
+ FacilitatorConfig,
17
+ FacilitatorConfig as FacilitatorConfig$1
18
+ } from "@x402/core/server";
6
19
  import { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
7
- import { Network, Network as Network$1, PaymentRequired, PaymentRequirements, PaymentRequirements as PaymentRequirements$1 } from "@x402/core/types";
8
- import { ClientEvmSigner, ClientEvmSigner as ClientEvmSigner$1 } from "@x402/evm";
20
+ import {
21
+ Network,
22
+ Network as Network$1,
23
+ PaymentRequired,
24
+ PaymentRequirements,
25
+ PaymentRequirements as PaymentRequirements$1
26
+ } from "@x402/core/types";
27
+ import {
28
+ ClientEvmSigner,
29
+ ClientEvmSigner as ClientEvmSigner$1
30
+ } from "@x402/evm";
9
31
 
10
32
  //#region src/mcp/x402.d.ts
11
33
  /**
@@ -18,17 +40,36 @@ type X402Config = {
18
40
  * Network identifier.
19
41
  * Accepts both legacy names ("base-sepolia") and CAIP-2 format ("eip155:84532").
20
42
  */
21
- network: string; /** Payment recipient address */
22
- recipient: `0x${string}`; /** Facilitator configuration. Defaults to https://x402.org/facilitator */
23
- facilitator?: FacilitatorConfig$1; /** @deprecated No longer used in v2. The protocol version is determined automatically. */
43
+ network: string /** Payment recipient address */;
44
+ recipient: `0x${string}` /** Facilitator configuration. Defaults to https://x402.org/facilitator */;
45
+ facilitator?: FacilitatorConfig$1 /** @deprecated No longer used in v2. The protocol version is determined automatically. */;
24
46
  version?: number;
25
47
  };
26
48
  interface X402AugmentedServer {
27
- paidTool<Args extends ZodRawShape>(name: string, description: string, priceUSD: number, paramsSchema: Args, annotations: ToolAnnotations, cb: ToolCallback<Args>): RegisteredTool;
49
+ paidTool<Args extends ZodRawShape>(
50
+ name: string,
51
+ description: string,
52
+ priceUSD: number,
53
+ paramsSchema: Args,
54
+ annotations: ToolAnnotations,
55
+ cb: ToolCallback<Args>
56
+ ): RegisteredTool;
28
57
  }
29
- declare function withX402<T extends McpServer>(server: T, cfg: X402Config): T & X402AugmentedServer;
58
+ declare function withX402<T extends McpServer>(
59
+ server: T,
60
+ cfg: X402Config
61
+ ): T & X402AugmentedServer;
30
62
  interface X402AugmentedClient {
31
- callTool(x402ConfirmationCallback: ((payment: PaymentRequirements$1[]) => Promise<boolean>) | null, params: CallToolRequest["params"], resultSchema?: typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema, options?: RequestOptions): Promise<CallToolResult>;
63
+ callTool(
64
+ x402ConfirmationCallback:
65
+ | ((payment: PaymentRequirements$1[]) => Promise<boolean>)
66
+ | null,
67
+ params: CallToolRequest["params"],
68
+ resultSchema?:
69
+ | typeof CallToolResultSchema
70
+ | typeof CompatibilityCallToolResultSchema,
71
+ options?: RequestOptions
72
+ ): Promise<CallToolResult>;
32
73
  }
33
74
  type X402ClientConfig = {
34
75
  /**
@@ -42,12 +83,28 @@ type X402ClientConfig = {
42
83
  * When set, the client prefers payment requirements matching this network.
43
84
  * If omitted, the client automatically selects from available requirements.
44
85
  */
45
- network?: string; /** Maximum payment value in atomic units (default: 0.10 USDC = 100000) */
46
- maxPaymentValue?: bigint; /** @deprecated No longer used in v2. The protocol version is determined automatically. */
47
- version?: number; /** Confirmation callback for payment approval */
86
+ network?: string /** Maximum payment value in atomic units (default: 0.10 USDC = 100000) */;
87
+ maxPaymentValue?: bigint /** @deprecated No longer used in v2. The protocol version is determined automatically. */;
88
+ version?: number /** Confirmation callback for payment approval */;
48
89
  confirmationCallback?: (payment: PaymentRequirements$1[]) => Promise<boolean>;
49
90
  };
50
- declare function withX402Client<T extends Client>(client: T, x402Config: X402ClientConfig): X402AugmentedClient & T;
91
+ declare function withX402Client<T extends Client>(
92
+ client: T,
93
+ x402Config: X402ClientConfig
94
+ ): X402AugmentedClient & T;
51
95
  //#endregion
52
- export { type ClientEvmSigner, type FacilitatorConfig, type Network, type PaymentRequired, type PaymentRequirements, X402AugmentedClient, X402AugmentedServer, X402ClientConfig, X402Config, normalizeNetwork, withX402, withX402Client };
53
- //# sourceMappingURL=x402.d.ts.map
96
+ export {
97
+ type ClientEvmSigner,
98
+ type FacilitatorConfig,
99
+ type Network,
100
+ type PaymentRequired,
101
+ type PaymentRequirements,
102
+ X402AugmentedClient,
103
+ X402AugmentedServer,
104
+ X402ClientConfig,
105
+ X402Config,
106
+ normalizeNetwork,
107
+ withX402,
108
+ withX402Client
109
+ };
110
+ //# sourceMappingURL=x402.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"x402.js","names":[],"sources":["../../src/mcp/x402.ts"],"sourcesContent":["/**\n * X402 MCP Integration (v2)\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 type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\n\n// v2 imports from @x402/core\nimport { x402ResourceServer, HTTPFacilitatorClient } from \"@x402/core/server\";\nimport type { FacilitatorConfig, ResourceConfig } from \"@x402/core/server\";\nimport { x402Client } from \"@x402/core/client\";\nimport type {\n PaymentPayload,\n PaymentRequirements,\n PaymentRequired,\n Network\n} from \"@x402/core/types\";\n\n// v2 imports from @x402/evm\nimport { registerExactEvmScheme as registerServerEvmScheme } from \"@x402/evm/exact/server\";\nimport { registerExactEvmScheme as registerClientEvmScheme } from \"@x402/evm/exact/client\";\nimport type { ClientEvmSigner } from \"@x402/evm\";\n\n// Re-export commonly used types for consumer convenience\nexport type {\n PaymentRequirements,\n PaymentRequired,\n Network\n} from \"@x402/core/types\";\nexport type { FacilitatorConfig } from \"@x402/core/server\";\nexport type { ClientEvmSigner } from \"@x402/evm\";\n\n/**\n * Map of legacy v1 network names to CAIP-2 identifiers.\n * Allows backward compatibility with v1 config.\n */\nconst LEGACY_NETWORK_MAP: Record<string, string> = {\n \"base-sepolia\": \"eip155:84532\",\n base: \"eip155:8453\",\n ethereum: \"eip155:1\",\n sepolia: \"eip155:11155111\"\n};\n\n/**\n * Normalize a network identifier to CAIP-2 format.\n * Accepts both legacy v1 names (\"base-sepolia\") and CAIP-2 (\"eip155:84532\").\n */\nexport function normalizeNetwork(network: string): Network {\n return (LEGACY_NETWORK_MAP[network] ?? network) as Network;\n}\n\n/*\n ======= SERVER SIDE =======\n*/\n\nexport type X402Config = {\n /**\n * Network identifier.\n * Accepts both legacy names (\"base-sepolia\") and CAIP-2 format (\"eip155:84532\").\n */\n network: string;\n /** Payment recipient address */\n recipient: `0x${string}`;\n /** Facilitator configuration. Defaults to https://x402.org/facilitator */\n facilitator?: FacilitatorConfig;\n /** @deprecated No longer used in v2. The protocol version is determined automatically. */\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: T,\n cfg: X402Config\n): T & X402AugmentedServer {\n const network = normalizeNetwork(cfg.network);\n const facilitatorConfig: FacilitatorConfig = cfg.facilitator ?? {\n url: \"https://x402.org/facilitator\"\n };\n\n // Create v2 resource server with facilitator client\n const facilitatorClient = new HTTPFacilitatorClient(facilitatorConfig);\n const resourceServer = new x402ResourceServer(facilitatorClient);\n registerServerEvmScheme(resourceServer);\n\n // Lazy initialization: fetch supported kinds from facilitator on first use\n let initPromise: Promise<void> | null = null;\n function ensureInitialized(): Promise<void> {\n if (!initPromise) {\n initPromise = resourceServer.initialize().catch((err) => {\n initPromise = null; // allow retry on failure\n throw err;\n });\n }\n return initPromise;\n }\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 await ensureInitialized();\n\n // Build v2 payment requirements for this tool call\n const resourceConfig: ResourceConfig = {\n scheme: \"exact\",\n payTo: cfg.recipient,\n price: priceUSD,\n network,\n maxTimeoutSeconds: 300\n };\n\n let requirements: PaymentRequirements[];\n try {\n requirements =\n await resourceServer.buildPaymentRequirements(resourceConfig);\n } catch {\n const payload = { x402Version: 2, 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\n const resourceInfo = {\n url: `x402://${name}`,\n description,\n mimeType: \"application/json\"\n };\n\n // Get payment token from MCP _meta or HTTP headers\n // Support both v2 (PAYMENT-SIGNATURE) and v1 (X-PAYMENT) header names\n const headers = extra?.requestInfo?.headers ?? {};\n const token =\n (extra?._meta?.[\"x402/payment\"] as string | undefined) ??\n headers[\"PAYMENT-SIGNATURE\"] ??\n headers[\"X-PAYMENT\"];\n\n const paymentRequired = (\n reason = \"PAYMENT_REQUIRED\",\n extraFields: Record<string, unknown> = {}\n ) => {\n const payload = {\n x402Version: 2,\n error: reason,\n resource: resourceInfo,\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 the payment payload (base64-encoded JSON)\n let paymentPayload: PaymentPayload;\n try {\n paymentPayload = JSON.parse(atob(token));\n } catch {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n // Find matching requirements for this payment\n const matchingReq = resourceServer.findMatchingRequirements(\n requirements,\n paymentPayload\n );\n if (!matchingReq) {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n // Verify payment with facilitator\n try {\n const vr = await resourceServer.verifyPayment(\n paymentPayload,\n matchingReq\n );\n if (!vr.isValid) {\n return paymentRequired(vr.invalidReason ?? \"INVALID_PAYMENT\", {\n payer: vr.payer\n });\n }\n } catch {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n // Execute the tool callback\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 payment only on success\n if (!failed) {\n try {\n const s = await resourceServer.settlePayment(\n paymentPayload,\n matchingReq\n );\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\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 /**\n * EVM account/signer for signing payment authorizations.\n * Use `privateKeyToAccount()` from viem/accounts to create one.\n */\n account: ClientEvmSigner;\n /**\n * Preferred network identifier (optional).\n * Accepts both legacy names (\"base-sepolia\") and CAIP-2 format (\"eip155:84532\").\n * When set, the client prefers payment requirements matching this network.\n * If omitted, the client automatically selects from available requirements.\n */\n network?: string;\n /** Maximum payment value in atomic units (default: 0.10 USDC = 100000) */\n maxPaymentValue?: bigint;\n /** @deprecated No longer used in v2. The protocol version is determined automatically. */\n version?: number;\n /** Confirmation callback for payment approval */\n confirmationCallback?: (payment: PaymentRequirements[]) => Promise<boolean>;\n};\n\nexport function withX402Client<T extends MCPClient>(\n client: T,\n x402Config: X402ClientConfig\n): X402AugmentedClient & T {\n const { account } = x402Config;\n\n const maxPaymentValue = x402Config.maxPaymentValue ?? BigInt(100_000); // 0.10 USDC\n\n // Create v2 x402 payment client with EVM scheme support\n const paymentClient = new x402Client();\n registerClientEvmScheme(paymentClient, { signer: account });\n\n // If a preferred network is specified, register a policy to prefer it\n if (x402Config.network) {\n const preferredNetwork = normalizeNetwork(x402Config.network);\n paymentClient.registerPolicy((_version, reqs) => {\n const matching = reqs.filter((r) => r.network === preferredNetwork);\n return matching.length > 0 ? matching : reqs;\n });\n }\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 return {\n ...toolsRes,\n 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 };\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\n // Check for x402 payment required error in response metadata\n const maybeX402Error = res._meta?.[\"x402/error\"] as\n | (PaymentRequired & Record<string, unknown>)\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 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 // Check max payment value against the first requirement's amount\n const selectedReq = accepts[0];\n if (!selectedReq || selectedReq.scheme !== \"exact\") return res;\n\n let amount: bigint;\n try {\n amount = BigInt(selectedReq.amount);\n } catch {\n return res; // malformed amount — return original error\n }\n if (amount > maxPaymentValue) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Payment exceeds client cap: ${amount} > ${maxPaymentValue}`\n }\n ]\n };\n }\n\n // Reconstruct the PaymentRequired response for the v2 x402 client\n const paymentRequiredResponse: PaymentRequired = {\n x402Version: (maybeX402Error.x402Version as number) ?? 2,\n resource: (maybeX402Error.resource as PaymentRequired[\"resource\"]) ?? {\n url: \"\",\n description: \"\",\n mimeType: \"application/json\"\n },\n accepts,\n extensions: maybeX402Error.extensions as\n | Record<string, unknown>\n | undefined\n };\n\n // Create the payment payload using the v2 x402 client\n let paymentPayload: PaymentPayload;\n try {\n paymentPayload = await paymentClient.createPaymentPayload(\n paymentRequiredResponse\n );\n } catch {\n return {\n isError: true,\n content: [{ type: \"text\", text: \"Failed to create payment payload\" }]\n };\n }\n\n // Encode the payment payload as a base64 JSON token for MCP transport\n const token = btoa(JSON.stringify(paymentPayload));\n\n // Retry the tool call 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 Object.defineProperty(_client, \"listTools\", {\n value: listTools,\n writable: false,\n enumerable: false,\n configurable: true\n });\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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"}
1
+ {"version":3,"file":"x402.js","names":[],"sources":["../../src/mcp/x402.ts"],"sourcesContent":["/**\n * X402 MCP Integration (v2)\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 type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\n\n// v2 imports from @x402/core\nimport { x402ResourceServer, HTTPFacilitatorClient } from \"@x402/core/server\";\nimport type { FacilitatorConfig, ResourceConfig } from \"@x402/core/server\";\nimport { x402Client } from \"@x402/core/client\";\nimport type {\n PaymentPayload,\n PaymentRequirements,\n PaymentRequired,\n Network\n} from \"@x402/core/types\";\n\n// v2 imports from @x402/evm\nimport { registerExactEvmScheme as registerServerEvmScheme } from \"@x402/evm/exact/server\";\nimport { registerExactEvmScheme as registerClientEvmScheme } from \"@x402/evm/exact/client\";\nimport type { ClientEvmSigner } from \"@x402/evm\";\n\n// Re-export commonly used types for consumer convenience\nexport type {\n PaymentRequirements,\n PaymentRequired,\n Network\n} from \"@x402/core/types\";\nexport type { FacilitatorConfig } from \"@x402/core/server\";\nexport type { ClientEvmSigner } from \"@x402/evm\";\n\n/**\n * Map of legacy v1 network names to CAIP-2 identifiers.\n * Allows backward compatibility with v1 config.\n */\nconst LEGACY_NETWORK_MAP: Record<string, string> = {\n \"base-sepolia\": \"eip155:84532\",\n base: \"eip155:8453\",\n ethereum: \"eip155:1\",\n sepolia: \"eip155:11155111\"\n};\n\n/**\n * Normalize a network identifier to CAIP-2 format.\n * Accepts both legacy v1 names (\"base-sepolia\") and CAIP-2 (\"eip155:84532\").\n */\nexport function normalizeNetwork(network: string): Network {\n return (LEGACY_NETWORK_MAP[network] ?? network) as Network;\n}\n\n/*\n ======= SERVER SIDE =======\n*/\n\nexport type X402Config = {\n /**\n * Network identifier.\n * Accepts both legacy names (\"base-sepolia\") and CAIP-2 format (\"eip155:84532\").\n */\n network: string;\n /** Payment recipient address */\n recipient: `0x${string}`;\n /** Facilitator configuration. Defaults to https://x402.org/facilitator */\n facilitator?: FacilitatorConfig;\n /** @deprecated No longer used in v2. The protocol version is determined automatically. */\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: T,\n cfg: X402Config\n): T & X402AugmentedServer {\n const network = normalizeNetwork(cfg.network);\n const facilitatorConfig: FacilitatorConfig = cfg.facilitator ?? {\n url: \"https://x402.org/facilitator\"\n };\n\n // Create v2 resource server with facilitator client\n const facilitatorClient = new HTTPFacilitatorClient(facilitatorConfig);\n const resourceServer = new x402ResourceServer(facilitatorClient);\n registerServerEvmScheme(resourceServer);\n\n // Lazy initialization: fetch supported kinds from facilitator on first use\n let initPromise: Promise<void> | null = null;\n function ensureInitialized(): Promise<void> {\n if (!initPromise) {\n initPromise = resourceServer.initialize().catch((err) => {\n initPromise = null; // allow retry on failure\n throw err;\n });\n }\n return initPromise;\n }\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 await ensureInitialized();\n\n // Build v2 payment requirements for this tool call\n const resourceConfig: ResourceConfig = {\n scheme: \"exact\",\n payTo: cfg.recipient,\n price: priceUSD,\n network,\n maxTimeoutSeconds: 300\n };\n\n let requirements: PaymentRequirements[];\n try {\n requirements =\n await resourceServer.buildPaymentRequirements(resourceConfig);\n } catch {\n const payload = { x402Version: 2, 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\n const resourceInfo = {\n url: `x402://${name}`,\n description,\n mimeType: \"application/json\"\n };\n\n // Get payment token from MCP _meta or HTTP headers\n // Support both v2 (PAYMENT-SIGNATURE) and v1 (X-PAYMENT) header names\n const headers = extra?.requestInfo?.headers ?? {};\n const token =\n (extra?._meta?.[\"x402/payment\"] as string | undefined) ??\n headers[\"PAYMENT-SIGNATURE\"] ??\n headers[\"X-PAYMENT\"];\n\n const paymentRequired = (\n reason = \"PAYMENT_REQUIRED\",\n extraFields: Record<string, unknown> = {}\n ) => {\n const payload = {\n x402Version: 2,\n error: reason,\n resource: resourceInfo,\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 the payment payload (base64-encoded JSON)\n let paymentPayload: PaymentPayload;\n try {\n paymentPayload = JSON.parse(atob(token));\n } catch {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n // Find matching requirements for this payment\n const matchingReq = resourceServer.findMatchingRequirements(\n requirements,\n paymentPayload\n );\n if (!matchingReq) {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n // Verify payment with facilitator\n try {\n const vr = await resourceServer.verifyPayment(\n paymentPayload,\n matchingReq\n );\n if (!vr.isValid) {\n return paymentRequired(vr.invalidReason ?? \"INVALID_PAYMENT\", {\n payer: vr.payer\n });\n }\n } catch {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n // Execute the tool callback\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 payment only on success\n if (!failed) {\n try {\n const s = await resourceServer.settlePayment(\n paymentPayload,\n matchingReq\n );\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\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 /**\n * EVM account/signer for signing payment authorizations.\n * Use `privateKeyToAccount()` from viem/accounts to create one.\n */\n account: ClientEvmSigner;\n /**\n * Preferred network identifier (optional).\n * Accepts both legacy names (\"base-sepolia\") and CAIP-2 format (\"eip155:84532\").\n * When set, the client prefers payment requirements matching this network.\n * If omitted, the client automatically selects from available requirements.\n */\n network?: string;\n /** Maximum payment value in atomic units (default: 0.10 USDC = 100000) */\n maxPaymentValue?: bigint;\n /** @deprecated No longer used in v2. The protocol version is determined automatically. */\n version?: number;\n /** Confirmation callback for payment approval */\n confirmationCallback?: (payment: PaymentRequirements[]) => Promise<boolean>;\n};\n\nexport function withX402Client<T extends MCPClient>(\n client: T,\n x402Config: X402ClientConfig\n): X402AugmentedClient & T {\n const { account } = x402Config;\n\n const maxPaymentValue = x402Config.maxPaymentValue ?? BigInt(100_000); // 0.10 USDC\n\n // Create v2 x402 payment client with EVM scheme support\n const paymentClient = new x402Client();\n registerClientEvmScheme(paymentClient, { signer: account });\n\n // If a preferred network is specified, register a policy to prefer it\n if (x402Config.network) {\n const preferredNetwork = normalizeNetwork(x402Config.network);\n paymentClient.registerPolicy((_version, reqs) => {\n const matching = reqs.filter((r) => r.network === preferredNetwork);\n return matching.length > 0 ? matching : reqs;\n });\n }\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 return {\n ...toolsRes,\n 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 };\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\n // Check for x402 payment required error in response metadata\n const maybeX402Error = res._meta?.[\"x402/error\"] as\n | (PaymentRequired & Record<string, unknown>)\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 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 // Check max payment value against the first requirement's amount\n const selectedReq = accepts[0];\n if (!selectedReq || selectedReq.scheme !== \"exact\") return res;\n\n let amount: bigint;\n try {\n amount = BigInt(selectedReq.amount);\n } catch {\n return res; // malformed amount — return original error\n }\n if (amount > maxPaymentValue) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Payment exceeds client cap: ${amount} > ${maxPaymentValue}`\n }\n ]\n };\n }\n\n // Reconstruct the PaymentRequired response for the v2 x402 client\n const paymentRequiredResponse: PaymentRequired = {\n x402Version: (maybeX402Error.x402Version as number) ?? 2,\n resource: (maybeX402Error.resource as PaymentRequired[\"resource\"]) ?? {\n url: \"\",\n description: \"\",\n mimeType: \"application/json\"\n },\n accepts,\n extensions: maybeX402Error.extensions as\n | Record<string, unknown>\n | undefined\n };\n\n // Create the payment payload using the v2 x402 client\n let paymentPayload: PaymentPayload;\n try {\n paymentPayload = await paymentClient.createPaymentPayload(\n paymentRequiredResponse\n );\n } catch {\n return {\n isError: true,\n content: [{ type: \"text\", text: \"Failed to create payment payload\" }]\n };\n }\n\n // Encode the payment payload as a base64 JSON token for MCP transport\n const token = btoa(JSON.stringify(paymentPayload));\n\n // Retry the tool call 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 Object.defineProperty(_client, \"listTools\", {\n value: listTools,\n writable: false,\n enumerable: false,\n configurable: true\n });\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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"}
@@ -1,2 +1,16 @@
1
- import { a as genericObservability, i as channels, n as Observability, o as subscribe, r as ObservabilityEvent, t as ChannelEventMap } from "../index-Biv6K70p.js";
2
- export { ChannelEventMap, Observability, ObservabilityEvent, channels, genericObservability, subscribe };
1
+ import {
2
+ a as genericObservability,
3
+ i as channels,
4
+ n as Observability,
5
+ o as subscribe,
6
+ r as ObservabilityEvent,
7
+ t as ChannelEventMap
8
+ } from "../index-DKey3P4s.js";
9
+ export {
10
+ ChannelEventMap,
11
+ Observability,
12
+ ObservabilityEvent,
13
+ channels,
14
+ genericObservability,
15
+ subscribe
16
+ };
@@ -32,7 +32,7 @@ function getChannel(type) {
32
32
  if (type.startsWith("mcp:")) return channels.mcp;
33
33
  if (type.startsWith("workflow:")) return channels.workflow;
34
34
  if (type.startsWith("schedule:") || type.startsWith("queue:")) return channels.schedule;
35
- if (type.startsWith("message:") || type.startsWith("tool:")) return channels.message;
35
+ if (type.startsWith("message:") || type.startsWith("tool:") || type.startsWith("submission:")) return channels.message;
36
36
  if (type === "rpc" || type.startsWith("rpc:")) return channels.rpc;
37
37
  if (type.startsWith("state:")) return channels.state;
38
38
  if (type.startsWith("email:")) return channels.email;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["dcUnsubscribe"],"sources":["../../src/observability/index.ts"],"sourcesContent":["import {\n channel,\n subscribe as dcSubscribe,\n unsubscribe as dcUnsubscribe,\n type Channel\n} from \"node:diagnostics_channel\";\nimport type { AgentObservabilityEvent } from \"./agent\";\nimport type { MCPObservabilityEvent } from \"./mcp\";\n\n/**\n * Union of all observability event types from different domains\n */\nexport type ObservabilityEvent =\n | AgentObservabilityEvent\n | MCPObservabilityEvent;\n\nexport interface Observability {\n /**\n * Emit an event for the Agent's observability implementation to handle.\n * @param event - The event to emit\n */\n emit(event: ObservabilityEvent): void;\n}\n\n/**\n * Diagnostics channels for agent observability.\n *\n * Events are published to named channels using the Node.js diagnostics_channel API.\n * By default, publishing to a channel with no subscribers is a no-op (zero overhead).\n *\n * To observe events, subscribe to the channels you care about:\n * ```ts\n * import { subscribe } from \"node:diagnostics_channel\";\n * subscribe(\"agents:rpc\", (event) => console.log(event));\n * ```\n *\n * In production, all published messages are automatically forwarded to\n * Tail Workers via `event.diagnosticsChannelEvents` — no subscription needed.\n */\nexport const channels = {\n state: channel(\"agents:state\"),\n rpc: channel(\"agents:rpc\"),\n message: channel(\"agents:message\"),\n schedule: channel(\"agents:schedule\"),\n lifecycle: channel(\"agents:lifecycle\"),\n workflow: channel(\"agents:workflow\"),\n mcp: channel(\"agents:mcp\"),\n email: channel(\"agents:email\")\n} as const;\n\n/**\n * Map event type prefixes to their diagnostics channel.\n */\nfunction getChannel(type: string): Channel {\n if (type.startsWith(\"mcp:\")) return channels.mcp;\n if (type.startsWith(\"workflow:\")) return channels.workflow;\n if (type.startsWith(\"schedule:\") || type.startsWith(\"queue:\"))\n return channels.schedule;\n if (type.startsWith(\"message:\") || type.startsWith(\"tool:\"))\n return channels.message;\n if (type === \"rpc\" || type.startsWith(\"rpc:\")) return channels.rpc;\n if (type.startsWith(\"state:\")) return channels.state;\n if (type.startsWith(\"email:\")) return channels.email;\n // connect, disconnect, destroy\n return channels.lifecycle;\n}\n\n/**\n * The default observability implementation.\n *\n * Publishes events to diagnostics_channel. Events are silent unless\n * a subscriber is registered or a Tail Worker is attached.\n */\nexport const genericObservability: Observability = {\n emit(event) {\n getChannel(event.type).publish(event);\n }\n};\n\n/**\n * Maps each channel key to the observability events it carries.\n */\nexport type ChannelEventMap = {\n state: Extract<ObservabilityEvent, { type: `state:${string}` }>;\n rpc: Extract<ObservabilityEvent, { type: \"rpc\" | `rpc:${string}` }>;\n message: Extract<\n ObservabilityEvent,\n { type: `message:${string}` | `tool:${string}` }\n >;\n schedule: Extract<\n ObservabilityEvent,\n { type: `schedule:${string}` | `queue:${string}` }\n >;\n lifecycle: Extract<\n ObservabilityEvent,\n { type: \"connect\" | \"disconnect\" | \"destroy\" }\n >;\n workflow: Extract<ObservabilityEvent, { type: `workflow:${string}` }>;\n mcp: Extract<ObservabilityEvent, { type: `mcp:${string}` }>;\n email: Extract<ObservabilityEvent, { type: `email:${string}` }>;\n};\n\n/**\n * Subscribe to a typed observability channel.\n *\n * ```ts\n * import { subscribe } from \"agents/observability\";\n *\n * const unsub = subscribe(\"rpc\", (event) => {\n * console.log(event.payload.method); // fully typed\n * });\n * ```\n *\n * @returns A function that unsubscribes the callback.\n */\nexport function subscribe<K extends keyof ChannelEventMap>(\n channelKey: K,\n callback: (event: ChannelEventMap[K]) => void\n): () => void {\n const name = `agents:${channelKey}`;\n const handler = (message: unknown, _name: string | symbol) =>\n callback(message as ChannelEventMap[K]);\n dcSubscribe(name, handler);\n return () => dcUnsubscribe(name, handler);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAuCA,MAAa,WAAW;CACtB,OAAO,QAAQ,eAAe;CAC9B,KAAK,QAAQ,aAAa;CAC1B,SAAS,QAAQ,iBAAiB;CAClC,UAAU,QAAQ,kBAAkB;CACpC,WAAW,QAAQ,mBAAmB;CACtC,UAAU,QAAQ,kBAAkB;CACpC,KAAK,QAAQ,aAAa;CAC1B,OAAO,QAAQ,eAAe;CAC/B;;;;AAKD,SAAS,WAAW,MAAuB;AACzC,KAAI,KAAK,WAAW,OAAO,CAAE,QAAO,SAAS;AAC7C,KAAI,KAAK,WAAW,YAAY,CAAE,QAAO,SAAS;AAClD,KAAI,KAAK,WAAW,YAAY,IAAI,KAAK,WAAW,SAAS,CAC3D,QAAO,SAAS;AAClB,KAAI,KAAK,WAAW,WAAW,IAAI,KAAK,WAAW,QAAQ,CACzD,QAAO,SAAS;AAClB,KAAI,SAAS,SAAS,KAAK,WAAW,OAAO,CAAE,QAAO,SAAS;AAC/D,KAAI,KAAK,WAAW,SAAS,CAAE,QAAO,SAAS;AAC/C,KAAI,KAAK,WAAW,SAAS,CAAE,QAAO,SAAS;AAE/C,QAAO,SAAS;;;;;;;;AASlB,MAAa,uBAAsC,EACjD,KAAK,OAAO;AACV,YAAW,MAAM,KAAK,CAAC,QAAQ,MAAM;GAExC;;;;;;;;;;;;;;AAsCD,SAAgB,UACd,YACA,UACY;CACZ,MAAM,OAAO,UAAU;CACvB,MAAM,WAAW,SAAkB,UACjC,SAAS,QAA8B;AACzC,aAAY,MAAM,QAAQ;AAC1B,cAAaA,YAAc,MAAM,QAAQ"}
1
+ {"version":3,"file":"index.js","names":["dcUnsubscribe"],"sources":["../../src/observability/index.ts"],"sourcesContent":["import {\n channel,\n subscribe as dcSubscribe,\n unsubscribe as dcUnsubscribe,\n type Channel\n} from \"node:diagnostics_channel\";\nimport type { AgentObservabilityEvent } from \"./agent\";\nimport type { MCPObservabilityEvent } from \"./mcp\";\n\n/**\n * Union of all observability event types from different domains\n */\nexport type ObservabilityEvent =\n | AgentObservabilityEvent\n | MCPObservabilityEvent;\n\nexport interface Observability {\n /**\n * Emit an event for the Agent's observability implementation to handle.\n * @param event - The event to emit\n */\n emit(event: ObservabilityEvent): void;\n}\n\n/**\n * Diagnostics channels for agent observability.\n *\n * Events are published to named channels using the Node.js diagnostics_channel API.\n * By default, publishing to a channel with no subscribers is a no-op (zero overhead).\n *\n * To observe events, subscribe to the channels you care about:\n * ```ts\n * import { subscribe } from \"node:diagnostics_channel\";\n * subscribe(\"agents:rpc\", (event) => console.log(event));\n * ```\n *\n * In production, all published messages are automatically forwarded to\n * Tail Workers via `event.diagnosticsChannelEvents` — no subscription needed.\n */\nexport const channels = {\n state: channel(\"agents:state\"),\n rpc: channel(\"agents:rpc\"),\n message: channel(\"agents:message\"),\n schedule: channel(\"agents:schedule\"),\n lifecycle: channel(\"agents:lifecycle\"),\n workflow: channel(\"agents:workflow\"),\n mcp: channel(\"agents:mcp\"),\n email: channel(\"agents:email\")\n} as const;\n\n/**\n * Map event type prefixes to their diagnostics channel.\n */\nfunction getChannel(type: string): Channel {\n if (type.startsWith(\"mcp:\")) return channels.mcp;\n if (type.startsWith(\"workflow:\")) return channels.workflow;\n if (type.startsWith(\"schedule:\") || type.startsWith(\"queue:\"))\n return channels.schedule;\n if (\n type.startsWith(\"message:\") ||\n type.startsWith(\"tool:\") ||\n type.startsWith(\"submission:\")\n )\n return channels.message;\n if (type === \"rpc\" || type.startsWith(\"rpc:\")) return channels.rpc;\n if (type.startsWith(\"state:\")) return channels.state;\n if (type.startsWith(\"email:\")) return channels.email;\n // connect, disconnect, destroy\n return channels.lifecycle;\n}\n\n/**\n * The default observability implementation.\n *\n * Publishes events to diagnostics_channel. Events are silent unless\n * a subscriber is registered or a Tail Worker is attached.\n */\nexport const genericObservability: Observability = {\n emit(event) {\n getChannel(event.type).publish(event);\n }\n};\n\n/**\n * Maps each channel key to the observability events it carries.\n */\nexport type ChannelEventMap = {\n state: Extract<ObservabilityEvent, { type: `state:${string}` }>;\n rpc: Extract<ObservabilityEvent, { type: \"rpc\" | `rpc:${string}` }>;\n message: Extract<\n ObservabilityEvent,\n { type: `message:${string}` | `tool:${string}` | `submission:${string}` }\n >;\n schedule: Extract<\n ObservabilityEvent,\n { type: `schedule:${string}` | `queue:${string}` }\n >;\n lifecycle: Extract<\n ObservabilityEvent,\n { type: \"connect\" | \"disconnect\" | \"destroy\" }\n >;\n workflow: Extract<ObservabilityEvent, { type: `workflow:${string}` }>;\n mcp: Extract<ObservabilityEvent, { type: `mcp:${string}` }>;\n email: Extract<ObservabilityEvent, { type: `email:${string}` }>;\n};\n\n/**\n * Subscribe to a typed observability channel.\n *\n * ```ts\n * import { subscribe } from \"agents/observability\";\n *\n * const unsub = subscribe(\"rpc\", (event) => {\n * console.log(event.payload.method); // fully typed\n * });\n * ```\n *\n * @returns A function that unsubscribes the callback.\n */\nexport function subscribe<K extends keyof ChannelEventMap>(\n channelKey: K,\n callback: (event: ChannelEventMap[K]) => void\n): () => void {\n const name = `agents:${channelKey}`;\n const handler = (message: unknown, _name: string | symbol) =>\n callback(message as ChannelEventMap[K]);\n dcSubscribe(name, handler);\n return () => dcUnsubscribe(name, handler);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAuCA,MAAa,WAAW;CACtB,OAAO,QAAQ,eAAe;CAC9B,KAAK,QAAQ,aAAa;CAC1B,SAAS,QAAQ,iBAAiB;CAClC,UAAU,QAAQ,kBAAkB;CACpC,WAAW,QAAQ,mBAAmB;CACtC,UAAU,QAAQ,kBAAkB;CACpC,KAAK,QAAQ,aAAa;CAC1B,OAAO,QAAQ,eAAe;CAC/B;;;;AAKD,SAAS,WAAW,MAAuB;CACzC,IAAI,KAAK,WAAW,OAAO,EAAE,OAAO,SAAS;CAC7C,IAAI,KAAK,WAAW,YAAY,EAAE,OAAO,SAAS;CAClD,IAAI,KAAK,WAAW,YAAY,IAAI,KAAK,WAAW,SAAS,EAC3D,OAAO,SAAS;CAClB,IACE,KAAK,WAAW,WAAW,IAC3B,KAAK,WAAW,QAAQ,IACxB,KAAK,WAAW,cAAc,EAE9B,OAAO,SAAS;CAClB,IAAI,SAAS,SAAS,KAAK,WAAW,OAAO,EAAE,OAAO,SAAS;CAC/D,IAAI,KAAK,WAAW,SAAS,EAAE,OAAO,SAAS;CAC/C,IAAI,KAAK,WAAW,SAAS,EAAE,OAAO,SAAS;CAE/C,OAAO,SAAS;;;;;;;;AASlB,MAAa,uBAAsC,EACjD,KAAK,OAAO;CACV,WAAW,MAAM,KAAK,CAAC,QAAQ,MAAM;GAExC;;;;;;;;;;;;;;AAsCD,SAAgB,UACd,YACA,UACY;CACZ,MAAM,OAAO,UAAU;CACvB,MAAM,WAAW,SAAkB,UACjC,SAAS,QAA8B;CACzC,YAAY,MAAM,QAAQ;CAC1B,aAAaA,YAAc,MAAM,QAAQ"}
package/dist/react.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
- N as MCPServersState,
2
+ P as MCPServersState,
3
3
  l as AgentToolRunState
4
- } from "./agent-tool-types-DSteYkkS.js";
4
+ } from "./agent-tool-types-CM_50fcV.js";
5
5
  import { ClientParameters } from "./serializable.js";
6
6
  import {
7
7
  AgentPromiseReturnType,
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":[],"sources":["../src/react.tsx"],"sourcesContent":["import type { PartySocket } from \"partysocket\";\nimport { usePartySocket } from \"partysocket/react\";\nimport { useCallback, useRef, use, useMemo, useState, useEffect } from \"react\";\nimport type { MCPServersState, RPCRequest, RPCResponse } from \"./\";\nimport type {\n AgentPromiseReturnType,\n AgentStub,\n CallOptions,\n OptionalAgentMethods,\n RequiredAgentMethods,\n StreamOptions,\n UntypedAgentStub\n} from \"./client\";\nimport type { ClientParameters } from \"./serializable\";\nimport { createStubProxy } from \"./client\";\nimport { camelCaseToKebabCase } from \"./utils\";\nimport { MessageType } from \"./types\";\nimport {\n applyAgentToolEvent,\n createAgentToolEventState,\n type AgentToolEventMessage,\n type AgentToolEventState,\n type AgentToolRunState\n} from \"./chat/agent-tools\";\n\ntype QueryObject = Record<string, string | null>;\n\ninterface CacheEntry {\n promise: Promise<QueryObject>;\n expiresAt: number;\n}\n\nconst queryCache = new Map<string, CacheEntry>();\n\nfunction createCacheKey(\n agentNamespace: string,\n name: string | undefined,\n subChainOrDeps: ReadonlyArray<{ agent: string; name: string }> | unknown[],\n deps?: unknown[]\n): string {\n // Backwards-compatible overload: if called with 3 args, the third\n // argument is `deps` and `subChain` defaults to empty. With 4 args,\n // the third is the sub-chain. This keeps existing callers (and\n // the `_testUtils` surface) working while letting new callers\n // include the nested chain in the cache key.\n //\n // Empty sub-chain must produce the same key as the old 3-arg\n // form, so nested-addressing code can opt-in without invalidating\n // existing caches.\n if (deps === undefined) {\n return JSON.stringify([\n agentNamespace,\n name || \"default\",\n ...(subChainOrDeps as unknown[])\n ]);\n }\n const subChain = subChainOrDeps as ReadonlyArray<{\n agent: string;\n name: string;\n }>;\n if (subChain.length === 0) {\n return JSON.stringify([agentNamespace, name || \"default\", ...deps]);\n }\n return JSON.stringify([\n agentNamespace,\n name || \"default\",\n subChain.map((s) => [s.agent, s.name]),\n ...deps\n ]);\n}\n\n/** Build a URL path tail `/sub/{agent-kebab}/{name}/...` from a sub chain. */\nfunction buildSubPath(\n subChain: ReadonlyArray<{ agent: string; name: string }>,\n extraPath?: string\n): string {\n if (subChain.length === 0) return extraPath ?? \"\";\n const parts = subChain.flatMap((step) => [\n \"sub\",\n camelCaseToKebabCase(step.agent),\n encodeURIComponent(step.name)\n ]);\n const combined = parts.join(\"/\");\n if (extraPath) {\n const trimmed = extraPath.startsWith(\"/\") ? extraPath.slice(1) : extraPath;\n return `${combined}/${trimmed}`;\n }\n return combined;\n}\n\nfunction getCacheEntry(key: string): CacheEntry | undefined {\n const entry = queryCache.get(key);\n if (!entry) return undefined;\n\n if (Date.now() >= entry.expiresAt) {\n queryCache.delete(key);\n return undefined;\n }\n\n return entry;\n}\n\nfunction setCacheEntry(\n key: string,\n promise: Promise<QueryObject>,\n cacheTtl: number\n): CacheEntry {\n const entry: CacheEntry = {\n promise,\n expiresAt: Date.now() + cacheTtl\n };\n queryCache.set(key, entry);\n return entry;\n}\n\nfunction deleteCacheEntry(key: string): void {\n queryCache.delete(key);\n}\n\n// Export for testing purposes\nexport const _testUtils = {\n queryCache,\n setCacheEntry,\n getCacheEntry,\n deleteCacheEntry,\n clearCache: () => queryCache.clear(),\n createStubProxy,\n createCacheKey\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 (ignored if basePath is set) */\n agent: string;\n /** Name of the specific Agent instance (ignored if basePath is set) */\n name?: string;\n /**\n * Full URL path - bypasses agent/name URL construction.\n * When set, the client connects to this path directly.\n * Server must handle routing manually (e.g., with getAgentByName + fetch).\n * @example\n * // Client connects to /user, server routes based on session\n * useAgent({ agent: \"UserAgent\", basePath: \"user\" })\n */\n basePath?: 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 a state update fails (e.g., connection is readonly) */\n onStateUpdateError?: (error: string) => void;\n /** Called when MCP server state is updated */\n onMcpUpdate?: (mcpServers: MCPServersState) => void;\n /**\n * Called when the server sends the agent's identity on connect.\n * Useful when using basePath, as the actual instance name is determined server-side.\n * @param name The actual agent instance name\n * @param agent The agent class name (kebab-case)\n */\n onIdentity?: (name: string, agent: string) => void;\n /**\n * Called when identity changes on reconnect (different instance than before).\n * If not provided and identity changes, a warning will be logged.\n * @param oldName Previous instance name\n * @param newName New instance name\n * @param oldAgent Previous agent class name\n * @param newAgent New agent class name\n */\n onIdentityChange?: (\n oldName: string,\n newName: string,\n oldAgent: string,\n newAgent: string\n ) => void;\n /**\n * Additional path to append to the URL.\n * Works with both standard routing and basePath.\n * @example\n * // With basePath: /user/settings\n * { basePath: \"user\", path: \"settings\" }\n * // Standard: /agents/my-agent/room/settings\n * { agent: \"MyAgent\", name: \"room\", path: \"settings\" }\n */\n path?: string;\n /**\n * Connect to a sub-agent (facet) via its parent. Flat array,\n * root-first. Each step addresses one parent↔child hop.\n *\n * The hook's returned `.agent` / `.name` report the **leaf**\n * identity (the deepest entry in `sub`), so downstream hooks\n * like `useAgentChat` see the child they actually talk to.\n * `.path` exposes the full chain for observability, deep links,\n * and reconnect keying.\n *\n * @example\n * ```ts\n * // Two-level nesting: Inbox (Alice) → Chat (abc)\n * useAgent({\n * agent: \"inbox\", name: userId,\n * sub: [{ agent: \"chat\", name: chatId }]\n * });\n *\n * // Three-level: tenant → inbox → chat\n * useAgent({\n * agent: \"tenant\", name: tenantId,\n * sub: [\n * { agent: \"inbox\", name: userId },\n * { agent: \"chat\", name: chatId }\n * ]\n * });\n * ```\n *\n * @experimental The API surface may change before stabilizing.\n */\n sub?: ReadonlyArray<{ agent: string; name: string }>;\n};\n\ntype OptionalArgsAgentMethodCall<AgentT> = <\n K extends keyof OptionalAgentMethods<AgentT>\n>(\n method: K,\n args?: ClientParameters<OptionalAgentMethods<AgentT>[K]>,\n options?: CallOptions | StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype RequiredArgsAgentMethodCall<AgentT> = <\n K extends keyof RequiredAgentMethods<AgentT>\n>(\n method: K,\n args: ClientParameters<RequiredAgentMethods<AgentT>[K]>,\n options?: CallOptions | 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 options?: CallOptions | StreamOptions\n) => Promise<T>;\n\n/**\n * React hook for connecting to an Agent\n */\nexport function useAgent<State = unknown>(\n options: UseAgentOptions<State>\n): Omit<PartySocket, \"path\"> & {\n agent: string;\n name: string;\n /** Full root-first address chain, including leaf. Single entry when `sub` isn't set. */\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n};\nexport function useAgent<\n AgentT extends {\n get state(): State;\n },\n State\n>(\n options: UseAgentOptions<State>\n): Omit<PartySocket, \"path\"> & {\n agent: string;\n name: string;\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n setState: (state: State) => void;\n call: AgentMethodCall<AgentT>;\n stub: AgentStub<AgentT>;\n getHttpUrl: () => string;\n};\nexport function useAgent<State>(options: UseAgentOptions<unknown>): Omit<\n PartySocket,\n \"path\"\n> & {\n agent: string;\n name: string;\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall | AgentMethodCall<unknown>;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n} {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n // NOTE: `path` is destructured out (as `userPath`) so it does NOT\n // end up in `restOptions`. Spreading `restOptions` after the\n // computed `path: combinedPath` would otherwise let the user's raw\n // `path` overwrite the combined sub-agent URL, dropping every\n // `/sub/{child}/{name}` segment on the way to the socket.\n const {\n query,\n queryDeps,\n cacheTtl,\n sub: subOption,\n path: userPath,\n ...restOptions\n } = options;\n\n const subChain = useMemo(\n () => (subOption ?? []).map((s) => ({ agent: s.agent, name: s.name })),\n // Stable serialization — deep changes re-memoize.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(subOption ?? [])]\n );\n\n // The \"leaf\" is the deepest entry in the chain; it's what\n // downstream code (useAgentChat etc.) should see as the\n // authoritative identity.\n const leafAgent =\n subChain.length > 0 ? subChain[subChain.length - 1].agent : options.agent;\n const leafName =\n subChain.length > 0\n ? subChain[subChain.length - 1].name\n : options.name || \"default\";\n\n // Full root-first chain, including the leaf. Exposed as `.path`\n // and used for cache keying so nested sessions with the same leaf\n // name don't collide.\n const fullPath = useMemo(\n () => [\n { agent: options.agent, name: options.name || \"default\" },\n ...subChain\n ],\n [options.agent, options.name, subChain]\n );\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 timeoutId?: ReturnType<typeof setTimeout>;\n }\n >()\n );\n\n const cacheKey = useMemo(\n () =>\n createCacheKey(agentNamespace, options.name, subChain, queryDeps || []),\n [agentNamespace, options.name, subChain, queryDeps]\n );\n\n // Track current cache key in a ref for use in onClose handler.\n // This ensures we invalidate the correct cache entry when the connection closes,\n // even if the component re-renders with different props before onClose fires.\n // We update synchronously during render (not in useEffect) to avoid race\n // conditions where onClose could fire before the effect runs.\n const cacheKeyRef = useRef(cacheKey);\n cacheKeyRef.current = cacheKey;\n\n const ttl = cacheTtl ?? 5 * 60 * 1000;\n\n // Track cache invalidation to force re-render when TTL expires\n const [cacheInvalidatedAt, setCacheInvalidatedAt] = useState<number>(0);\n\n // Disable socket while waiting for async query to refresh after disconnect\n const isAsyncQuery = query && typeof query === \"function\";\n const [awaitingQueryRefresh, setAwaitingQueryRefresh] = useState(false);\n\n // Get or create the query promise\n const queryPromise = useMemo(() => {\n // Re-run when cache is invalidated after TTL expiry\n void cacheInvalidatedAt;\n\n if (!query || typeof query !== \"function\") {\n return null;\n }\n\n // Always check cache first to deduplicate concurrent requests\n const cached = getCacheEntry(cacheKey);\n if (cached) {\n return cached.promise;\n }\n\n // Create new promise\n const promise = query().catch((error) => {\n console.error(\n `[useAgent] Query failed for agent \"${options.agent}\":`,\n error\n );\n deleteCacheEntry(cacheKey);\n throw error;\n });\n\n // Always cache to deduplicate concurrent requests\n setCacheEntry(cacheKey, promise, ttl);\n\n return promise;\n }, [cacheKey, query, options.agent, ttl, cacheInvalidatedAt]);\n\n // Schedule cache invalidation when TTL expires\n useEffect(() => {\n if (!queryPromise || ttl <= 0) return;\n\n const entry = getCacheEntry(cacheKey);\n if (!entry) return;\n\n const timeUntilExpiry = entry.expiresAt - Date.now();\n\n // Always set a timer (with min 0ms) to ensure cleanup function is returned\n const timer = setTimeout(\n () => {\n deleteCacheEntry(cacheKey);\n setCacheInvalidatedAt(Date.now());\n },\n Math.max(0, timeUntilExpiry)\n );\n\n return () => clearTimeout(timer);\n }, [cacheKey, queryPromise, ttl]);\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 // Re-enable socket after async query resolves\n useEffect(() => {\n if (awaitingQueryRefresh && resolvedQuery !== undefined) {\n setAwaitingQueryRefresh(false);\n }\n }, [awaitingQueryRefresh, resolvedQuery]);\n\n // Track agent state for reactivity — updated on server broadcasts and client setState\n const [agentState, setAgentState] = useState<State | undefined>(undefined);\n\n // Store identity in React state for reactivity. Seed with the\n // leaf's address — what the server will echo back in\n // `cf_agent_identity`.\n const [identity, setIdentity] = useState({\n name: leafName,\n agent: camelCaseToKebabCase(leafAgent),\n identified: false\n });\n\n // Track previous identity for change detection\n const previousIdentityRef = useRef<{\n name: string | null;\n agent: string | null;\n }>({ name: null, agent: null });\n\n // Ready promise - resolves when identity is received, resets on close\n const readyRef = useRef<\n { promise: Promise<void>; resolve: () => void } | undefined\n >(undefined);\n\n const resetReady = () => {\n let resolve: () => void;\n const promise = new Promise<void>((r) => {\n resolve = r;\n });\n readyRef.current = { promise, resolve: resolve! };\n };\n\n if (!readyRef.current) {\n resetReady();\n }\n\n const mutableAgentRef = useRef<{\n agent: string;\n name: string;\n identified: boolean;\n } | null>(null);\n\n // Combine the sub-agent chain with the user-provided `path`.\n // Order matters: `/sub/{child}/{name}/...` comes before `path` so\n // the server sees the hierarchy it expects.\n const combinedPath = useMemo(\n () => buildSubPath(subChain, userPath),\n [subChain, userPath]\n );\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n const socketOptions = options.basePath\n ? {\n basePath: options.basePath,\n path: combinedPath || undefined,\n query: resolvedQuery,\n ...restOptions\n }\n : {\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n path: combinedPath || undefined,\n query: resolvedQuery,\n ...restOptions\n };\n\n const socketEnabled = !awaitingQueryRefresh && (restOptions.enabled ?? true);\n\n const agent = usePartySocket({\n ...socketOptions,\n enabled: socketEnabled,\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_IDENTITY) {\n const oldName = previousIdentityRef.current.name;\n const oldAgent = previousIdentityRef.current.agent;\n const newName = parsedMessage.name as string;\n const newAgent = parsedMessage.agent as string;\n\n const currentAgent = mutableAgentRef.current;\n if (currentAgent) {\n currentAgent.name = newName;\n currentAgent.agent = newAgent;\n currentAgent.identified = true;\n }\n\n // Update reactive state (triggers re-render)\n setIdentity({ name: newName, agent: newAgent, identified: true });\n\n // Resolve ready promise\n readyRef.current?.resolve();\n\n // Detect identity change on reconnect\n if (\n oldName !== null &&\n oldAgent !== null &&\n (oldName !== newName || oldAgent !== newAgent)\n ) {\n if (options.onIdentityChange) {\n options.onIdentityChange(oldName, newName, oldAgent, newAgent);\n } else {\n const agentChanged = oldAgent !== newAgent;\n const nameChanged = oldName !== newName;\n let changeDescription = \"\";\n if (agentChanged && nameChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\", instance \"${oldName}\" → \"${newName}\"`;\n } else if (agentChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\"`;\n } else {\n changeDescription = `instance \"${oldName}\" → \"${newName}\"`;\n }\n console.warn(\n `[agents] Identity changed on reconnect: ${changeDescription}. ` +\n \"This can happen with server-side routing (e.g., basePath with getAgentByName) \" +\n \"where the instance is determined by auth/session. \" +\n \"Provide onIdentityChange callback to handle this explicitly, \" +\n \"or ignore if this is expected for your routing pattern.\"\n );\n }\n }\n\n // Track for next change detection\n previousIdentityRef.current = { name: newName, agent: newAgent };\n\n // Call onIdentity callback\n options.onIdentity?.(newName, newAgent);\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n setAgentState(parsedMessage.state as State);\n options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE_ERROR) {\n options.onStateUpdateError?.(parsedMessage.error as string);\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 if (pending.timeoutId) clearTimeout(pending.timeoutId);\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 if (pending.timeoutId) clearTimeout(pending.timeoutId);\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 if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n }\n return;\n }\n }\n options.onMessage?.(message);\n },\n onClose: (event: CloseEvent) => {\n // Reset ready state for next connection\n resetReady();\n if (mutableAgentRef.current) {\n mutableAgentRef.current.identified = false;\n }\n setIdentity((prev) => ({ ...prev, identified: false }));\n\n // Pause reconnection for async queries until fresh query params are ready\n if (isAsyncQuery) {\n setAwaitingQueryRefresh(true);\n }\n\n // Invalidate cache and trigger re-render to fetch fresh query params\n deleteCacheEntry(cacheKeyRef.current);\n setCacheInvalidatedAt(Date.now());\n\n // Reject all pending calls (consistent with AgentClient behavior)\n const error = new Error(\"Connection closed\");\n for (const pending of pendingCallsRef.current.values()) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.reject(error);\n pending.stream?.onError?.(\"Connection closed\");\n }\n pendingCallsRef.current.clear();\n\n // Call user's onClose if provided\n options.onClose?.(event);\n }\n }) as PartySocket & {\n agent: string;\n name: string;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n };\n // Create the call method\n const call = useCallback(\n <T = unknown,>(\n method: string,\n args: unknown[] = [],\n options?: CallOptions | StreamOptions\n ): Promise<T> => {\n return new Promise((resolve, reject) => {\n const id = crypto.randomUUID();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Detect legacy format: { onChunk?, onDone?, onError? } vs new format: { timeout?, stream? }\n const isLegacyFormat =\n options &&\n (\"onChunk\" in options || \"onDone\" in options || \"onError\" in options);\n const streamOptions = isLegacyFormat\n ? (options as StreamOptions)\n : (options as CallOptions | undefined)?.stream;\n const timeout = isLegacyFormat\n ? undefined\n : (options as CallOptions | undefined)?.timeout;\n\n if (timeout) {\n timeoutId = setTimeout(() => {\n const pending = pendingCallsRef.current.get(id);\n pendingCallsRef.current.delete(id);\n const errorMessage = `RPC call to ${method} timed out after ${timeout}ms`;\n pending?.stream?.onError?.(errorMessage);\n reject(new Error(errorMessage));\n }, timeout);\n }\n\n pendingCallsRef.current.set(id, {\n reject,\n resolve: resolve as (value: unknown) => void,\n stream: streamOptions,\n timeoutId\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 = (newState: State) => {\n agent.send(\n JSON.stringify({ state: newState, type: MessageType.CF_AGENT_STATE })\n );\n setAgentState(newState);\n options.onStateUpdate?.(newState, \"client\");\n };\n\n agent.call = call;\n // Use reactive identity state (updates on identity message)\n agent.agent = identity.agent;\n agent.name = identity.name;\n // Full root-first chain including the leaf. Computed from the\n // user-provided options — the server doesn't need to echo it\n // back because the client already knows. Write past the\n // PartySocket `.path: string` shape via an unknown cast — the\n // overload signatures expose this as `ReadonlyArray<...>`.\n (\n agent as unknown as { path: ReadonlyArray<{ agent: string; name: string }> }\n ).path = fullPath;\n agent.identified = identity.identified;\n agent.ready = readyRef.current!.promise;\n agent.state = agentState;\n mutableAgentRef.current = agent;\n // Memoize stub so it's referentially stable across renders\n // (call is already stable via useCallback)\n const stub = useMemo(() => createStubProxy(call), [call]);\n agent.stub = stub;\n agent.getHttpUrl = () => {\n // TODO: upstream to partysocket — expose an HTTP URL property\n // @ts-expect-error accessing protected PartySocket internals\n const wsUrl: string = (agent._url as string | null) || agent._pkurl || \"\";\n return wsUrl.replace(\"ws://\", \"http://\").replace(\"wss://\", \"https://\");\n };\n\n // warn if agent isn't in lowercase\n if (identity.agent !== identity.agent.toLowerCase()) {\n console.warn(\n \"Agent name: \" +\n identity.agent +\n \" should probably be in lowercase. Received: \" +\n identity.agent\n );\n }\n\n // The overload signatures return `Omit<PartySocket, \"path\"> & { path: ... }`,\n // but `agent` is inferred as the raw PartySocket. Cast to satisfy\n // the overload contract — the runtime override of `agent.path`\n // above ensures the shape matches.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return agent as any;\n}\n\ntype AgentToolEventAgent = Pick<\n PartySocket,\n \"addEventListener\" | \"removeEventListener\"\n>;\n\nfunction agentToolDedupeKey(message: AgentToolEventMessage): string {\n return [\n message.parentToolCallId ?? \"\",\n message.event.runId,\n String(message.sequence)\n ].join(\"\\0\");\n}\n\nexport function useAgentToolEvents(options: { agent: AgentToolEventAgent }): {\n runsById: Record<string, AgentToolRunState>;\n runsByToolCallId: Record<string, AgentToolRunState[]>;\n unboundRuns: AgentToolRunState[];\n getRunsForToolCall(toolCallId: string): AgentToolRunState[];\n resetLocalState(): void;\n} {\n const { agent } = options;\n const [state, setState] = useState<AgentToolEventState>(() =>\n createAgentToolEventState()\n );\n const seenRef = useRef(new Set<string>());\n\n useEffect(() => {\n const onMessage = (event: MessageEvent) => {\n if (typeof event.data !== \"string\") return;\n let message: AgentToolEventMessage;\n try {\n message = JSON.parse(event.data) as AgentToolEventMessage;\n } catch {\n return;\n }\n if (message.type !== \"agent-tool-event\") return;\n const key = agentToolDedupeKey(message);\n if (seenRef.current.has(key)) return;\n seenRef.current.add(key);\n setState((prev) => applyAgentToolEvent(prev, message));\n };\n\n agent.addEventListener(\"message\", onMessage);\n return () => agent.removeEventListener(\"message\", onMessage);\n }, [agent]);\n\n const resetLocalState = useCallback(() => {\n seenRef.current.clear();\n setState(createAgentToolEventState());\n }, []);\n\n const getRunsForToolCall = useCallback(\n (toolCallId: string) => state.runsByToolCallId[toolCallId] ?? [],\n [state.runsByToolCallId]\n );\n\n return {\n ...state,\n getRunsForToolCall,\n resetLocalState\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"react.js","names":[],"sources":["../src/react.tsx"],"sourcesContent":["import type { PartySocket } from \"partysocket\";\nimport { usePartySocket } from \"partysocket/react\";\nimport { useCallback, useRef, use, useMemo, useState, useEffect } from \"react\";\nimport type { MCPServersState, RPCRequest, RPCResponse } from \"./\";\nimport type {\n AgentPromiseReturnType,\n AgentStub,\n CallOptions,\n OptionalAgentMethods,\n RequiredAgentMethods,\n StreamOptions,\n UntypedAgentStub\n} from \"./client\";\nimport type { ClientParameters } from \"./serializable\";\nimport { createStubProxy } from \"./client\";\nimport { camelCaseToKebabCase } from \"./utils\";\nimport { MessageType } from \"./types\";\nimport {\n applyAgentToolEvent,\n createAgentToolEventState,\n type AgentToolEventMessage,\n type AgentToolEventState,\n type AgentToolRunState\n} from \"./chat/agent-tools\";\n\ntype QueryObject = Record<string, string | null>;\n\ninterface CacheEntry {\n promise: Promise<QueryObject>;\n expiresAt: number;\n}\n\nconst queryCache = new Map<string, CacheEntry>();\n\nfunction createCacheKey(\n agentNamespace: string,\n name: string | undefined,\n subChainOrDeps: ReadonlyArray<{ agent: string; name: string }> | unknown[],\n deps?: unknown[]\n): string {\n // Backwards-compatible overload: if called with 3 args, the third\n // argument is `deps` and `subChain` defaults to empty. With 4 args,\n // the third is the sub-chain. This keeps existing callers (and\n // the `_testUtils` surface) working while letting new callers\n // include the nested chain in the cache key.\n //\n // Empty sub-chain must produce the same key as the old 3-arg\n // form, so nested-addressing code can opt-in without invalidating\n // existing caches.\n if (deps === undefined) {\n return JSON.stringify([\n agentNamespace,\n name || \"default\",\n ...(subChainOrDeps as unknown[])\n ]);\n }\n const subChain = subChainOrDeps as ReadonlyArray<{\n agent: string;\n name: string;\n }>;\n if (subChain.length === 0) {\n return JSON.stringify([agentNamespace, name || \"default\", ...deps]);\n }\n return JSON.stringify([\n agentNamespace,\n name || \"default\",\n subChain.map((s) => [s.agent, s.name]),\n ...deps\n ]);\n}\n\n/** Build a URL path tail `/sub/{agent-kebab}/{name}/...` from a sub chain. */\nfunction buildSubPath(\n subChain: ReadonlyArray<{ agent: string; name: string }>,\n extraPath?: string\n): string {\n if (subChain.length === 0) return extraPath ?? \"\";\n const parts = subChain.flatMap((step) => [\n \"sub\",\n camelCaseToKebabCase(step.agent),\n encodeURIComponent(step.name)\n ]);\n const combined = parts.join(\"/\");\n if (extraPath) {\n const trimmed = extraPath.startsWith(\"/\") ? extraPath.slice(1) : extraPath;\n return `${combined}/${trimmed}`;\n }\n return combined;\n}\n\nfunction getCacheEntry(key: string): CacheEntry | undefined {\n const entry = queryCache.get(key);\n if (!entry) return undefined;\n\n if (Date.now() >= entry.expiresAt) {\n queryCache.delete(key);\n return undefined;\n }\n\n return entry;\n}\n\nfunction setCacheEntry(\n key: string,\n promise: Promise<QueryObject>,\n cacheTtl: number\n): CacheEntry {\n const entry: CacheEntry = {\n promise,\n expiresAt: Date.now() + cacheTtl\n };\n queryCache.set(key, entry);\n return entry;\n}\n\nfunction deleteCacheEntry(key: string): void {\n queryCache.delete(key);\n}\n\n// Export for testing purposes\nexport const _testUtils = {\n queryCache,\n setCacheEntry,\n getCacheEntry,\n deleteCacheEntry,\n clearCache: () => queryCache.clear(),\n createStubProxy,\n createCacheKey\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 (ignored if basePath is set) */\n agent: string;\n /** Name of the specific Agent instance (ignored if basePath is set) */\n name?: string;\n /**\n * Full URL path - bypasses agent/name URL construction.\n * When set, the client connects to this path directly.\n * Server must handle routing manually (e.g., with getAgentByName + fetch).\n * @example\n * // Client connects to /user, server routes based on session\n * useAgent({ agent: \"UserAgent\", basePath: \"user\" })\n */\n basePath?: 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 a state update fails (e.g., connection is readonly) */\n onStateUpdateError?: (error: string) => void;\n /** Called when MCP server state is updated */\n onMcpUpdate?: (mcpServers: MCPServersState) => void;\n /**\n * Called when the server sends the agent's identity on connect.\n * Useful when using basePath, as the actual instance name is determined server-side.\n * @param name The actual agent instance name\n * @param agent The agent class name (kebab-case)\n */\n onIdentity?: (name: string, agent: string) => void;\n /**\n * Called when identity changes on reconnect (different instance than before).\n * If not provided and identity changes, a warning will be logged.\n * @param oldName Previous instance name\n * @param newName New instance name\n * @param oldAgent Previous agent class name\n * @param newAgent New agent class name\n */\n onIdentityChange?: (\n oldName: string,\n newName: string,\n oldAgent: string,\n newAgent: string\n ) => void;\n /**\n * Additional path to append to the URL.\n * Works with both standard routing and basePath.\n * @example\n * // With basePath: /user/settings\n * { basePath: \"user\", path: \"settings\" }\n * // Standard: /agents/my-agent/room/settings\n * { agent: \"MyAgent\", name: \"room\", path: \"settings\" }\n */\n path?: string;\n /**\n * Connect to a sub-agent (facet) via its parent. Flat array,\n * root-first. Each step addresses one parent↔child hop.\n *\n * The hook's returned `.agent` / `.name` report the **leaf**\n * identity (the deepest entry in `sub`), so downstream hooks\n * like `useAgentChat` see the child they actually talk to.\n * `.path` exposes the full chain for observability, deep links,\n * and reconnect keying.\n *\n * @example\n * ```ts\n * // Two-level nesting: Inbox (Alice) → Chat (abc)\n * useAgent({\n * agent: \"inbox\", name: userId,\n * sub: [{ agent: \"chat\", name: chatId }]\n * });\n *\n * // Three-level: tenant → inbox → chat\n * useAgent({\n * agent: \"tenant\", name: tenantId,\n * sub: [\n * { agent: \"inbox\", name: userId },\n * { agent: \"chat\", name: chatId }\n * ]\n * });\n * ```\n *\n * @experimental The API surface may change before stabilizing.\n */\n sub?: ReadonlyArray<{ agent: string; name: string }>;\n};\n\ntype OptionalArgsAgentMethodCall<AgentT> = <\n K extends keyof OptionalAgentMethods<AgentT>\n>(\n method: K,\n args?: ClientParameters<OptionalAgentMethods<AgentT>[K]>,\n options?: CallOptions | StreamOptions\n) => AgentPromiseReturnType<AgentT, K>;\n\ntype RequiredArgsAgentMethodCall<AgentT> = <\n K extends keyof RequiredAgentMethods<AgentT>\n>(\n method: K,\n args: ClientParameters<RequiredAgentMethods<AgentT>[K]>,\n options?: CallOptions | 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 options?: CallOptions | StreamOptions\n) => Promise<T>;\n\n/**\n * React hook for connecting to an Agent\n */\nexport function useAgent<State = unknown>(\n options: UseAgentOptions<State>\n): Omit<PartySocket, \"path\"> & {\n agent: string;\n name: string;\n /** Full root-first address chain, including leaf. Single entry when `sub` isn't set. */\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n};\nexport function useAgent<\n AgentT extends {\n get state(): State;\n },\n State\n>(\n options: UseAgentOptions<State>\n): Omit<PartySocket, \"path\"> & {\n agent: string;\n name: string;\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n setState: (state: State) => void;\n call: AgentMethodCall<AgentT>;\n stub: AgentStub<AgentT>;\n getHttpUrl: () => string;\n};\nexport function useAgent<State>(options: UseAgentOptions<unknown>): Omit<\n PartySocket,\n \"path\"\n> & {\n agent: string;\n name: string;\n path: ReadonlyArray<{ agent: string; name: string }>;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall | AgentMethodCall<unknown>;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n} {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n // NOTE: `path` is destructured out (as `userPath`) so it does NOT\n // end up in `restOptions`. Spreading `restOptions` after the\n // computed `path: combinedPath` would otherwise let the user's raw\n // `path` overwrite the combined sub-agent URL, dropping every\n // `/sub/{child}/{name}` segment on the way to the socket.\n const {\n query,\n queryDeps,\n cacheTtl,\n sub: subOption,\n path: userPath,\n ...restOptions\n } = options;\n\n const subChain = useMemo(\n () => (subOption ?? []).map((s) => ({ agent: s.agent, name: s.name })),\n // Stable serialization — deep changes re-memoize.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(subOption ?? [])]\n );\n\n // The \"leaf\" is the deepest entry in the chain; it's what\n // downstream code (useAgentChat etc.) should see as the\n // authoritative identity.\n const leafAgent =\n subChain.length > 0 ? subChain[subChain.length - 1].agent : options.agent;\n const leafName =\n subChain.length > 0\n ? subChain[subChain.length - 1].name\n : options.name || \"default\";\n\n // Full root-first chain, including the leaf. Exposed as `.path`\n // and used for cache keying so nested sessions with the same leaf\n // name don't collide.\n const fullPath = useMemo(\n () => [\n { agent: options.agent, name: options.name || \"default\" },\n ...subChain\n ],\n [options.agent, options.name, subChain]\n );\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 timeoutId?: ReturnType<typeof setTimeout>;\n }\n >()\n );\n\n const cacheKey = useMemo(\n () =>\n createCacheKey(agentNamespace, options.name, subChain, queryDeps || []),\n [agentNamespace, options.name, subChain, queryDeps]\n );\n\n // Track current cache key in a ref for use in onClose handler.\n // This ensures we invalidate the correct cache entry when the connection closes,\n // even if the component re-renders with different props before onClose fires.\n // We update synchronously during render (not in useEffect) to avoid race\n // conditions where onClose could fire before the effect runs.\n const cacheKeyRef = useRef(cacheKey);\n cacheKeyRef.current = cacheKey;\n\n const ttl = cacheTtl ?? 5 * 60 * 1000;\n\n // Track cache invalidation to force re-render when TTL expires\n const [cacheInvalidatedAt, setCacheInvalidatedAt] = useState<number>(0);\n\n // Disable socket while waiting for async query to refresh after disconnect\n const isAsyncQuery = query && typeof query === \"function\";\n const [awaitingQueryRefresh, setAwaitingQueryRefresh] = useState(false);\n\n // Get or create the query promise\n const queryPromise = useMemo(() => {\n // Re-run when cache is invalidated after TTL expiry\n void cacheInvalidatedAt;\n\n if (!query || typeof query !== \"function\") {\n return null;\n }\n\n // Always check cache first to deduplicate concurrent requests\n const cached = getCacheEntry(cacheKey);\n if (cached) {\n return cached.promise;\n }\n\n // Create new promise\n const promise = query().catch((error) => {\n console.error(\n `[useAgent] Query failed for agent \"${options.agent}\":`,\n error\n );\n deleteCacheEntry(cacheKey);\n throw error;\n });\n\n // Always cache to deduplicate concurrent requests\n setCacheEntry(cacheKey, promise, ttl);\n\n return promise;\n }, [cacheKey, query, options.agent, ttl, cacheInvalidatedAt]);\n\n // Schedule cache invalidation when TTL expires\n useEffect(() => {\n if (!queryPromise || ttl <= 0) return;\n\n const entry = getCacheEntry(cacheKey);\n if (!entry) return;\n\n const timeUntilExpiry = entry.expiresAt - Date.now();\n\n // Always set a timer (with min 0ms) to ensure cleanup function is returned\n const timer = setTimeout(\n () => {\n deleteCacheEntry(cacheKey);\n setCacheInvalidatedAt(Date.now());\n },\n Math.max(0, timeUntilExpiry)\n );\n\n return () => clearTimeout(timer);\n }, [cacheKey, queryPromise, ttl]);\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 // Re-enable socket after async query resolves\n useEffect(() => {\n if (awaitingQueryRefresh && resolvedQuery !== undefined) {\n setAwaitingQueryRefresh(false);\n }\n }, [awaitingQueryRefresh, resolvedQuery]);\n\n // Track agent state for reactivity — updated on server broadcasts and client setState\n const [agentState, setAgentState] = useState<State | undefined>(undefined);\n\n // Store identity in React state for reactivity. Seed with the\n // leaf's address — what the server will echo back in\n // `cf_agent_identity`.\n const [identity, setIdentity] = useState({\n name: leafName,\n agent: camelCaseToKebabCase(leafAgent),\n identified: false\n });\n\n // Track previous identity for change detection\n const previousIdentityRef = useRef<{\n name: string | null;\n agent: string | null;\n }>({ name: null, agent: null });\n\n // Ready promise - resolves when identity is received, resets on close\n const readyRef = useRef<\n { promise: Promise<void>; resolve: () => void } | undefined\n >(undefined);\n\n const resetReady = () => {\n let resolve: () => void;\n const promise = new Promise<void>((r) => {\n resolve = r;\n });\n readyRef.current = { promise, resolve: resolve! };\n };\n\n if (!readyRef.current) {\n resetReady();\n }\n\n const mutableAgentRef = useRef<{\n agent: string;\n name: string;\n identified: boolean;\n } | null>(null);\n\n // Combine the sub-agent chain with the user-provided `path`.\n // Order matters: `/sub/{child}/{name}/...` comes before `path` so\n // the server sees the hierarchy it expects.\n const combinedPath = useMemo(\n () => buildSubPath(subChain, userPath),\n [subChain, userPath]\n );\n\n // If basePath is provided, use it directly; otherwise construct from agent/name\n const socketOptions = options.basePath\n ? {\n basePath: options.basePath,\n path: combinedPath || undefined,\n query: resolvedQuery,\n ...restOptions\n }\n : {\n party: agentNamespace,\n prefix: \"agents\",\n room: options.name || \"default\",\n path: combinedPath || undefined,\n query: resolvedQuery,\n ...restOptions\n };\n\n const socketEnabled = !awaitingQueryRefresh && (restOptions.enabled ?? true);\n\n const agent = usePartySocket({\n ...socketOptions,\n enabled: socketEnabled,\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_IDENTITY) {\n const oldName = previousIdentityRef.current.name;\n const oldAgent = previousIdentityRef.current.agent;\n const newName = parsedMessage.name as string;\n const newAgent = parsedMessage.agent as string;\n\n const currentAgent = mutableAgentRef.current;\n if (currentAgent) {\n currentAgent.name = newName;\n currentAgent.agent = newAgent;\n currentAgent.identified = true;\n }\n\n // Update reactive state (triggers re-render)\n setIdentity({ name: newName, agent: newAgent, identified: true });\n\n // Resolve ready promise\n readyRef.current?.resolve();\n\n // Detect identity change on reconnect\n if (\n oldName !== null &&\n oldAgent !== null &&\n (oldName !== newName || oldAgent !== newAgent)\n ) {\n if (options.onIdentityChange) {\n options.onIdentityChange(oldName, newName, oldAgent, newAgent);\n } else {\n const agentChanged = oldAgent !== newAgent;\n const nameChanged = oldName !== newName;\n let changeDescription = \"\";\n if (agentChanged && nameChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\", instance \"${oldName}\" → \"${newName}\"`;\n } else if (agentChanged) {\n changeDescription = `agent \"${oldAgent}\" → \"${newAgent}\"`;\n } else {\n changeDescription = `instance \"${oldName}\" → \"${newName}\"`;\n }\n console.warn(\n `[agents] Identity changed on reconnect: ${changeDescription}. ` +\n \"This can happen with server-side routing (e.g., basePath with getAgentByName) \" +\n \"where the instance is determined by auth/session. \" +\n \"Provide onIdentityChange callback to handle this explicitly, \" +\n \"or ignore if this is expected for your routing pattern.\"\n );\n }\n }\n\n // Track for next change detection\n previousIdentityRef.current = { name: newName, agent: newAgent };\n\n // Call onIdentity callback\n options.onIdentity?.(newName, newAgent);\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE) {\n setAgentState(parsedMessage.state as State);\n options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === MessageType.CF_AGENT_STATE_ERROR) {\n options.onStateUpdateError?.(parsedMessage.error as string);\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 if (pending.timeoutId) clearTimeout(pending.timeoutId);\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 if (pending.timeoutId) clearTimeout(pending.timeoutId);\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 if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.resolve(response.result);\n pendingCallsRef.current.delete(response.id);\n }\n return;\n }\n }\n options.onMessage?.(message);\n },\n onClose: (event: CloseEvent) => {\n // Reset ready state for next connection\n resetReady();\n if (mutableAgentRef.current) {\n mutableAgentRef.current.identified = false;\n }\n setIdentity((prev) => ({ ...prev, identified: false }));\n\n // Pause reconnection for async queries until fresh query params are ready\n if (isAsyncQuery) {\n setAwaitingQueryRefresh(true);\n }\n\n // Invalidate cache and trigger re-render to fetch fresh query params\n deleteCacheEntry(cacheKeyRef.current);\n setCacheInvalidatedAt(Date.now());\n\n // Reject all pending calls (consistent with AgentClient behavior)\n const error = new Error(\"Connection closed\");\n for (const pending of pendingCallsRef.current.values()) {\n if (pending.timeoutId) clearTimeout(pending.timeoutId);\n pending.reject(error);\n pending.stream?.onError?.(\"Connection closed\");\n }\n pendingCallsRef.current.clear();\n\n // Call user's onClose if provided\n options.onClose?.(event);\n }\n }) as PartySocket & {\n agent: string;\n name: string;\n identified: boolean;\n ready: Promise<void>;\n state: State | undefined;\n setState: (state: State) => void;\n call: UntypedAgentMethodCall;\n stub: UntypedAgentStub;\n getHttpUrl: () => string;\n };\n // Create the call method\n const call = useCallback(\n <T = unknown,>(\n method: string,\n args: unknown[] = [],\n options?: CallOptions | StreamOptions\n ): Promise<T> => {\n return new Promise((resolve, reject) => {\n const id = crypto.randomUUID();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Detect legacy format: { onChunk?, onDone?, onError? } vs new format: { timeout?, stream? }\n const isLegacyFormat =\n options &&\n (\"onChunk\" in options || \"onDone\" in options || \"onError\" in options);\n const streamOptions = isLegacyFormat\n ? (options as StreamOptions)\n : (options as CallOptions | undefined)?.stream;\n const timeout = isLegacyFormat\n ? undefined\n : (options as CallOptions | undefined)?.timeout;\n\n if (timeout) {\n timeoutId = setTimeout(() => {\n const pending = pendingCallsRef.current.get(id);\n pendingCallsRef.current.delete(id);\n const errorMessage = `RPC call to ${method} timed out after ${timeout}ms`;\n pending?.stream?.onError?.(errorMessage);\n reject(new Error(errorMessage));\n }, timeout);\n }\n\n pendingCallsRef.current.set(id, {\n reject,\n resolve: resolve as (value: unknown) => void,\n stream: streamOptions,\n timeoutId\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 = (newState: State) => {\n agent.send(\n JSON.stringify({ state: newState, type: MessageType.CF_AGENT_STATE })\n );\n setAgentState(newState);\n options.onStateUpdate?.(newState, \"client\");\n };\n\n agent.call = call;\n // Use reactive identity state (updates on identity message)\n agent.agent = identity.agent;\n agent.name = identity.name;\n // Full root-first chain including the leaf. Computed from the\n // user-provided options — the server doesn't need to echo it\n // back because the client already knows. Write past the\n // PartySocket `.path: string` shape via an unknown cast — the\n // overload signatures expose this as `ReadonlyArray<...>`.\n (\n agent as unknown as { path: ReadonlyArray<{ agent: string; name: string }> }\n ).path = fullPath;\n agent.identified = identity.identified;\n agent.ready = readyRef.current!.promise;\n agent.state = agentState;\n mutableAgentRef.current = agent;\n // Memoize stub so it's referentially stable across renders\n // (call is already stable via useCallback)\n const stub = useMemo(() => createStubProxy(call), [call]);\n agent.stub = stub;\n agent.getHttpUrl = () => {\n // TODO: upstream to partysocket — expose an HTTP URL property\n // @ts-expect-error accessing protected PartySocket internals\n const wsUrl: string = (agent._url as string | null) || agent._pkurl || \"\";\n return wsUrl.replace(\"ws://\", \"http://\").replace(\"wss://\", \"https://\");\n };\n\n // warn if agent isn't in lowercase\n if (identity.agent !== identity.agent.toLowerCase()) {\n console.warn(\n \"Agent name: \" +\n identity.agent +\n \" should probably be in lowercase. Received: \" +\n identity.agent\n );\n }\n\n // The overload signatures return `Omit<PartySocket, \"path\"> & { path: ... }`,\n // but `agent` is inferred as the raw PartySocket. Cast to satisfy\n // the overload contract — the runtime override of `agent.path`\n // above ensures the shape matches.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return agent as any;\n}\n\ntype AgentToolEventAgent = Pick<\n PartySocket,\n \"addEventListener\" | \"removeEventListener\"\n>;\n\nfunction agentToolDedupeKey(message: AgentToolEventMessage): string {\n return [\n message.parentToolCallId ?? \"\",\n message.event.runId,\n String(message.sequence)\n ].join(\"\\0\");\n}\n\nexport function useAgentToolEvents(options: { agent: AgentToolEventAgent }): {\n runsById: Record<string, AgentToolRunState>;\n runsByToolCallId: Record<string, AgentToolRunState[]>;\n unboundRuns: AgentToolRunState[];\n getRunsForToolCall(toolCallId: string): AgentToolRunState[];\n resetLocalState(): void;\n} {\n const { agent } = options;\n const [state, setState] = useState<AgentToolEventState>(() =>\n createAgentToolEventState()\n );\n const seenRef = useRef(new Set<string>());\n\n useEffect(() => {\n const onMessage = (event: MessageEvent) => {\n if (typeof event.data !== \"string\") return;\n let message: AgentToolEventMessage;\n try {\n message = JSON.parse(event.data) as AgentToolEventMessage;\n } catch {\n return;\n }\n if (message.type !== \"agent-tool-event\") return;\n const key = agentToolDedupeKey(message);\n if (seenRef.current.has(key)) return;\n seenRef.current.add(key);\n setState((prev) => applyAgentToolEvent(prev, message));\n };\n\n agent.addEventListener(\"message\", onMessage);\n return () => agent.removeEventListener(\"message\", onMessage);\n }, [agent]);\n\n const resetLocalState = useCallback(() => {\n seenRef.current.clear();\n setState(createAgentToolEventState());\n }, []);\n\n const getRunsForToolCall = useCallback(\n (toolCallId: string) => state.runsByToolCallId[toolCallId] ?? [],\n [state.runsByToolCallId]\n );\n\n return {\n ...state,\n getRunsForToolCall,\n resetLocalState\n };\n}\n"],"mappings":"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"}
@@ -76,4 +76,4 @@ export {
76
76
  jitterBackoff as r,
77
77
  RetryOptions as t
78
78
  };
79
- //# sourceMappingURL=retries-fLD8cGNf.d.ts.map
79
+ //# sourceMappingURL=retries-BVdRl5ZE.d.ts.map
package/dist/retries.d.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  n as isErrorRetryable,
5
5
  r as jitterBackoff,
6
6
  t as RetryOptions
7
- } from "./retries-fLD8cGNf.js";
7
+ } from "./retries-BVdRl5ZE.js";
8
8
  export {
9
9
  RetryOptions,
10
10
  isErrorRetryable,
@@ -1 +1 @@
1
- {"version":3,"file":"retries.js","names":[],"sources":["../src/retries.ts"],"sourcesContent":["/**\n * Retry options for schedule(), scheduleEvery(), queue(), and this.retry().\n */\nexport interface RetryOptions {\n /** Max number of attempts (including the first). Default: 3 */\n maxAttempts?: number;\n /** Base delay in ms for exponential backoff. Default: 100 */\n baseDelayMs?: number;\n /** Max delay cap in ms. Default: 3000 */\n maxDelayMs?: number;\n}\n\n/**\n * Internal options for tryN -- extends RetryOptions with a shouldRetry predicate.\n */\ninterface TryNOptions extends RetryOptions {\n /**\n * Predicate to determine if an error should be retried.\n * Receives the error and the next attempt number (so callers can\n * make attempt-aware decisions).\n * If not provided, all errors are retried.\n */\n shouldRetry?: (err: unknown, nextAttempt: number) => boolean;\n}\n\n/**\n * Validate retry options eagerly so invalid config fails at enqueue/schedule time\n * rather than at execution time. Checks individual field ranges, enforces integer\n * maxAttempts, and validates cross-field constraints after resolving against\n * defaults when provided.\n */\nexport function validateRetryOptions(\n options: RetryOptions,\n defaults?: Required<RetryOptions>\n): void {\n if (options.maxAttempts !== undefined) {\n if (!Number.isFinite(options.maxAttempts) || options.maxAttempts < 1) {\n throw new Error(\"retry.maxAttempts must be >= 1\");\n }\n if (!Number.isInteger(options.maxAttempts)) {\n throw new Error(\"retry.maxAttempts must be an integer\");\n }\n }\n if (options.baseDelayMs !== undefined) {\n if (!Number.isFinite(options.baseDelayMs) || options.baseDelayMs <= 0) {\n throw new Error(\"retry.baseDelayMs must be > 0\");\n }\n }\n if (options.maxDelayMs !== undefined) {\n if (!Number.isFinite(options.maxDelayMs) || options.maxDelayMs <= 0) {\n throw new Error(\"retry.maxDelayMs must be > 0\");\n }\n }\n\n // Resolve against defaults (when provided) so that cross-field checks\n // catch e.g. { baseDelayMs: 5000 } against default maxDelayMs: 3000.\n const resolvedBase = options.baseDelayMs ?? defaults?.baseDelayMs;\n const resolvedMax = options.maxDelayMs ?? defaults?.maxDelayMs;\n if (\n resolvedBase !== undefined &&\n resolvedMax !== undefined &&\n resolvedBase > resolvedMax\n ) {\n throw new Error(\"retry.baseDelayMs must be <= retry.maxDelayMs\");\n }\n}\n\n/**\n * Returns the number of milliseconds to wait before retrying a request.\n * Uses the \"Full Jitter\" approach from\n * https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/\n *\n * @param attempt The current attempt number (1-indexed).\n * @param baseDelayMs Base delay multiplier in ms.\n * @param maxDelayMs Maximum delay cap in ms.\n * @returns Milliseconds to wait before retrying.\n */\nexport function jitterBackoff(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number\n): number {\n const upperBoundMs = Math.min(2 ** attempt * baseDelayMs, maxDelayMs);\n return Math.floor(Math.random() * upperBoundMs);\n}\n\n/**\n * Retry an async function up to `n` total attempts with jittered exponential backoff.\n *\n * @param n Total number of attempts (must be a finite integer >= 1).\n * @param fn The async function to retry. Receives the current attempt number (1-indexed).\n * @param options Retry configuration.\n * @returns The result of `fn` on success.\n * @throws The last error if all attempts fail or `shouldRetry` returns false.\n */\nexport async function tryN<T>(\n n: number,\n fn: (attempt: number) => Promise<T>,\n options?: TryNOptions\n): Promise<T> {\n if (!Number.isFinite(n) || n < 1) {\n throw new Error(\"retry.maxAttempts must be >= 1\");\n }\n n = Math.floor(n);\n\n const rawBase = options?.baseDelayMs ?? 100;\n const rawMax = options?.maxDelayMs ?? 3000;\n\n if (!Number.isFinite(rawBase) || rawBase <= 0) {\n throw new Error(\"retry.baseDelayMs must be > 0\");\n }\n if (!Number.isFinite(rawMax) || rawMax <= 0) {\n throw new Error(\"retry.maxDelayMs must be > 0\");\n }\n\n const baseDelayMs = Math.floor(rawBase);\n const maxDelayMs = Math.floor(rawMax);\n\n if (baseDelayMs > maxDelayMs) {\n throw new Error(\"retry.baseDelayMs must be <= retry.maxDelayMs\");\n }\n\n let attempt = 1;\n while (true) {\n try {\n return await fn(attempt);\n } catch (err) {\n const nextAttempt = attempt + 1;\n if (\n nextAttempt > n ||\n (options?.shouldRetry && !options.shouldRetry(err, nextAttempt))\n ) {\n throw err;\n }\n const delay = jitterBackoff(attempt, baseDelayMs, maxDelayMs);\n await new Promise((resolve) => setTimeout(resolve, delay));\n attempt = nextAttempt;\n }\n }\n}\n\n/**\n * Returns true if the given error is retryable according to Durable Object error handling.\n * See https://developers.cloudflare.com/durable-objects/best-practices/error-handling/\n *\n * An error is retryable if it has `retryable: true` but is NOT an overloaded error.\n */\nexport function isErrorRetryable(err: unknown): boolean {\n if (typeof err !== \"object\" || err === null) {\n return false;\n }\n const msg = String(err);\n const typed = err as { retryable?: boolean; overloaded?: boolean };\n return (\n Boolean(typed.retryable) &&\n !typed.overloaded &&\n !msg.includes(\"Durable Object is overloaded\")\n );\n}\n"],"mappings":";;;;;;;AA+BA,SAAgB,qBACd,SACA,UACM;AACN,KAAI,QAAQ,gBAAgB,KAAA,GAAW;AACrC,MAAI,CAAC,OAAO,SAAS,QAAQ,YAAY,IAAI,QAAQ,cAAc,EACjE,OAAM,IAAI,MAAM,iCAAiC;AAEnD,MAAI,CAAC,OAAO,UAAU,QAAQ,YAAY,CACxC,OAAM,IAAI,MAAM,uCAAuC;;AAG3D,KAAI,QAAQ,gBAAgB,KAAA;MACtB,CAAC,OAAO,SAAS,QAAQ,YAAY,IAAI,QAAQ,eAAe,EAClE,OAAM,IAAI,MAAM,gCAAgC;;AAGpD,KAAI,QAAQ,eAAe,KAAA;MACrB,CAAC,OAAO,SAAS,QAAQ,WAAW,IAAI,QAAQ,cAAc,EAChE,OAAM,IAAI,MAAM,+BAA+B;;CAMnD,MAAM,eAAe,QAAQ,eAAe,UAAU;CACtD,MAAM,cAAc,QAAQ,cAAc,UAAU;AACpD,KACE,iBAAiB,KAAA,KACjB,gBAAgB,KAAA,KAChB,eAAe,YAEf,OAAM,IAAI,MAAM,gDAAgD;;;;;;;;;;;;AAcpE,SAAgB,cACd,SACA,aACA,YACQ;CACR,MAAM,eAAe,KAAK,IAAI,KAAK,UAAU,aAAa,WAAW;AACrE,QAAO,KAAK,MAAM,KAAK,QAAQ,GAAG,aAAa;;;;;;;;;;;AAYjD,eAAsB,KACpB,GACA,IACA,SACY;AACZ,KAAI,CAAC,OAAO,SAAS,EAAE,IAAI,IAAI,EAC7B,OAAM,IAAI,MAAM,iCAAiC;AAEnD,KAAI,KAAK,MAAM,EAAE;CAEjB,MAAM,UAAU,SAAS,eAAe;CACxC,MAAM,SAAS,SAAS,cAAc;AAEtC,KAAI,CAAC,OAAO,SAAS,QAAQ,IAAI,WAAW,EAC1C,OAAM,IAAI,MAAM,gCAAgC;AAElD,KAAI,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,EACxC,OAAM,IAAI,MAAM,+BAA+B;CAGjD,MAAM,cAAc,KAAK,MAAM,QAAQ;CACvC,MAAM,aAAa,KAAK,MAAM,OAAO;AAErC,KAAI,cAAc,WAChB,OAAM,IAAI,MAAM,gDAAgD;CAGlE,IAAI,UAAU;AACd,QAAO,KACL,KAAI;AACF,SAAO,MAAM,GAAG,QAAQ;UACjB,KAAK;EACZ,MAAM,cAAc,UAAU;AAC9B,MACE,cAAc,KACb,SAAS,eAAe,CAAC,QAAQ,YAAY,KAAK,YAAY,CAE/D,OAAM;EAER,MAAM,QAAQ,cAAc,SAAS,aAAa,WAAW;AAC7D,QAAM,IAAI,SAAS,YAAY,WAAW,SAAS,MAAM,CAAC;AAC1D,YAAU;;;;;;;;;AAWhB,SAAgB,iBAAiB,KAAuB;AACtD,KAAI,OAAO,QAAQ,YAAY,QAAQ,KACrC,QAAO;CAET,MAAM,MAAM,OAAO,IAAI;CACvB,MAAM,QAAQ;AACd,QACE,QAAQ,MAAM,UAAU,IACxB,CAAC,MAAM,cACP,CAAC,IAAI,SAAS,+BAA+B"}
1
+ {"version":3,"file":"retries.js","names":[],"sources":["../src/retries.ts"],"sourcesContent":["/**\n * Retry options for schedule(), scheduleEvery(), queue(), and this.retry().\n */\nexport interface RetryOptions {\n /** Max number of attempts (including the first). Default: 3 */\n maxAttempts?: number;\n /** Base delay in ms for exponential backoff. Default: 100 */\n baseDelayMs?: number;\n /** Max delay cap in ms. Default: 3000 */\n maxDelayMs?: number;\n}\n\n/**\n * Internal options for tryN -- extends RetryOptions with a shouldRetry predicate.\n */\ninterface TryNOptions extends RetryOptions {\n /**\n * Predicate to determine if an error should be retried.\n * Receives the error and the next attempt number (so callers can\n * make attempt-aware decisions).\n * If not provided, all errors are retried.\n */\n shouldRetry?: (err: unknown, nextAttempt: number) => boolean;\n}\n\n/**\n * Validate retry options eagerly so invalid config fails at enqueue/schedule time\n * rather than at execution time. Checks individual field ranges, enforces integer\n * maxAttempts, and validates cross-field constraints after resolving against\n * defaults when provided.\n */\nexport function validateRetryOptions(\n options: RetryOptions,\n defaults?: Required<RetryOptions>\n): void {\n if (options.maxAttempts !== undefined) {\n if (!Number.isFinite(options.maxAttempts) || options.maxAttempts < 1) {\n throw new Error(\"retry.maxAttempts must be >= 1\");\n }\n if (!Number.isInteger(options.maxAttempts)) {\n throw new Error(\"retry.maxAttempts must be an integer\");\n }\n }\n if (options.baseDelayMs !== undefined) {\n if (!Number.isFinite(options.baseDelayMs) || options.baseDelayMs <= 0) {\n throw new Error(\"retry.baseDelayMs must be > 0\");\n }\n }\n if (options.maxDelayMs !== undefined) {\n if (!Number.isFinite(options.maxDelayMs) || options.maxDelayMs <= 0) {\n throw new Error(\"retry.maxDelayMs must be > 0\");\n }\n }\n\n // Resolve against defaults (when provided) so that cross-field checks\n // catch e.g. { baseDelayMs: 5000 } against default maxDelayMs: 3000.\n const resolvedBase = options.baseDelayMs ?? defaults?.baseDelayMs;\n const resolvedMax = options.maxDelayMs ?? defaults?.maxDelayMs;\n if (\n resolvedBase !== undefined &&\n resolvedMax !== undefined &&\n resolvedBase > resolvedMax\n ) {\n throw new Error(\"retry.baseDelayMs must be <= retry.maxDelayMs\");\n }\n}\n\n/**\n * Returns the number of milliseconds to wait before retrying a request.\n * Uses the \"Full Jitter\" approach from\n * https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/\n *\n * @param attempt The current attempt number (1-indexed).\n * @param baseDelayMs Base delay multiplier in ms.\n * @param maxDelayMs Maximum delay cap in ms.\n * @returns Milliseconds to wait before retrying.\n */\nexport function jitterBackoff(\n attempt: number,\n baseDelayMs: number,\n maxDelayMs: number\n): number {\n const upperBoundMs = Math.min(2 ** attempt * baseDelayMs, maxDelayMs);\n return Math.floor(Math.random() * upperBoundMs);\n}\n\n/**\n * Retry an async function up to `n` total attempts with jittered exponential backoff.\n *\n * @param n Total number of attempts (must be a finite integer >= 1).\n * @param fn The async function to retry. Receives the current attempt number (1-indexed).\n * @param options Retry configuration.\n * @returns The result of `fn` on success.\n * @throws The last error if all attempts fail or `shouldRetry` returns false.\n */\nexport async function tryN<T>(\n n: number,\n fn: (attempt: number) => Promise<T>,\n options?: TryNOptions\n): Promise<T> {\n if (!Number.isFinite(n) || n < 1) {\n throw new Error(\"retry.maxAttempts must be >= 1\");\n }\n n = Math.floor(n);\n\n const rawBase = options?.baseDelayMs ?? 100;\n const rawMax = options?.maxDelayMs ?? 3000;\n\n if (!Number.isFinite(rawBase) || rawBase <= 0) {\n throw new Error(\"retry.baseDelayMs must be > 0\");\n }\n if (!Number.isFinite(rawMax) || rawMax <= 0) {\n throw new Error(\"retry.maxDelayMs must be > 0\");\n }\n\n const baseDelayMs = Math.floor(rawBase);\n const maxDelayMs = Math.floor(rawMax);\n\n if (baseDelayMs > maxDelayMs) {\n throw new Error(\"retry.baseDelayMs must be <= retry.maxDelayMs\");\n }\n\n let attempt = 1;\n while (true) {\n try {\n return await fn(attempt);\n } catch (err) {\n const nextAttempt = attempt + 1;\n if (\n nextAttempt > n ||\n (options?.shouldRetry && !options.shouldRetry(err, nextAttempt))\n ) {\n throw err;\n }\n const delay = jitterBackoff(attempt, baseDelayMs, maxDelayMs);\n await new Promise((resolve) => setTimeout(resolve, delay));\n attempt = nextAttempt;\n }\n }\n}\n\n/**\n * Returns true if the given error is retryable according to Durable Object error handling.\n * See https://developers.cloudflare.com/durable-objects/best-practices/error-handling/\n *\n * An error is retryable if it has `retryable: true` but is NOT an overloaded error.\n */\nexport function isErrorRetryable(err: unknown): boolean {\n if (typeof err !== \"object\" || err === null) {\n return false;\n }\n const msg = String(err);\n const typed = err as { retryable?: boolean; overloaded?: boolean };\n return (\n Boolean(typed.retryable) &&\n !typed.overloaded &&\n !msg.includes(\"Durable Object is overloaded\")\n );\n}\n"],"mappings":";;;;;;;AA+BA,SAAgB,qBACd,SACA,UACM;CACN,IAAI,QAAQ,gBAAgB,KAAA,GAAW;EACrC,IAAI,CAAC,OAAO,SAAS,QAAQ,YAAY,IAAI,QAAQ,cAAc,GACjE,MAAM,IAAI,MAAM,iCAAiC;EAEnD,IAAI,CAAC,OAAO,UAAU,QAAQ,YAAY,EACxC,MAAM,IAAI,MAAM,uCAAuC;;CAG3D,IAAI,QAAQ,gBAAgB,KAAA;MACtB,CAAC,OAAO,SAAS,QAAQ,YAAY,IAAI,QAAQ,eAAe,GAClE,MAAM,IAAI,MAAM,gCAAgC;;CAGpD,IAAI,QAAQ,eAAe,KAAA;MACrB,CAAC,OAAO,SAAS,QAAQ,WAAW,IAAI,QAAQ,cAAc,GAChE,MAAM,IAAI,MAAM,+BAA+B;;CAMnD,MAAM,eAAe,QAAQ,eAAe,UAAU;CACtD,MAAM,cAAc,QAAQ,cAAc,UAAU;CACpD,IACE,iBAAiB,KAAA,KACjB,gBAAgB,KAAA,KAChB,eAAe,aAEf,MAAM,IAAI,MAAM,gDAAgD;;;;;;;;;;;;AAcpE,SAAgB,cACd,SACA,aACA,YACQ;CACR,MAAM,eAAe,KAAK,IAAI,KAAK,UAAU,aAAa,WAAW;CACrE,OAAO,KAAK,MAAM,KAAK,QAAQ,GAAG,aAAa;;;;;;;;;;;AAYjD,eAAsB,KACpB,GACA,IACA,SACY;CACZ,IAAI,CAAC,OAAO,SAAS,EAAE,IAAI,IAAI,GAC7B,MAAM,IAAI,MAAM,iCAAiC;CAEnD,IAAI,KAAK,MAAM,EAAE;CAEjB,MAAM,UAAU,SAAS,eAAe;CACxC,MAAM,SAAS,SAAS,cAAc;CAEtC,IAAI,CAAC,OAAO,SAAS,QAAQ,IAAI,WAAW,GAC1C,MAAM,IAAI,MAAM,gCAAgC;CAElD,IAAI,CAAC,OAAO,SAAS,OAAO,IAAI,UAAU,GACxC,MAAM,IAAI,MAAM,+BAA+B;CAGjD,MAAM,cAAc,KAAK,MAAM,QAAQ;CACvC,MAAM,aAAa,KAAK,MAAM,OAAO;CAErC,IAAI,cAAc,YAChB,MAAM,IAAI,MAAM,gDAAgD;CAGlE,IAAI,UAAU;CACd,OAAO,MACL,IAAI;EACF,OAAO,MAAM,GAAG,QAAQ;UACjB,KAAK;EACZ,MAAM,cAAc,UAAU;EAC9B,IACE,cAAc,KACb,SAAS,eAAe,CAAC,QAAQ,YAAY,KAAK,YAAY,EAE/D,MAAM;EAER,MAAM,QAAQ,cAAc,SAAS,aAAa,WAAW;EAC7D,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,MAAM,CAAC;EAC1D,UAAU;;;;;;;;;AAWhB,SAAgB,iBAAiB,KAAuB;CACtD,IAAI,OAAO,QAAQ,YAAY,QAAQ,MACrC,OAAO;CAET,MAAM,MAAM,OAAO,IAAI;CACvB,MAAM,QAAQ;CACd,OACE,QAAQ,MAAM,UAAU,IACxB,CAAC,MAAM,cACP,CAAC,IAAI,SAAS,+BAA+B"}
@@ -1 +1 @@
1
- {"version":3,"file":"schedule.js","names":[],"sources":["../src/schedule.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Get the schedule prompt for a given event\n * @param event - The event to get the schedule prompt for\n * @returns The schedule prompt\n */\nexport function getSchedulePrompt(event: { date: Date }) {\n return `\n[Schedule Parser Component]\n\nCurrent time: ${event.date.toUTCString()}\n\nThis component parses natural language scheduling requests into a structured format. It extracts:\n1. A clean task description (without timing information)\n2. Scheduling details in one of these formats:\n - scheduled: Specific date/time events\n - delayed: Relative time delays (in seconds)\n - cron: Recurring patterns\n - no-schedule: Tasks without timing\n\nRules:\n- Task descriptions should be clean and focused on the action\n- Use numbers (0-6) for days in cron patterns (0=Sunday)\n- For recurring tasks, use standard cron syntax\n- For relative times, convert to seconds\n- For specific dates, use the current time as reference\n\nExample outputs:\n{\n \"description\": \"meeting with team\",\n \"when\": {\n \"type\": \"scheduled\",\n \"date\": \"tomorrow at 14:00\"\n }\n}\n\n{\n \"description\": \"backup database\",\n \"when\": {\n \"type\": \"cron\",\n \"cron\": \"0 0 * * *\"\n }\n}\n\n{\n \"description\": \"send report\",\n \"when\": {\n \"type\": \"delayed\",\n \"delayInSeconds\": 1800\n }\n}\n\n[End Schedule Parser Component]\n`;\n}\n\nlet didWarnAboutUnstableGetSchedulePrompt = false;\n\n/**\n * @deprecated this has been renamed to getSchedulePrompt, and unstable_getSchedulePrompt will be removed in the next major version\n * @param event - The event to get the schedule prompt for\n * @returns The schedule prompt\n */\nexport function unstable_getSchedulePrompt(event: { date: Date }) {\n if (!didWarnAboutUnstableGetSchedulePrompt) {\n didWarnAboutUnstableGetSchedulePrompt = true;\n console.warn(\n \"unstable_getSchedulePrompt is deprecated, use getSchedulePrompt instead. unstable_getSchedulePrompt will be removed in the next major version.\"\n );\n }\n return getSchedulePrompt(event);\n}\n\n/**\n * The schema for parsing natural language scheduling requests.\n *\n * @example\n * ```typescript\n * import { generateObject } from \"ai\";\n * import { scheduleSchema, getSchedulePrompt } from \"agents/schedule\";\n *\n * const result = await generateObject({\n * model,\n * prompt: `${getSchedulePrompt({ date: new Date() })} Input: \"${userInput}\"`,\n * schema: scheduleSchema,\n * // Required for OpenAI to avoid strict JSON schema validation errors\n * providerOptions: {\n * openai: { strictJsonSchema: false }\n * }\n * });\n * ```\n *\n * @remarks\n * When using this schema with OpenAI models via the AI SDK, you must pass\n * `providerOptions: { openai: { strictJsonSchema: false } }` to `generateObject`.\n * This is because the schema uses a discriminated union which is not compatible\n * with OpenAI's strict structured outputs mode.\n */\nexport const scheduleSchema = z.object({\n description: z.string().describe(\"A description of the task\"),\n when: z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"scheduled\"),\n date: z\n .string()\n .describe(\n \"Execute task at the specified date and time in ISO 8601 format\"\n )\n }),\n z.object({\n type: z.literal(\"delayed\"),\n delayInSeconds: z\n .number()\n .describe(\"Execute task after a delay in seconds\")\n }),\n z.object({\n type: z.literal(\"cron\"),\n cron: z\n .string()\n .describe(\n \"Execute task on a recurring interval specified as cron syntax\"\n )\n }),\n z.object({\n type: z.literal(\"no-schedule\")\n })\n ])\n});\n\n/**\n * The type for the schedule prompt\n */\nexport type Schedule = z.infer<typeof scheduleSchema>;\n\n/**\n * @deprecated this has been renamed to scheduleSchema, and unstable_scheduleSchema will be removed in the next major version\n * @returns The schedule schema\n */\nexport const unstable_scheduleSchema = scheduleSchema;\n"],"mappings":";;;;;;;AAOA,SAAgB,kBAAkB,OAAuB;AACvD,QAAO;;;gBAGO,MAAM,KAAK,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CzC,IAAI,wCAAwC;;;;;;AAO5C,SAAgB,2BAA2B,OAAuB;AAChE,KAAI,CAAC,uCAAuC;AAC1C,0CAAwC;AACxC,UAAQ,KACN,iJACD;;AAEH,QAAO,kBAAkB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BjC,MAAa,iBAAiB,EAAE,OAAO;CACrC,aAAa,EAAE,QAAQ,CAAC,SAAS,4BAA4B;CAC7D,MAAM,EAAE,mBAAmB,QAAQ;EACjC,EAAE,OAAO;GACP,MAAM,EAAE,QAAQ,YAAY;GAC5B,MAAM,EACH,QAAQ,CACR,SACC,iEACD;GACJ,CAAC;EACF,EAAE,OAAO;GACP,MAAM,EAAE,QAAQ,UAAU;GAC1B,gBAAgB,EACb,QAAQ,CACR,SAAS,wCAAwC;GACrD,CAAC;EACF,EAAE,OAAO;GACP,MAAM,EAAE,QAAQ,OAAO;GACvB,MAAM,EACH,QAAQ,CACR,SACC,gEACD;GACJ,CAAC;EACF,EAAE,OAAO,EACP,MAAM,EAAE,QAAQ,cAAc,EAC/B,CAAC;EACH,CAAC;CACH,CAAC;;;;;AAWF,MAAa,0BAA0B"}
1
+ {"version":3,"file":"schedule.js","names":[],"sources":["../src/schedule.ts"],"sourcesContent":["import { z } from \"zod\";\n\n/**\n * Get the schedule prompt for a given event\n * @param event - The event to get the schedule prompt for\n * @returns The schedule prompt\n */\nexport function getSchedulePrompt(event: { date: Date }) {\n return `\n[Schedule Parser Component]\n\nCurrent time: ${event.date.toUTCString()}\n\nThis component parses natural language scheduling requests into a structured format. It extracts:\n1. A clean task description (without timing information)\n2. Scheduling details in one of these formats:\n - scheduled: Specific date/time events\n - delayed: Relative time delays (in seconds)\n - cron: Recurring patterns\n - no-schedule: Tasks without timing\n\nRules:\n- Task descriptions should be clean and focused on the action\n- Use numbers (0-6) for days in cron patterns (0=Sunday)\n- For recurring tasks, use standard cron syntax\n- For relative times, convert to seconds\n- For specific dates, use the current time as reference\n\nExample outputs:\n{\n \"description\": \"meeting with team\",\n \"when\": {\n \"type\": \"scheduled\",\n \"date\": \"tomorrow at 14:00\"\n }\n}\n\n{\n \"description\": \"backup database\",\n \"when\": {\n \"type\": \"cron\",\n \"cron\": \"0 0 * * *\"\n }\n}\n\n{\n \"description\": \"send report\",\n \"when\": {\n \"type\": \"delayed\",\n \"delayInSeconds\": 1800\n }\n}\n\n[End Schedule Parser Component]\n`;\n}\n\nlet didWarnAboutUnstableGetSchedulePrompt = false;\n\n/**\n * @deprecated this has been renamed to getSchedulePrompt, and unstable_getSchedulePrompt will be removed in the next major version\n * @param event - The event to get the schedule prompt for\n * @returns The schedule prompt\n */\nexport function unstable_getSchedulePrompt(event: { date: Date }) {\n if (!didWarnAboutUnstableGetSchedulePrompt) {\n didWarnAboutUnstableGetSchedulePrompt = true;\n console.warn(\n \"unstable_getSchedulePrompt is deprecated, use getSchedulePrompt instead. unstable_getSchedulePrompt will be removed in the next major version.\"\n );\n }\n return getSchedulePrompt(event);\n}\n\n/**\n * The schema for parsing natural language scheduling requests.\n *\n * @example\n * ```typescript\n * import { generateObject } from \"ai\";\n * import { scheduleSchema, getSchedulePrompt } from \"agents/schedule\";\n *\n * const result = await generateObject({\n * model,\n * prompt: `${getSchedulePrompt({ date: new Date() })} Input: \"${userInput}\"`,\n * schema: scheduleSchema,\n * // Required for OpenAI to avoid strict JSON schema validation errors\n * providerOptions: {\n * openai: { strictJsonSchema: false }\n * }\n * });\n * ```\n *\n * @remarks\n * When using this schema with OpenAI models via the AI SDK, you must pass\n * `providerOptions: { openai: { strictJsonSchema: false } }` to `generateObject`.\n * This is because the schema uses a discriminated union which is not compatible\n * with OpenAI's strict structured outputs mode.\n */\nexport const scheduleSchema = z.object({\n description: z.string().describe(\"A description of the task\"),\n when: z.discriminatedUnion(\"type\", [\n z.object({\n type: z.literal(\"scheduled\"),\n date: z\n .string()\n .describe(\n \"Execute task at the specified date and time in ISO 8601 format\"\n )\n }),\n z.object({\n type: z.literal(\"delayed\"),\n delayInSeconds: z\n .number()\n .describe(\"Execute task after a delay in seconds\")\n }),\n z.object({\n type: z.literal(\"cron\"),\n cron: z\n .string()\n .describe(\n \"Execute task on a recurring interval specified as cron syntax\"\n )\n }),\n z.object({\n type: z.literal(\"no-schedule\")\n })\n ])\n});\n\n/**\n * The type for the schedule prompt\n */\nexport type Schedule = z.infer<typeof scheduleSchema>;\n\n/**\n * @deprecated this has been renamed to scheduleSchema, and unstable_scheduleSchema will be removed in the next major version\n * @returns The schedule schema\n */\nexport const unstable_scheduleSchema = scheduleSchema;\n"],"mappings":";;;;;;;AAOA,SAAgB,kBAAkB,OAAuB;CACvD,OAAO;;;gBAGO,MAAM,KAAK,aAAa,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CzC,IAAI,wCAAwC;;;;;;AAO5C,SAAgB,2BAA2B,OAAuB;CAChE,IAAI,CAAC,uCAAuC;EAC1C,wCAAwC;EACxC,QAAQ,KACN,iJACD;;CAEH,OAAO,kBAAkB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BjC,MAAa,iBAAiB,EAAE,OAAO;CACrC,aAAa,EAAE,QAAQ,CAAC,SAAS,4BAA4B;CAC7D,MAAM,EAAE,mBAAmB,QAAQ;EACjC,EAAE,OAAO;GACP,MAAM,EAAE,QAAQ,YAAY;GAC5B,MAAM,EACH,QAAQ,CACR,SACC,iEACD;GACJ,CAAC;EACF,EAAE,OAAO;GACP,MAAM,EAAE,QAAQ,UAAU;GAC1B,gBAAgB,EACb,QAAQ,CACR,SAAS,wCAAwC;GACrD,CAAC;EACF,EAAE,OAAO;GACP,MAAM,EAAE,QAAQ,OAAO;GACvB,MAAM,EACH,QAAQ,CACR,SACC,gEACD;GACJ,CAAC;EACF,EAAE,OAAO,EACP,MAAM,EAAE,QAAQ,cAAc,EAC/B,CAAC;EACH,CAAC;CACH,CAAC;;;;;AAWF,MAAa,0BAA0B"}
@@ -1,4 +1,4 @@
1
- import { H as StreamingResponse } from "./agent-tool-types-DSteYkkS.js";
1
+ import { W as StreamingResponse } from "./agent-tool-types-CM_50fcV.js";
2
2
 
3
3
  //#region src/serializable.d.ts
4
4
  type SerializablePrimitive = undefined | null | string | number | boolean;
@@ -31,4 +31,4 @@ export {
31
31
  SEARCH_DESCRIPTION as r,
32
32
  BrowserToolsOptions as t
33
33
  };
34
- //# sourceMappingURL=shared-Ch9slKdI.d.ts.map
34
+ //# sourceMappingURL=shared-Cvj92byG.d.ts.map
@@ -1,6 +1,6 @@
1
- import { a as _checkPrivateRedeclaration, i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-Bqby-AHD.js";
1
+ import { a as _checkPrivateRedeclaration, i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-CS51BNGR.js";
2
2
  import { DynamicWorkerExecutor } from "@cloudflare/codemode";
3
- //#region \0@oxc-project+runtime@0.127.0/helpers/classPrivateMethodInitSpec.js
3
+ //#region \0@oxc-project+runtime@0.129.0/helpers/classPrivateMethodInitSpec.js
4
4
  function _classPrivateMethodInitSpec(e, a) {
5
5
  _checkPrivateRedeclaration(e, a), a.add(e);
6
6
  }
@@ -434,4 +434,4 @@ function createBrowserToolHandlers(options) {
434
434
  //#endregion
435
435
  export { connectBrowser as a, CdpSession as i, SEARCH_DESCRIPTION as n, connectUrl as o, createBrowserToolHandlers as r, EXECUTE_DESCRIPTION as t };
436
436
 
437
- //# sourceMappingURL=shared-C6l4ZKRN.js.map
437
+ //# sourceMappingURL=shared-DzJYHisH.js.map