agents 0.20.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/README.md +50 -12
  2. package/dist/{agent-tool-types-Btk9ETS-.d.ts → agent-tool-types-CzGGB-20.d.ts} +403 -115
  3. package/dist/agent-tool-types.d.ts +1 -1
  4. package/dist/{agent-tools-UuScsJg3.d.ts → agent-tools-zR2d5uij.d.ts} +2 -2
  5. package/dist/agent-tools.d.ts +24 -8
  6. package/dist/agent-tools.js +14 -6
  7. package/dist/agent-tools.js.map +1 -1
  8. package/dist/browser/ai.d.ts +5 -3
  9. package/dist/browser/ai.js +86 -7
  10. package/dist/browser/ai.js.map +1 -1
  11. package/dist/browser/index.d.ts +1 -1
  12. package/dist/browser/index.js +1 -1
  13. package/dist/browser/tanstack-ai.js +13 -1
  14. package/dist/browser/tanstack-ai.js.map +1 -1
  15. package/dist/chat/index.d.ts +31 -2
  16. package/dist/chat/index.js +57 -2
  17. package/dist/chat/index.js.map +1 -1
  18. package/dist/chat/react.d.ts +5 -179
  19. package/dist/chat/react.js +18 -555
  20. package/dist/chat/react.js.map +1 -1
  21. package/dist/chat/transport.d.ts +10 -0
  22. package/dist/chat/transport.js +2 -0
  23. package/dist/chat-sdk/index.d.ts +1 -1
  24. package/dist/client.d.ts +1 -1
  25. package/dist/cloudflare-BduZwmYK.js +204 -0
  26. package/dist/cloudflare-BduZwmYK.js.map +1 -0
  27. package/dist/{connector-v2M1zlZp.d.ts → connector-CkQD4MK3.d.ts} +20 -3
  28. package/dist/{connector-KEJnl6e5.js → connector-CptFKzRh.js} +158 -40
  29. package/dist/connector-CptFKzRh.js.map +1 -0
  30. package/dist/{handler-stateless-8hQN_kC3.js → handler-stateless-CIkKPETH.js} +20 -69
  31. package/dist/handler-stateless-CIkKPETH.js.map +1 -0
  32. package/dist/index.d.ts +21 -11
  33. package/dist/index.js +31 -21
  34. package/dist/index.js.map +1 -1
  35. package/dist/mcp/client.d.ts +20 -20
  36. package/dist/mcp/index.d.ts +35 -35
  37. package/dist/mcp/index.js +32 -98
  38. package/dist/mcp/index.js.map +1 -1
  39. package/dist/mcp/server.js +1 -1
  40. package/dist/observability/ai/index.d.ts +10 -131
  41. package/dist/observability/ai/index.js +209 -444
  42. package/dist/observability/ai/index.js.map +1 -1
  43. package/dist/{wire-types-CU9rLoeS.js → protocol-Dqc2MQxo.js} +2 -46
  44. package/dist/protocol-Dqc2MQxo.js.map +1 -0
  45. package/dist/react.d.ts +1 -1
  46. package/dist/react.js +5 -8
  47. package/dist/react.js.map +1 -1
  48. package/dist/serializable.d.ts +1 -1
  49. package/dist/sub-routing.d.ts +18 -6
  50. package/dist/sub-routing.js +92 -2
  51. package/dist/sub-routing.js.map +1 -1
  52. package/dist/wire-types-CnMt6_HR.js +47 -0
  53. package/dist/wire-types-CnMt6_HR.js.map +1 -0
  54. package/dist/workflow-types.d.ts +25 -25
  55. package/dist/workflow-types.js.map +1 -1
  56. package/dist/workflows.d.ts +22 -22
  57. package/dist/ws-chat-transport-CIoOBbO7.js +561 -0
  58. package/dist/ws-chat-transport-CIoOBbO7.js.map +1 -0
  59. package/dist/ws-chat-transport-UNRIS2xl.d.ts +184 -0
  60. package/docs/adding-to-existing-project.md +4 -2
  61. package/docs/agent-class.md +1 -1
  62. package/docs/agent-tools.md +29 -0
  63. package/docs/browse-the-web.md +16 -1
  64. package/docs/chat-agents.md +3 -1
  65. package/docs/client-sdk.md +12 -8
  66. package/docs/configuration.md +7 -1
  67. package/docs/cross-domain-authentication.md +7 -35
  68. package/docs/email.md +2 -13
  69. package/docs/human-in-the-loop.md +15 -12
  70. package/docs/long-running-agents.md +11 -11
  71. package/docs/mcp-client.md +1 -1
  72. package/docs/mcp-servers.md +7 -1
  73. package/docs/mcp-transports.md +18 -12
  74. package/docs/migration-to-ai-sdk-v5.md +2 -2
  75. package/docs/migration-to-ai-sdk-v6.md +5 -1
  76. package/docs/observability.md +24 -67
  77. package/docs/routing.md +27 -0
  78. package/docs/sub-agents.md +47 -2
  79. package/docs/webhooks.md +109 -136
  80. package/docs/workflows.md +9 -1
  81. package/package.json +19 -10
  82. package/dist/cloudflare-BldFV0Pa.js +0 -117
  83. package/dist/cloudflare-BldFV0Pa.js.map +0 -1
  84. package/dist/connector-KEJnl6e5.js.map +0 -1
  85. package/dist/handler-stateless-8hQN_kC3.js.map +0 -1
  86. package/dist/wire-types-CU9rLoeS.js.map +0 -1
  87. package/dist/workflow-types-Baz_PO5v.d.ts +0 -280
package/docs/webhooks.md CHANGED
@@ -7,56 +7,54 @@ Receive webhook events from external services and route them to dedicated agent
7
7
  ```typescript
8
8
  import { Agent, getAgentByName, routeAgentRequest } from "agents";
9
9
 
10
- // Agent that handles webhooks for a specific entity
10
+ type GitHubWebhookPayload = {
11
+ repository?: { full_name?: string };
12
+ };
13
+
14
+ async function verifyGitHubWebhook(
15
+ rawBody: string,
16
+ signature: string | null,
17
+ secret: string
18
+ ): Promise<boolean> {
19
+ if (!signature || !/^sha256=[0-9a-f]{64}$/i.test(signature)) return false;
20
+
21
+ const encoder = new TextEncoder();
22
+ const key = await crypto.subtle.importKey(
23
+ "raw",
24
+ encoder.encode(secret),
25
+ { name: "HMAC", hash: "SHA-256" },
26
+ false,
27
+ ["verify"]
28
+ );
29
+ const signatureBytes = Uint8Array.from(
30
+ signature.slice("sha256=".length).match(/.{2}/g) ?? [],
31
+ (byte) => Number.parseInt(byte, 16)
32
+ );
33
+
34
+ return crypto.subtle.verify(
35
+ "HMAC",
36
+ key,
37
+ signatureBytes,
38
+ encoder.encode(rawBody)
39
+ );
40
+ }
41
+
11
42
  export class WebhookAgent extends Agent<Env> {
12
43
  async onRequest(request: Request): Promise<Response> {
13
44
  if (request.method !== "POST") {
14
45
  return new Response("Method not allowed", { status: 405 });
15
46
  }
16
47
 
17
- // Verify the webhook signature
48
+ const rawBody = await request.text();
18
49
  const signature = request.headers.get("X-Hub-Signature-256");
19
- const body = await request.text();
20
-
21
50
  if (
22
- !(await this.verifySignature(body, signature, this.env.WEBHOOK_SECRET))
51
+ !(await verifyGitHubWebhook(rawBody, signature, this.env.WEBHOOK_SECRET))
23
52
  ) {
24
53
  return new Response("Invalid signature", { status: 401 });
25
54
  }
26
55
 
27
- // Process the webhook payload
28
- const payload = JSON.parse(body);
29
- await this.processEvent(payload);
30
-
31
- return new Response("OK", { status: 200 });
32
- }
33
-
34
- private async verifySignature(
35
- payload: string,
36
- signature: string | null,
37
- secret: string
38
- ): Promise<boolean> {
39
- if (!signature) return false;
40
-
41
- const encoder = new TextEncoder();
42
- const key = await crypto.subtle.importKey(
43
- "raw",
44
- encoder.encode(secret),
45
- { name: "HMAC", hash: "SHA-256" },
46
- false,
47
- ["sign"]
48
- );
49
-
50
- const signatureBytes = await crypto.subtle.sign(
51
- "HMAC",
52
- key,
53
- encoder.encode(payload)
54
- );
55
- const expected = `sha256=${Array.from(new Uint8Array(signatureBytes))
56
- .map((b) => b.toString(16).padStart(2, "0"))
57
- .join("")}`;
58
-
59
- return signature === expected;
56
+ await this.processEvent(JSON.parse(rawBody));
57
+ return new Response("OK");
60
58
  }
61
59
 
62
60
  private async processEvent(payload: unknown) {
@@ -64,19 +62,30 @@ export class WebhookAgent extends Agent<Env> {
64
62
  }
65
63
  }
66
64
 
67
- // Route webhooks to the right agent instance
68
65
  export default {
69
66
  async fetch(request: Request, env: Env): Promise<Response> {
70
67
  const url = new URL(request.url);
71
68
 
72
- // Webhook endpoint: POST /webhooks/:entityId
73
- if (url.pathname.startsWith("/webhooks/") && request.method === "POST") {
74
- const entityId = url.pathname.split("/")[2];
75
- const agent = await getAgentByName(env.WebhookAgent, entityId);
69
+ if (url.pathname === "/webhooks/github" && request.method === "POST") {
70
+ const rawBody = await request.clone().text();
71
+ const signature = request.headers.get("X-Hub-Signature-256");
72
+ if (
73
+ !(await verifyGitHubWebhook(rawBody, signature, env.WEBHOOK_SECRET))
74
+ ) {
75
+ return new Response("Invalid signature", { status: 401 });
76
+ }
77
+
78
+ const payload = JSON.parse(rawBody) as GitHubWebhookPayload;
79
+ const repository = payload.repository?.full_name;
80
+ if (!repository) {
81
+ return new Response("Missing repository", { status: 400 });
82
+ }
83
+
84
+ const agentName = repository.toLowerCase().replace(/\//g, "-");
85
+ const agent = await getAgentByName(env.WebhookAgent, agentName);
76
86
  return agent.fetch(request);
77
87
  }
78
88
 
79
- // Default routing for WebSocket connections
80
89
  return (
81
90
  (await routeAgentRequest(request, env)) ||
82
91
  new Response("Not found", { status: 404 })
@@ -131,7 +140,7 @@ Webhooks combined with agents enable powerful patterns where each external entit
131
140
 
132
141
  ## Routing Webhooks to Agents
133
142
 
134
- The key pattern is extracting an entity identifier from the webhook and using `getAgentByName()` to route to a dedicated agent instance.
143
+ The key pattern is verifying the raw request before parsing it, then deriving the Agent identity from authenticated payload data. A body signature does not authenticate an unrelated URL segment or arbitrary header.
135
144
 
136
145
  ### Extract Entity from Payload
137
146
 
@@ -140,19 +149,23 @@ Most webhooks include an identifier in the payload:
140
149
  ```typescript
141
150
  export default {
142
151
  async fetch(request: Request, env: Env): Promise<Response> {
152
+ const url = new URL(request.url);
143
153
  if (request.method === "POST" && url.pathname === "/webhooks/github") {
144
- const payload = await request.clone().json();
154
+ const rawBody = await request.clone().text();
155
+ const signature = request.headers.get("X-Hub-Signature-256");
156
+ if (
157
+ !(await verifyGitHubWebhook(rawBody, signature, env.WEBHOOK_SECRET))
158
+ ) {
159
+ return new Response("Invalid signature", { status: 401 });
160
+ }
145
161
 
146
- // Extract entity ID from payload
147
- const repoFullName = payload.repository?.full_name;
148
- if (!repoFullName) {
162
+ const payload = JSON.parse(rawBody) as GitHubWebhookPayload;
163
+ const repository = payload.repository?.full_name;
164
+ if (!repository) {
149
165
  return new Response("Missing repository", { status: 400 });
150
166
  }
151
167
 
152
- // Sanitize for use as agent name
153
- const agentName = repoFullName.toLowerCase().replace(/\//g, "-");
154
-
155
- // Route to dedicated agent
168
+ const agentName = repository.toLowerCase().replace(/\//g, "-");
156
169
  const agent = await getAgentByName(env.RepoAgent, agentName);
157
170
  return agent.fetch(request);
158
171
  }
@@ -160,69 +173,21 @@ export default {
160
173
  };
161
174
  ```
162
175
 
163
- ### Extract Entity from URL
164
-
165
- Alternatively, include the entity ID in the webhook URL:
166
-
167
- ```typescript
168
- // Webhook URL: https://your-worker.dev/webhooks/stripe/cus_123456
169
- if (url.pathname.startsWith("/webhooks/stripe/")) {
170
- const customerId = url.pathname.split("/")[3]; // "cus_123456"
171
- const agent = await getAgentByName(env.StripeAgent, customerId);
172
- return agent.fetch(request);
173
- }
174
- ```
176
+ ### Validate Entity IDs in URLs
175
177
 
176
- ### Extract Entity from Headers
178
+ A provider's body signature does not authenticate the webhook URL. If the URL includes an entity ID, compare it with the corresponding identity from the verified provider payload and reject a mismatch before calling `getAgentByName()`.
177
179
 
178
- Some services include identifiers in headers:
180
+ ### Derive Slack Identity from the Verified Body
179
181
 
180
- ```typescript
181
- // Slack sends workspace info in headers
182
- const teamId = request.headers.get("X-Slack-Team-Id");
183
- if (teamId) {
184
- const agent = await getAgentByName(env.SlackAgent, teamId);
185
- return agent.fetch(request);
186
- }
187
- ```
182
+ Slack does not send an authenticated `X-Slack-Team-Id` routing header. Validate Slack's timestamped signature and replay window against the raw body, then read `team_id` from the verified event or form body.
188
183
 
189
184
  ## Signature Verification
190
185
 
191
- Always verify webhook signatures to ensure requests are authentic. Most providers use HMAC-SHA256.
186
+ Always verify webhook signatures before trusting or processing the payload.
192
187
 
193
- ### HMAC-SHA256 Pattern
188
+ ### GitHub HMAC-SHA256 Pattern
194
189
 
195
- ```typescript
196
- async function verifySignature(
197
- payload: string,
198
- signature: string | null,
199
- secret: string
200
- ): Promise<boolean> {
201
- if (!signature) return false;
202
-
203
- const encoder = new TextEncoder();
204
- const key = await crypto.subtle.importKey(
205
- "raw",
206
- encoder.encode(secret),
207
- { name: "HMAC", hash: "SHA-256" },
208
- false,
209
- ["sign"]
210
- );
211
-
212
- const signatureBytes = await crypto.subtle.sign(
213
- "HMAC",
214
- key,
215
- encoder.encode(payload)
216
- );
217
-
218
- const expected = `sha256=${Array.from(new Uint8Array(signatureBytes))
219
- .map((b) => b.toString(16).padStart(2, "0"))
220
- .join("")}`;
221
-
222
- // Use timing-safe comparison in production
223
- return signature === expected;
224
- }
225
- ```
190
+ The Quick Start's `verifyGitHubWebhook()` helper verifies GitHub's `sha256=<hex>` signature over the raw body with `crypto.subtle.verify()`. This format is GitHub-specific. Other providers use different signature encodings, signed inputs, timestamp checks, and replay protections; follow the provider documentation linked under [Common Webhook Providers](#common-webhook-providers).
226
191
 
227
192
  ### Provider-Specific Headers
228
193
 
@@ -238,7 +203,7 @@ async function verifySignature(
238
203
 
239
204
  ### The onRequest Handler
240
205
 
241
- Use `onRequest()` to handle incoming webhooks in your agent:
206
+ Use `onRequest()` to handle incoming webhooks in your agent. If the Worker has not already verified the request, verify it before parsing the body. This example reuses the Quick Start's `verifyGitHubWebhook()` helper:
242
207
 
243
208
  ```typescript
244
209
  export class WebhookAgent extends Agent<Env, MyState> {
@@ -248,14 +213,16 @@ export class WebhookAgent extends Agent<Env, MyState> {
248
213
  return new Response("Method not allowed", { status: 405 });
249
214
  }
250
215
 
251
- // 2. Get event type from headers
252
- const eventType = request.headers.get("X-Event-Type");
216
+ // 2. Get the GitHub event type
217
+ const eventType = request.headers.get("X-GitHub-Event") ?? "unknown";
253
218
 
254
- // 3. Verify signature
255
- const signature = request.headers.get("X-Signature");
219
+ // 3. Verify the GitHub signature
220
+ const signature = request.headers.get("X-Hub-Signature-256");
256
221
  const body = await request.text();
257
222
 
258
- if (!(await this.verifySignature(body, signature))) {
223
+ if (
224
+ !(await verifyGitHubWebhook(body, signature, this.env.WEBHOOK_SECRET))
225
+ ) {
259
226
  return new Response("Invalid signature", { status: 401 });
260
227
  }
261
228
 
@@ -462,35 +429,41 @@ fibers retain status, dedupe provider retries, and let `onFiberRecovered()` or
462
429
 
463
430
  ### Multi-Provider Routing
464
431
 
465
- Handle webhooks from multiple services in one worker:
432
+ Keep provider-specific verification and parsing behind one typed seam. Its implementation must validate the raw request according to the provider documentation linked under [Common Webhook Providers](#common-webhook-providers), then derive `agentName` only from the verified body.
466
433
 
467
434
  ```typescript
435
+ type VerifiedWebhook =
436
+ | { provider: "github"; agentName: string }
437
+ | { provider: "stripe"; agentName: string }
438
+ | { provider: "slack"; agentName: string };
439
+
440
+ declare function verifyAndParseWebhook(
441
+ request: Request,
442
+ env: Env
443
+ ): Promise<VerifiedWebhook | null>;
444
+
468
445
  export default {
469
446
  async fetch(request: Request, env: Env): Promise<Response> {
470
447
  const url = new URL(request.url);
471
-
472
- if (request.method === "POST") {
473
- // GitHub webhooks
474
- if (url.pathname.startsWith("/webhooks/github/")) {
475
- const payload = await request.clone().json();
476
- const repoName = payload.repository?.full_name?.replace("/", "-");
477
- const agent = await getAgentByName(env.GitHubAgent, repoName);
478
- return agent.fetch(request);
479
- }
480
-
481
- // Stripe webhooks
482
- if (url.pathname.startsWith("/webhooks/stripe/")) {
483
- const payload = await request.clone().json();
484
- const customerId = payload.data?.object?.customer;
485
- const agent = await getAgentByName(env.StripeAgent, customerId);
486
- return agent.fetch(request);
448
+ if (request.method === "POST" && url.pathname.startsWith("/webhooks/")) {
449
+ const verified = await verifyAndParseWebhook(request.clone(), env);
450
+ if (!verified) {
451
+ return new Response("Invalid signature", { status: 401 });
487
452
  }
488
453
 
489
- // Slack webhooks
490
- if (url.pathname === "/webhooks/slack") {
491
- const teamId = request.headers.get("X-Slack-Team-Id");
492
- const agent = await getAgentByName(env.SlackAgent, teamId);
493
- return agent.fetch(request);
454
+ switch (verified.provider) {
455
+ case "github":
456
+ return (
457
+ await getAgentByName(env.GitHubAgent, verified.agentName)
458
+ ).fetch(request);
459
+ case "stripe":
460
+ return (
461
+ await getAgentByName(env.StripeAgent, verified.agentName)
462
+ ).fetch(request);
463
+ case "slack":
464
+ return (
465
+ await getAgentByName(env.SlackAgent, verified.agentName)
466
+ ).fetch(request);
494
467
  }
495
468
  }
496
469
 
package/docs/workflows.md CHANGED
@@ -246,7 +246,11 @@ const instanceId = await this.runWorkflow(
246
246
  {
247
247
  id: "custom-id", // optional - auto-generated if not provided
248
248
  metadata: { userId: "user-456", priority: "high" }, // optional - for querying
249
- agentBinding: "MyAgent" // optional - auto-detected from class name if not provided
249
+ agentBinding: "MyAgent", // optional - auto-detected from class name if not provided
250
+ retention: {
251
+ successRetention: "1 day",
252
+ errorRetention: "7 days"
253
+ }
250
254
  }
251
255
  );
252
256
  ```
@@ -258,6 +262,10 @@ const instanceId = await this.runWorkflow(
258
262
  - `options.id` - Custom workflow ID (auto-generated if not provided)
259
263
  - `options.metadata` - Optional metadata stored for querying (not passed to workflow)
260
264
  - `options.agentBinding` - Agent binding name (auto-detected from class name if not provided). When called from a sub-agent, this is the root Agent binding name.
265
+ - [`options.retention`](https://developers.cloudflare.com/workflows/build/workers-api/#workflowinstancecreateoptions) - Workflow retention passed unchanged to
266
+ `Workflow.create()`.
267
+ Use `successRetention` for successful instances and `errorRetention` for
268
+ errored or terminated instances.
261
269
 
262
270
  **Returns:** Workflow instance ID
263
271
 
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "durable objects"
10
10
  ],
11
11
  "type": "module",
12
- "version": "0.20.0",
12
+ "version": "0.21.0",
13
13
  "license": "MIT",
14
14
  "repository": {
15
15
  "directory": "packages/agents",
@@ -31,22 +31,23 @@
31
31
  "esbuild": "^0.28.1",
32
32
  "mimetext": "^3.0.28",
33
33
  "nanoid": "^5.1.16",
34
- "partyserver": "^0.5.8",
34
+ "partyserver": "^0.5.9",
35
35
  "partysocket": "1.3.0",
36
36
  "yaml": "^2.9.0",
37
37
  "yargs": "^18.0.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@ai-sdk/react": "^4.0.0",
41
+ "@ai-sdk/valibot": "3.0.6",
41
42
  "@cloudflare/codemode": "^0.5.1",
42
- "@modelcontextprotocol/client": "2.0.0-beta.5",
43
+ "@modelcontextprotocol/client": "2.0.0",
43
44
  "@modelcontextprotocol/conformance-v2": "npm:@modelcontextprotocol/conformance@0.2.0-alpha.10",
44
- "@modelcontextprotocol/sdk": "1.29.0",
45
- "@modelcontextprotocol/server": "2.0.0-beta.5",
45
+ "@modelcontextprotocol/sdk": "1.30.0",
46
+ "@modelcontextprotocol/server": "2.0.0",
46
47
  "@tanstack/ai": "0.38.0",
47
48
  "@types/react": "^19.2.17",
48
49
  "@types/yargs": "^17.0.35",
49
- "@vitest/browser-playwright": "^4.1.9",
50
+ "@valibot/to-json-schema": "1.3.0",
50
51
  "@x402/core": "^2.17.0",
51
52
  "@x402/evm": "^2.17.0",
52
53
  "ai": "^7.0.0",
@@ -54,15 +55,15 @@
54
55
  "glob": "^13.0.6",
55
56
  "just-bash": "^3.0.2",
56
57
  "react": "^19.2.7",
57
- "vitest-browser-react": "^2.2.0",
58
+ "valibot": "1.4.1",
58
59
  "zod": "^4.4.3"
59
60
  },
60
61
  "peerDependencies": {
61
62
  "@ai-sdk/react": "^3.0.0 || ^4.0.0",
62
63
  "@cloudflare/codemode": ">=0.5.0",
63
- "@modelcontextprotocol/client": "2.0.0-beta.5",
64
- "@modelcontextprotocol/sdk": "1.29.0",
65
- "@modelcontextprotocol/server": "2.0.0-beta.5",
64
+ "@modelcontextprotocol/client": "2.0.0",
65
+ "@modelcontextprotocol/sdk": "1.30.0",
66
+ "@modelcontextprotocol/server": "2.0.0",
66
67
  "@tanstack/ai": ">=0.10.2 <1.0.0",
67
68
  "@x402/core": "^2.0.0",
68
69
  "@x402/evm": "^2.0.0",
@@ -98,6 +99,9 @@
98
99
  "just-bash": {
99
100
  "optional": true
100
101
  },
102
+ "react": {
103
+ "optional": true
104
+ },
101
105
  "vite": {
102
106
  "optional": true
103
107
  }
@@ -199,6 +203,11 @@
199
203
  "import": "./dist/chat/index.js",
200
204
  "require": "./dist/chat/index.js"
201
205
  },
206
+ "./chat/transport": {
207
+ "types": "./dist/chat/transport.d.ts",
208
+ "import": "./dist/chat/transport.js",
209
+ "require": "./dist/chat/transport.js"
210
+ },
202
211
  "./chat/react": {
203
212
  "types": "./dist/chat/react.d.ts",
204
213
  "import": "./dist/chat/react.js",
@@ -1,117 +0,0 @@
1
- import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
2
- import * as cloudflareWorkers from "cloudflare:workers";
3
- //#region src/observability/tracing/tracer.ts
4
- /** Creates a tracer from a runtime span capability. */
5
- function createTracer(runtime) {
6
- return new RuntimeTracer(runtime);
7
- }
8
- var RuntimeTracer = class {
9
- constructor(runtime) {
10
- this.runtime = runtime;
11
- }
12
- withSpan(name, attributes, run) {
13
- return this.activate(name, attributes, (span) => {
14
- const result = run(span);
15
- if (isPromiseLike(result)) return Promise.resolve(result).catch((cause) => {
16
- span.fail(cause);
17
- throw cause;
18
- }).finally(() => {
19
- span.close();
20
- });
21
- span.close();
22
- return result;
23
- });
24
- }
25
- openSpan(name, attributes, activate) {
26
- return this.activate(name, attributes, activate);
27
- }
28
- /**
29
- * Shared scaffold: opens an active span, seeds its attributes, and fails the
30
- * span on a thrown defect before rethrowing. The `body` decides the span's
31
- * finishing policy (managed vs. caller-owned).
32
- */
33
- activate(name, attributes, body) {
34
- return this.runtime.startActiveSpan(name, (writer) => {
35
- setAttributes(writer, attributes);
36
- const span = new ManagedSpan(writer);
37
- try {
38
- return body(span);
39
- } catch (cause) {
40
- span.fail(cause);
41
- throw cause;
42
- }
43
- });
44
- }
45
- };
46
- var _closed = /* @__PURE__ */ new WeakMap();
47
- var ManagedSpan = class {
48
- constructor(span) {
49
- this.span = span;
50
- _classPrivateFieldInitSpec(this, _closed, false);
51
- }
52
- get isTraced() {
53
- return this.span.isTraced;
54
- }
55
- /** INTERNAL: see {@link writeSpanAttributes}. */
56
- writeAttributes(attributes) {
57
- if (_classPrivateFieldGet2(_closed, this)) return;
58
- setAttributes(this.span, attributes);
59
- }
60
- finish(attributes = {}) {
61
- if (_classPrivateFieldGet2(_closed, this)) return;
62
- setAttributes(this.span, attributes);
63
- this.close();
64
- }
65
- fail(cause) {
66
- if (_classPrivateFieldGet2(_closed, this)) return;
67
- if (isCancellation(cause)) setAttributes(this.span, { "cloudflare.agents.canceled": true });
68
- else setAttributes(this.span, { "error.type": cause instanceof Error ? cause.name || "Error" : typeof cause });
69
- this.close();
70
- }
71
- close() {
72
- if (_classPrivateFieldGet2(_closed, this)) return;
73
- _classPrivateFieldSet2(_closed, this, true);
74
- this.span.end();
75
- }
76
- };
77
- /**
78
- * INTERNAL: writes attributes onto an open managed span. Lets instrumentation
79
- * defer expensive attribute computation until after the isTraced check (span
80
- * names must exist at open time; attributes need not). Not part of the public
81
- * barrel surface.
82
- */
83
- function writeSpanAttributes(span, attributes) {
84
- if (span instanceof ManagedSpan) span.writeAttributes(attributes);
85
- }
86
- function setAttributes(span, attributes) {
87
- if (!span.isTraced) return;
88
- try {
89
- for (const [key, value] of Object.entries(attributes)) if (value !== void 0) span.setAttribute(key, value);
90
- } catch {}
91
- }
92
- function isPromiseLike(value) {
93
- return value !== null && value !== void 0 && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
94
- }
95
- /**
96
- * Recognizes caller/runtime cancellation (an `AbortError`, e.g. from an aborted
97
- * `AbortSignal`) so it can be classified separately from genuine failures. A
98
- * `DOMException` named `AbortError` is not always an `Error` instance, so this
99
- * probes the `name` field structurally rather than via `instanceof`.
100
- */
101
- function isCancellation(cause) {
102
- return typeof cause === "object" && cause !== null && "name" in cause && cause.name === "AbortError";
103
- }
104
- //#endregion
105
- //#region src/observability/tracing/cloudflare.ts
106
- const noopSpan = {
107
- isTraced: false,
108
- setAttribute() {},
109
- end() {}
110
- };
111
- const tracer = createTracer(cloudflareWorkers.tracing ?? { startActiveSpan(_name, run) {
112
- return run(noopSpan);
113
- } });
114
- //#endregion
115
- export { writeSpanAttributes as n, tracer as t };
116
-
117
- //# sourceMappingURL=cloudflare-BldFV0Pa.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cloudflare-BldFV0Pa.js","names":[],"sources":["../src/observability/tracing/tracer.ts","../src/observability/tracing/cloudflare.ts"],"sourcesContent":["/** Attribute values accepted by custom spans. */\nexport type TraceAttributeValue = string | number | boolean | undefined;\n\n/** Initial or finish attributes attached to a span. */\nexport type TraceAttributes = Readonly<Record<string, TraceAttributeValue>>;\n\n/** A value that may complete synchronously or through a promise-like result. */\nexport type MaybePromise<T> = T | PromiseLike<T>;\n\n/** Minimal runtime span surface used by tracers. */\nexport type SpanWriter = {\n readonly isTraced: boolean;\n setAttribute(key: string, value: TraceAttributeValue): void;\n end(): void;\n};\n\n/** Runtime capability for starting an active span in the current async context. */\nexport type SpanRuntime = {\n startActiveSpan<T>(name: string, run: (span: SpanWriter) => T): T;\n};\n\n/** AgentTracer seam used by integrations. */\nexport type AgentTracer = {\n /**\n * Runs `run` inside an active span whose lifetime the tracer owns: the span\n * finishes when `run` returns (or its promise resolves) and fails when `run`\n * throws or rejects. Callers do not call {@link AgentSpan.finish}/{@link AgentSpan.fail};\n * doing so early is safe but the tracer guarantees closure.\n *\n * @template T The value produced by the instrumented work.\n */\n withSpan<T>(\n name: string,\n attributes: TraceAttributes,\n run: (span: AgentSpan) => MaybePromise<T>\n ): T | Promise<T>;\n /**\n * Activates a span and returns whatever `activate` returns (typically the\n * {@link AgentSpan} handle itself). The caller owns the span lifetime and MUST call\n * {@link AgentSpan.finish} or {@link AgentSpan.fail}; an unfinished span leaks. Use this\n * for work that outlives the callback, such as streams and event-driven\n * telemetry. A throw from `activate` still fails the span before rethrowing.\n *\n * @template T The value returned to the caller, usually the span handle.\n */\n openSpan<T>(\n name: string,\n attributes: TraceAttributes,\n activate: (span: AgentSpan) => T\n ): T;\n};\n\n/** Active span handle passed to instrumented work. */\nexport type AgentSpan = {\n /**\n * Whether this invocation is actually being traced. Instrumentation can use\n * this to skip expensive capture work when nobody is listening.\n */\n readonly isTraced: boolean;\n /** Records the optional finish attributes and ends the span. Idempotent. */\n finish(attributes?: TraceAttributes): void;\n /**\n * Ends the span as not-successful. Genuine failures record `error.type`;\n * recognized cancellations (an `AbortError`) record `canceled` instead so aborts\n * are not counted as errors. The cause message is never recorded. Idempotent.\n */\n fail(cause: unknown): void;\n};\n\n/** Creates a tracer from a runtime span capability. */\nexport function createTracer(runtime: SpanRuntime): AgentTracer {\n return new RuntimeTracer(runtime);\n}\n\nclass RuntimeTracer implements AgentTracer {\n constructor(private readonly runtime: SpanRuntime) {}\n\n withSpan<T>(\n name: string,\n attributes: TraceAttributes,\n run: (span: AgentSpan) => MaybePromise<T>\n ): T | Promise<T> {\n return this.activate(name, attributes, (span) => {\n const result = run(span);\n if (isPromiseLike(result)) {\n return Promise.resolve(result)\n .catch((cause: unknown) => {\n span.fail(cause);\n throw cause;\n })\n .finally(() => {\n span.close();\n });\n }\n\n span.close();\n return result;\n });\n }\n\n openSpan<T>(\n name: string,\n attributes: TraceAttributes,\n activate: (span: AgentSpan) => T\n ): T {\n return this.activate(name, attributes, activate);\n }\n\n /**\n * Shared scaffold: opens an active span, seeds its attributes, and fails the\n * span on a thrown defect before rethrowing. The `body` decides the span's\n * finishing policy (managed vs. caller-owned).\n */\n private activate<T>(\n name: string,\n attributes: TraceAttributes,\n body: (span: ManagedSpan) => T\n ): T {\n return this.runtime.startActiveSpan(name, (writer) => {\n setAttributes(writer, attributes);\n const span = new ManagedSpan(writer);\n\n try {\n return body(span);\n } catch (cause: unknown) {\n span.fail(cause);\n throw cause;\n }\n });\n }\n}\n\nclass ManagedSpan implements AgentSpan {\n #closed = false;\n\n constructor(private readonly span: SpanWriter) {}\n\n get isTraced(): boolean {\n return this.span.isTraced;\n }\n\n /** INTERNAL: see {@link writeSpanAttributes}. */\n writeAttributes(attributes: TraceAttributes): void {\n if (this.#closed) {\n return;\n }\n\n setAttributes(this.span, attributes);\n }\n\n finish(attributes: TraceAttributes = {}): void {\n if (this.#closed) {\n return;\n }\n\n setAttributes(this.span, attributes);\n this.close();\n }\n\n fail(cause: unknown): void {\n if (this.#closed) {\n return;\n }\n\n if (isCancellation(cause)) {\n // Cancellation is a control path, not a failure: OTel semconv leaves\n // status Unset and records no error.type for cancellations, so aborted\n // operations do not inflate error rates. The vendor marker is additive.\n setAttributes(this.span, { \"cloudflare.agents.canceled\": true });\n } else {\n // Workers' custom Span API does not currently expose setStatus(). Do not\n // invent an `otel.status_code` attribute: status is span state in OTel,\n // not an attribute. error.type remains the standard queryable marker.\n setAttributes(this.span, {\n \"error.type\":\n cause instanceof Error ? cause.name || \"Error\" : typeof cause\n });\n }\n\n this.close();\n }\n\n close(): void {\n if (this.#closed) {\n return;\n }\n\n this.#closed = true;\n this.span.end();\n }\n}\n\n/**\n * INTERNAL: writes attributes onto an open managed span. Lets instrumentation\n * defer expensive attribute computation until after the isTraced check (span\n * names must exist at open time; attributes need not). Not part of the public\n * barrel surface.\n */\nexport function writeSpanAttributes(\n span: AgentSpan,\n attributes: TraceAttributes\n): void {\n if (span instanceof ManagedSpan) {\n span.writeAttributes(attributes);\n }\n}\n\nfunction setAttributes(span: SpanWriter, attributes: TraceAttributes): void {\n if (!span.isTraced) {\n return;\n }\n\n // Fail-safe: a throwing writer must not leak the span or replace the\n // application's original error with a telemetry one.\n try {\n for (const [key, value] of Object.entries(attributes)) {\n if (value !== undefined) {\n span.setAttribute(key, value);\n }\n }\n } catch {\n // Drop the attributes; the span still closes.\n }\n}\n\nfunction isPromiseLike<T>(value: MaybePromise<T>): value is PromiseLike<T> {\n return (\n value !== null &&\n value !== undefined &&\n (typeof value === \"object\" || typeof value === \"function\") &&\n \"then\" in value &&\n typeof value.then === \"function\"\n );\n}\n\n/**\n * Recognizes caller/runtime cancellation (an `AbortError`, e.g. from an aborted\n * `AbortSignal`) so it can be classified separately from genuine failures. A\n * `DOMException` named `AbortError` is not always an `Error` instance, so this\n * probes the `name` field structurally rather than via `instanceof`.\n */\nfunction isCancellation(cause: unknown): boolean {\n return (\n typeof cause === \"object\" &&\n cause !== null &&\n \"name\" in cause &&\n cause.name === \"AbortError\"\n );\n}\n","import * as cloudflareWorkers from \"cloudflare:workers\";\nimport { createTracer } from \"./tracer\";\nimport type { SpanRuntime, SpanWriter, AgentTracer } from \"./tracer\";\n\nconst noopSpan: SpanWriter = {\n isTraced: false,\n setAttribute() {},\n end() {}\n};\n\nconst noopRuntime: SpanRuntime = {\n startActiveSpan(_name, run) {\n return run(noopSpan);\n }\n};\n\n// Accessed via the namespace so runtimes that predate the `tracing` export\n// degrade to a no-op tracer instead of failing at module-link time — this\n// module loads with the main `agents` entry, not just for tracing users.\nconst runtime: SpanRuntime =\n (cloudflareWorkers as { tracing?: SpanRuntime }).tracing ?? noopRuntime;\n\nexport const tracer: AgentTracer = createTracer(runtime);\n"],"mappings":";;;;AAsEA,SAAgB,aAAa,SAAmC;CAC9D,OAAO,IAAI,cAAc,OAAO;AAClC;AAEA,IAAM,gBAAN,MAA2C;CACzC,YAAY,SAAuC;EAAtB,KAAA,UAAA;CAAuB;CAEpD,SACE,MACA,YACA,KACgB;EAChB,OAAO,KAAK,SAAS,MAAM,aAAa,SAAS;GAC/C,MAAM,SAAS,IAAI,IAAI;GACvB,IAAI,cAAc,MAAM,GACtB,OAAO,QAAQ,QAAQ,MAAM,CAAC,CAC3B,OAAO,UAAmB;IACzB,KAAK,KAAK,KAAK;IACf,MAAM;GACR,CAAC,CAAC,CACD,cAAc;IACb,KAAK,MAAM;GACb,CAAC;GAGL,KAAK,MAAM;GACX,OAAO;EACT,CAAC;CACH;CAEA,SACE,MACA,YACA,UACG;EACH,OAAO,KAAK,SAAS,MAAM,YAAY,QAAQ;CACjD;;;;;;CAOA,SACE,MACA,YACA,MACG;EACH,OAAO,KAAK,QAAQ,gBAAgB,OAAO,WAAW;GACpD,cAAc,QAAQ,UAAU;GAChC,MAAM,OAAO,IAAI,YAAY,MAAM;GAEnC,IAAI;IACF,OAAO,KAAK,IAAI;GAClB,SAAS,OAAgB;IACvB,KAAK,KAAK,KAAK;IACf,MAAM;GACR;EACF,CAAC;CACH;AACF;;AAEA,IAAM,cAAN,MAAuC;CAGrC,YAAY,MAAmC;EAAlB,KAAA,OAAA;4CAFnB,KAAA;CAEsC;CAEhD,IAAI,WAAoB;EACtB,OAAO,KAAK,KAAK;CACnB;;CAGA,gBAAgB,YAAmC;EACjD,IAAA,uBAAA,SAAI,IAAA,GACF;EAGF,cAAc,KAAK,MAAM,UAAU;CACrC;CAEA,OAAO,aAA8B,CAAC,GAAS;EAC7C,IAAA,uBAAA,SAAI,IAAA,GACF;EAGF,cAAc,KAAK,MAAM,UAAU;EACnC,KAAK,MAAM;CACb;CAEA,KAAK,OAAsB;EACzB,IAAA,uBAAA,SAAI,IAAA,GACF;EAGF,IAAI,eAAe,KAAK,GAItB,cAAc,KAAK,MAAM,EAAE,8BAA8B,KAAK,CAAC;OAK/D,cAAc,KAAK,MAAM,EACvB,cACE,iBAAiB,QAAQ,MAAM,QAAQ,UAAU,OAAO,MAC5D,CAAC;EAGH,KAAK,MAAM;CACb;CAEA,QAAc;EACZ,IAAA,uBAAA,SAAI,IAAA,GACF;EAGF,uBAAA,SAAA,MAAe,IAAA;EACf,KAAK,KAAK,IAAI;CAChB;AACF;;;;;;;AAQA,SAAgB,oBACd,MACA,YACM;CACN,IAAI,gBAAgB,aAClB,KAAK,gBAAgB,UAAU;AAEnC;AAEA,SAAS,cAAc,MAAkB,YAAmC;CAC1E,IAAI,CAAC,KAAK,UACR;CAKF,IAAI;EACF,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,UAAU,GAClD,IAAI,UAAU,KAAA,GACZ,KAAK,aAAa,KAAK,KAAK;CAGlC,QAAQ,CAER;AACF;AAEA,SAAS,cAAiB,OAAiD;CACzE,OACE,UAAU,QACV,UAAU,KAAA,MACT,OAAO,UAAU,YAAY,OAAO,UAAU,eAC/C,UAAU,SACV,OAAO,MAAM,SAAS;AAE1B;;;;;;;AAQA,SAAS,eAAe,OAAyB;CAC/C,OACE,OAAO,UAAU,YACjB,UAAU,QACV,UAAU,SACV,MAAM,SAAS;AAEnB;;;ACpPA,MAAM,WAAuB;CAC3B,UAAU;CACV,eAAe,CAAC;CAChB,MAAM,CAAC;AACT;AAcA,MAAa,SAAsB,aAFhC,kBAAgD,WAAW,EAT5D,gBAAgB,OAAO,KAAK;CAC1B,OAAO,IAAI,QAAQ;AACrB,EAOsE,CAEjB"}