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.
- package/README.md +50 -12
- package/dist/{agent-tool-types-Btk9ETS-.d.ts → agent-tool-types-CzGGB-20.d.ts} +403 -115
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-UuScsJg3.d.ts → agent-tools-zR2d5uij.d.ts} +2 -2
- package/dist/agent-tools.d.ts +24 -8
- package/dist/agent-tools.js +14 -6
- package/dist/agent-tools.js.map +1 -1
- package/dist/browser/ai.d.ts +5 -3
- package/dist/browser/ai.js +86 -7
- package/dist/browser/ai.js.map +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.js +1 -1
- package/dist/browser/tanstack-ai.js +13 -1
- package/dist/browser/tanstack-ai.js.map +1 -1
- package/dist/chat/index.d.ts +31 -2
- package/dist/chat/index.js +57 -2
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +5 -179
- package/dist/chat/react.js +18 -555
- package/dist/chat/react.js.map +1 -1
- package/dist/chat/transport.d.ts +10 -0
- package/dist/chat/transport.js +2 -0
- package/dist/chat-sdk/index.d.ts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/cloudflare-BduZwmYK.js +204 -0
- package/dist/cloudflare-BduZwmYK.js.map +1 -0
- package/dist/{connector-v2M1zlZp.d.ts → connector-CkQD4MK3.d.ts} +20 -3
- package/dist/{connector-KEJnl6e5.js → connector-CptFKzRh.js} +158 -40
- package/dist/connector-CptFKzRh.js.map +1 -0
- package/dist/{handler-stateless-8hQN_kC3.js → handler-stateless-CIkKPETH.js} +20 -69
- package/dist/handler-stateless-CIkKPETH.js.map +1 -0
- package/dist/index.d.ts +21 -11
- package/dist/index.js +31 -21
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +20 -20
- package/dist/mcp/index.d.ts +35 -35
- package/dist/mcp/index.js +32 -98
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/observability/ai/index.d.ts +10 -131
- package/dist/observability/ai/index.js +209 -444
- package/dist/observability/ai/index.js.map +1 -1
- package/dist/{wire-types-CU9rLoeS.js → protocol-Dqc2MQxo.js} +2 -46
- package/dist/protocol-Dqc2MQxo.js.map +1 -0
- package/dist/react.d.ts +1 -1
- package/dist/react.js +5 -8
- package/dist/react.js.map +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/sub-routing.d.ts +18 -6
- package/dist/sub-routing.js +92 -2
- package/dist/sub-routing.js.map +1 -1
- package/dist/wire-types-CnMt6_HR.js +47 -0
- package/dist/wire-types-CnMt6_HR.js.map +1 -0
- package/dist/workflow-types.d.ts +25 -25
- package/dist/workflow-types.js.map +1 -1
- package/dist/workflows.d.ts +22 -22
- package/dist/ws-chat-transport-CIoOBbO7.js +561 -0
- package/dist/ws-chat-transport-CIoOBbO7.js.map +1 -0
- package/dist/ws-chat-transport-UNRIS2xl.d.ts +184 -0
- package/docs/adding-to-existing-project.md +4 -2
- package/docs/agent-class.md +1 -1
- package/docs/agent-tools.md +29 -0
- package/docs/browse-the-web.md +16 -1
- package/docs/chat-agents.md +3 -1
- package/docs/client-sdk.md +12 -8
- package/docs/configuration.md +7 -1
- package/docs/cross-domain-authentication.md +7 -35
- package/docs/email.md +2 -13
- package/docs/human-in-the-loop.md +15 -12
- package/docs/long-running-agents.md +11 -11
- package/docs/mcp-client.md +1 -1
- package/docs/mcp-servers.md +7 -1
- package/docs/mcp-transports.md +18 -12
- package/docs/migration-to-ai-sdk-v5.md +2 -2
- package/docs/migration-to-ai-sdk-v6.md +5 -1
- package/docs/observability.md +24 -67
- package/docs/routing.md +27 -0
- package/docs/sub-agents.md +47 -2
- package/docs/webhooks.md +109 -136
- package/docs/workflows.md +9 -1
- package/package.json +19 -10
- package/dist/cloudflare-BldFV0Pa.js +0 -117
- package/dist/cloudflare-BldFV0Pa.js.map +0 -1
- package/dist/connector-KEJnl6e5.js.map +0 -1
- package/dist/handler-stateless-8hQN_kC3.js.map +0 -1
- package/dist/wire-types-CU9rLoeS.js.map +0 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
28
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
147
|
-
const
|
|
148
|
-
if (!
|
|
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
|
-
|
|
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
|
-
###
|
|
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
|
-
|
|
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
|
-
|
|
180
|
+
### Derive Slack Identity from the Verified Body
|
|
179
181
|
|
|
180
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
252
|
-
const eventType = request.headers.get("X-Event
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
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.
|
|
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.
|
|
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
|
|
43
|
+
"@modelcontextprotocol/client": "2.0.0",
|
|
43
44
|
"@modelcontextprotocol/conformance-v2": "npm:@modelcontextprotocol/conformance@0.2.0-alpha.10",
|
|
44
|
-
"@modelcontextprotocol/sdk": "1.
|
|
45
|
-
"@modelcontextprotocol/server": "2.0.0
|
|
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
|
-
"@
|
|
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
|
-
"
|
|
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
|
|
64
|
-
"@modelcontextprotocol/sdk": "1.
|
|
65
|
-
"@modelcontextprotocol/server": "2.0.0
|
|
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"}
|