agents 0.0.0-22d140b → 0.0.0-23db655

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 (68) hide show
  1. package/README.md +255 -27
  2. package/dist/_esm-LV5FJ3HK.js +3922 -0
  3. package/dist/_esm-LV5FJ3HK.js.map +1 -0
  4. package/dist/ai-chat-agent.d.ts +11 -7
  5. package/dist/ai-chat-agent.js +169 -47
  6. package/dist/ai-chat-agent.js.map +1 -1
  7. package/dist/ai-chat-v5-migration.d.ts +152 -0
  8. package/dist/ai-chat-v5-migration.js +20 -0
  9. package/dist/ai-chat-v5-migration.js.map +1 -0
  10. package/dist/ai-react.d.ts +67 -70
  11. package/dist/ai-react.js +178 -37
  12. package/dist/ai-react.js.map +1 -1
  13. package/dist/ai-types.d.ts +37 -19
  14. package/dist/ai-types.js +7 -0
  15. package/dist/ccip-CMBYN64O.js +15 -0
  16. package/dist/ccip-CMBYN64O.js.map +1 -0
  17. package/dist/chunk-5Y6BEZDY.js +276 -0
  18. package/dist/chunk-5Y6BEZDY.js.map +1 -0
  19. package/dist/chunk-BER7KXUJ.js +18 -0
  20. package/dist/chunk-BER7KXUJ.js.map +1 -0
  21. package/dist/{chunk-4CIGD73X.js → chunk-HS7VEROK.js} +610 -101
  22. package/dist/chunk-HS7VEROK.js.map +1 -0
  23. package/dist/chunk-JJBFIGUC.js +5202 -0
  24. package/dist/chunk-JJBFIGUC.js.map +1 -0
  25. package/dist/{chunk-767EASBA.js → chunk-LL2AFX7V.js} +5 -2
  26. package/dist/chunk-LL2AFX7V.js.map +1 -0
  27. package/dist/chunk-PR4QN5HX.js +43 -0
  28. package/dist/chunk-PR4QN5HX.js.map +1 -0
  29. package/dist/{chunk-NKZZ66QY.js → chunk-QEVM4BVL.js} +5 -5
  30. package/dist/chunk-QEVM4BVL.js.map +1 -0
  31. package/dist/{chunk-E3LCYPCB.js → chunk-SKACXF37.js} +164 -21
  32. package/dist/chunk-SKACXF37.js.map +1 -0
  33. package/dist/chunk-TYAY6AU6.js +159 -0
  34. package/dist/chunk-TYAY6AU6.js.map +1 -0
  35. package/dist/chunk-UJVEAURM.js +150 -0
  36. package/dist/chunk-UJVEAURM.js.map +1 -0
  37. package/dist/client-CvaJdLQA.d.ts +5015 -0
  38. package/dist/client.d.ts +2 -2
  39. package/dist/client.js +3 -1
  40. package/dist/index.d.ts +172 -20
  41. package/dist/index.js +14 -4
  42. package/dist/mcp/client.d.ts +9 -1053
  43. package/dist/mcp/client.js +2 -1
  44. package/dist/mcp/do-oauth-client-provider.d.ts +1 -0
  45. package/dist/mcp/do-oauth-client-provider.js +2 -1
  46. package/dist/mcp/index.d.ts +64 -56
  47. package/dist/mcp/index.js +953 -637
  48. package/dist/mcp/index.js.map +1 -1
  49. package/dist/mcp/x402.d.ts +31 -0
  50. package/dist/mcp/x402.js +3195 -0
  51. package/dist/mcp/x402.js.map +1 -0
  52. package/dist/observability/index.d.ts +46 -0
  53. package/dist/observability/index.js +12 -0
  54. package/dist/observability/index.js.map +1 -0
  55. package/dist/react.d.ts +9 -5
  56. package/dist/react.js +8 -5
  57. package/dist/react.js.map +1 -1
  58. package/dist/schedule.d.ts +79 -5
  59. package/dist/schedule.js +17 -2
  60. package/dist/schedule.js.map +1 -1
  61. package/dist/secp256k1-M22GZP2U.js +2193 -0
  62. package/dist/secp256k1-M22GZP2U.js.map +1 -0
  63. package/package.json +30 -8
  64. package/src/index.ts +836 -140
  65. package/dist/chunk-4CIGD73X.js.map +0 -1
  66. package/dist/chunk-767EASBA.js.map +0 -1
  67. package/dist/chunk-E3LCYPCB.js.map +0 -1
  68. package/dist/chunk-NKZZ66QY.js.map +0 -1
@@ -1,30 +1,31 @@
1
1
  import {
2
2
  MCPClientManager
3
- } from "./chunk-E3LCYPCB.js";
3
+ } from "./chunk-SKACXF37.js";
4
4
  import {
5
5
  DurableObjectOAuthClientProvider
6
- } from "./chunk-767EASBA.js";
6
+ } from "./chunk-LL2AFX7V.js";
7
7
  import {
8
8
  camelCaseToKebabCase
9
- } from "./chunk-NKZZ66QY.js";
9
+ } from "./chunk-QEVM4BVL.js";
10
10
 
11
11
  // src/index.ts
12
12
  import { AsyncLocalStorage } from "async_hooks";
13
13
  import { parseCronExpression } from "cron-schedule";
14
14
  import { nanoid } from "nanoid";
15
+ import { EmailMessage } from "cloudflare:email";
15
16
  import {
17
+ Server,
16
18
  getServerByName,
17
- routePartykitRequest,
18
- Server
19
+ routePartykitRequest
19
20
  } from "partyserver";
20
21
  function isRPCRequest(msg) {
21
- return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "rpc" && "id" in msg && typeof msg.id === "string" && "method" in msg && typeof msg.method === "string" && "args" in msg && Array.isArray(msg.args);
22
+ return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "rpc" /* RPC */ && "id" in msg && typeof msg.id === "string" && "method" in msg && typeof msg.method === "string" && "args" in msg && Array.isArray(msg.args);
22
23
  }
23
24
  function isStateUpdateMessage(msg) {
24
- return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "cf_agent_state" && "state" in msg;
25
+ return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "cf_agent_state" /* CF_AGENT_STATE */ && "state" in msg;
25
26
  }
26
27
  var callableMetadata = /* @__PURE__ */ new Map();
27
- function unstable_callable(metadata = {}) {
28
+ function callable(metadata = {}) {
28
29
  return function callableDecorator(target, context) {
29
30
  if (!callableMetadata.has(target)) {
30
31
  callableMetadata.set(target, metadata);
@@ -32,6 +33,16 @@ function unstable_callable(metadata = {}) {
32
33
  return target;
33
34
  };
34
35
  }
36
+ var didWarnAboutUnstableCallable = false;
37
+ var unstable_callable = (metadata = {}) => {
38
+ if (!didWarnAboutUnstableCallable) {
39
+ didWarnAboutUnstableCallable = true;
40
+ console.warn(
41
+ "unstable_callable is deprecated, use callable instead. unstable_callable will be removed in the next major version."
42
+ );
43
+ }
44
+ callable(metadata);
45
+ };
35
46
  function getNextCronTime(cron) {
36
47
  const interval = parseCronExpression(cron);
37
48
  return interval.getNextDate();
@@ -46,12 +57,24 @@ function getCurrentAgent() {
46
57
  return {
47
58
  agent: void 0,
48
59
  connection: void 0,
49
- request: void 0
60
+ request: void 0,
61
+ email: void 0
50
62
  };
51
63
  }
52
64
  return store;
53
65
  }
54
- var Agent = class extends Server {
66
+ function withAgentContext(method) {
67
+ return function(...args) {
68
+ const { connection, request, email, agent } = getCurrentAgent();
69
+ if (agent === this) {
70
+ return method.apply(this, args);
71
+ }
72
+ return agentContext.run({ agent: this, connection, request, email }, () => {
73
+ return method.apply(this, args);
74
+ });
75
+ };
76
+ }
77
+ var _Agent = class _Agent extends Server {
55
78
  constructor(ctx, env) {
56
79
  super(ctx, env);
57
80
  this._state = DEFAULT_STATE;
@@ -62,6 +85,11 @@ var Agent = class extends Server {
62
85
  * Override to provide default state values
63
86
  */
64
87
  this.initialState = DEFAULT_STATE;
88
+ /**
89
+ * The observability implementation to use for the Agent
90
+ */
91
+ this.observability = genericObservability;
92
+ this._flushingQueue = false;
65
93
  /**
66
94
  * Method called when an alarm fires.
67
95
  * Executes any scheduled tasks that are due.
@@ -75,42 +103,74 @@ var Agent = class extends Server {
75
103
  const result = this.sql`
76
104
  SELECT * FROM cf_agents_schedules WHERE time <= ${now}
77
105
  `;
78
- for (const row of result || []) {
79
- const callback = this[row.callback];
80
- if (!callback) {
81
- console.error(`callback ${row.callback} not found`);
82
- continue;
83
- }
84
- await agentContext.run(
85
- { agent: this, connection: void 0, request: void 0 },
86
- async () => {
87
- try {
88
- await callback.bind(this)(JSON.parse(row.payload), row);
89
- } catch (e) {
90
- console.error(`error executing callback "${row.callback}"`, e);
91
- }
106
+ if (result && Array.isArray(result)) {
107
+ for (const row of result) {
108
+ const callback = this[row.callback];
109
+ if (!callback) {
110
+ console.error(`callback ${row.callback} not found`);
111
+ continue;
92
112
  }
93
- );
94
- if (row.type === "cron") {
95
- const nextExecutionTime = getNextCronTime(row.cron);
96
- const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1e3);
97
- this.sql`
113
+ await agentContext.run(
114
+ {
115
+ agent: this,
116
+ connection: void 0,
117
+ request: void 0,
118
+ email: void 0
119
+ },
120
+ async () => {
121
+ try {
122
+ this.observability?.emit(
123
+ {
124
+ displayMessage: `Schedule ${row.id} executed`,
125
+ id: nanoid(),
126
+ payload: {
127
+ callback: row.callback,
128
+ id: row.id
129
+ },
130
+ timestamp: Date.now(),
131
+ type: "schedule:execute"
132
+ },
133
+ this.ctx
134
+ );
135
+ await callback.bind(this)(JSON.parse(row.payload), row);
136
+ } catch (e) {
137
+ console.error(`error executing callback "${row.callback}"`, e);
138
+ }
139
+ }
140
+ );
141
+ if (row.type === "cron") {
142
+ const nextExecutionTime = getNextCronTime(row.cron);
143
+ const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1e3);
144
+ this.sql`
98
145
  UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}
99
146
  `;
100
- } else {
101
- this.sql`
147
+ } else {
148
+ this.sql`
102
149
  DELETE FROM cf_agents_schedules WHERE id = ${row.id}
103
150
  `;
151
+ }
104
152
  }
105
153
  }
106
154
  await this._scheduleNextAlarm();
107
155
  };
156
+ if (!wrappedClasses.has(this.constructor)) {
157
+ this._autoWrapCustomMethods();
158
+ wrappedClasses.add(this.constructor);
159
+ }
108
160
  this.sql`
109
161
  CREATE TABLE IF NOT EXISTS cf_agents_state (
110
162
  id TEXT PRIMARY KEY NOT NULL,
111
163
  state TEXT
112
164
  )
113
165
  `;
166
+ this.sql`
167
+ CREATE TABLE IF NOT EXISTS cf_agents_queues (
168
+ id TEXT PRIMARY KEY NOT NULL,
169
+ payload TEXT,
170
+ callback TEXT,
171
+ created_at INTEGER DEFAULT (unixepoch())
172
+ )
173
+ `;
114
174
  void this.ctx.blockConcurrencyWhile(async () => {
115
175
  return this._tryCatch(async () => {
116
176
  this.sql`
@@ -142,14 +202,14 @@ var Agent = class extends Server {
142
202
  const _onRequest = this.onRequest.bind(this);
143
203
  this.onRequest = (request) => {
144
204
  return agentContext.run(
145
- { agent: this, connection: void 0, request },
205
+ { agent: this, connection: void 0, request, email: void 0 },
146
206
  async () => {
147
207
  if (this.mcp.isCallbackRequest(request)) {
148
208
  await this.mcp.handleCallbackRequest(request);
149
209
  this.broadcast(
150
210
  JSON.stringify({
151
211
  mcp: this.getMcpServers(),
152
- type: "cf_agent_mcp_servers"
212
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
153
213
  })
154
214
  );
155
215
  return new Response("<script>window.close();</script>", {
@@ -164,7 +224,7 @@ var Agent = class extends Server {
164
224
  const _onMessage = this.onMessage.bind(this);
165
225
  this.onMessage = async (connection, message) => {
166
226
  return agentContext.run(
167
- { agent: this, connection, request: void 0 },
227
+ { agent: this, connection, request: void 0, email: void 0 },
168
228
  async () => {
169
229
  if (typeof message !== "string") {
170
230
  return this._tryCatch(() => _onMessage(connection, message));
@@ -196,12 +256,25 @@ var Agent = class extends Server {
196
256
  return;
197
257
  }
198
258
  const result = await methodFn.apply(this, args);
259
+ this.observability?.emit(
260
+ {
261
+ displayMessage: `RPC call to ${method}`,
262
+ id: nanoid(),
263
+ payload: {
264
+ method,
265
+ streaming: metadata?.streaming
266
+ },
267
+ timestamp: Date.now(),
268
+ type: "rpc"
269
+ },
270
+ this.ctx
271
+ );
199
272
  const response = {
200
273
  done: true,
201
274
  id,
202
275
  result,
203
276
  success: true,
204
- type: "rpc"
277
+ type: "rpc" /* RPC */
205
278
  };
206
279
  connection.send(JSON.stringify(response));
207
280
  } catch (e) {
@@ -209,7 +282,7 @@ var Agent = class extends Server {
209
282
  error: e instanceof Error ? e.message : "Unknown error occurred",
210
283
  id: parsed.id,
211
284
  success: false,
212
- type: "rpc"
285
+ type: "rpc" /* RPC */
213
286
  };
214
287
  connection.send(JSON.stringify(response));
215
288
  console.error("RPC error:", e);
@@ -223,58 +296,92 @@ var Agent = class extends Server {
223
296
  const _onConnect = this.onConnect.bind(this);
224
297
  this.onConnect = (connection, ctx2) => {
225
298
  return agentContext.run(
226
- { agent: this, connection, request: ctx2.request },
227
- async () => {
228
- setTimeout(() => {
229
- if (this.state) {
230
- connection.send(
231
- JSON.stringify({
232
- state: this.state,
233
- type: "cf_agent_state"
234
- })
235
- );
236
- }
299
+ { agent: this, connection, request: ctx2.request, email: void 0 },
300
+ () => {
301
+ if (this.state) {
237
302
  connection.send(
238
303
  JSON.stringify({
239
- mcp: this.getMcpServers(),
240
- type: "cf_agent_mcp_servers"
304
+ state: this.state,
305
+ type: "cf_agent_state" /* CF_AGENT_STATE */
241
306
  })
242
307
  );
243
- return this._tryCatch(() => _onConnect(connection, ctx2));
244
- }, 20);
308
+ }
309
+ connection.send(
310
+ JSON.stringify({
311
+ mcp: this.getMcpServers(),
312
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
313
+ })
314
+ );
315
+ this.observability?.emit(
316
+ {
317
+ displayMessage: "Connection established",
318
+ id: nanoid(),
319
+ payload: {
320
+ connectionId: connection.id
321
+ },
322
+ timestamp: Date.now(),
323
+ type: "connect"
324
+ },
325
+ this.ctx
326
+ );
327
+ return this._tryCatch(() => _onConnect(connection, ctx2));
245
328
  }
246
329
  );
247
330
  };
248
331
  const _onStart = this.onStart.bind(this);
249
- this.onStart = async () => {
332
+ this.onStart = async (props) => {
250
333
  return agentContext.run(
251
- { agent: this, connection: void 0, request: void 0 },
334
+ {
335
+ agent: this,
336
+ connection: void 0,
337
+ request: void 0,
338
+ email: void 0
339
+ },
252
340
  async () => {
253
- const servers = this.sql`
341
+ await this._tryCatch(() => {
342
+ const servers = this.sql`
254
343
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
255
344
  `;
256
- Promise.allSettled(
257
- servers.map((server) => {
258
- return this._connectToMcpServerInternal(
259
- server.name,
260
- server.server_url,
261
- server.callback_url,
262
- server.server_options ? JSON.parse(server.server_options) : void 0,
263
- {
264
- id: server.id,
265
- oauthClientId: server.client_id ?? void 0
266
- }
267
- );
268
- })
269
- ).then((_results) => {
270
345
  this.broadcast(
271
346
  JSON.stringify({
272
347
  mcp: this.getMcpServers(),
273
- type: "cf_agent_mcp_servers"
348
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
274
349
  })
275
350
  );
351
+ if (servers && Array.isArray(servers) && servers.length > 0) {
352
+ servers.forEach((server) => {
353
+ this._connectToMcpServerInternal(
354
+ server.name,
355
+ server.server_url,
356
+ server.callback_url,
357
+ server.server_options ? JSON.parse(server.server_options) : void 0,
358
+ {
359
+ id: server.id,
360
+ oauthClientId: server.client_id ?? void 0
361
+ }
362
+ ).then(() => {
363
+ this.broadcast(
364
+ JSON.stringify({
365
+ mcp: this.getMcpServers(),
366
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
367
+ })
368
+ );
369
+ }).catch((error) => {
370
+ console.error(
371
+ `Error connecting to MCP server: ${server.name} (${server.server_url})`,
372
+ error
373
+ );
374
+ this.broadcast(
375
+ JSON.stringify({
376
+ mcp: this.getMcpServers(),
377
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
378
+ })
379
+ );
380
+ });
381
+ });
382
+ }
383
+ return _onStart(props);
276
384
  });
277
- await this._tryCatch(() => _onStart());
278
385
  }
279
386
  );
280
387
  };
@@ -337,15 +444,25 @@ var Agent = class extends Server {
337
444
  this.broadcast(
338
445
  JSON.stringify({
339
446
  state,
340
- type: "cf_agent_state"
447
+ type: "cf_agent_state" /* CF_AGENT_STATE */
341
448
  }),
342
449
  source !== "server" ? [source.id] : []
343
450
  );
344
451
  return this._tryCatch(() => {
345
- const { connection, request } = agentContext.getStore() || {};
452
+ const { connection, request, email } = agentContext.getStore() || {};
346
453
  return agentContext.run(
347
- { agent: this, connection, request },
454
+ { agent: this, connection, request, email },
348
455
  async () => {
456
+ this.observability?.emit(
457
+ {
458
+ displayMessage: "State updated",
459
+ id: nanoid(),
460
+ payload: {},
461
+ timestamp: Date.now(),
462
+ type: "state:update"
463
+ },
464
+ this.ctx
465
+ );
349
466
  return this.onStateUpdate(state, source);
350
467
  }
351
468
  );
@@ -367,18 +484,67 @@ var Agent = class extends Server {
367
484
  onStateUpdate(state, source) {
368
485
  }
369
486
  /**
370
- * Called when the Agent receives an email
487
+ * Called when the Agent receives an email via routeAgentEmail()
488
+ * Override this method to handle incoming emails
371
489
  * @param email Email message to process
372
490
  */
373
- // biome-ignore lint/correctness/noUnusedFunctionParameters: overridden later
374
- onEmail(email) {
491
+ async _onEmail(email) {
375
492
  return agentContext.run(
376
- { agent: this, connection: void 0, request: void 0 },
493
+ { agent: this, connection: void 0, request: void 0, email },
377
494
  async () => {
378
- console.error("onEmail not implemented");
495
+ if ("onEmail" in this && typeof this.onEmail === "function") {
496
+ return this._tryCatch(
497
+ () => this.onEmail(email)
498
+ );
499
+ } else {
500
+ console.log("Received email from:", email.from, "to:", email.to);
501
+ console.log("Subject:", email.headers.get("subject"));
502
+ console.log(
503
+ "Implement onEmail(email: AgentEmail): Promise<void> in your agent to process emails"
504
+ );
505
+ }
379
506
  }
380
507
  );
381
508
  }
509
+ /**
510
+ * Reply to an email
511
+ * @param email The email to reply to
512
+ * @param options Options for the reply
513
+ * @returns void
514
+ */
515
+ async replyToEmail(email, options) {
516
+ return this._tryCatch(async () => {
517
+ const agentName = camelCaseToKebabCase(this._ParentClass.name);
518
+ const agentId = this.name;
519
+ const { createMimeMessage } = await import("mimetext");
520
+ const msg = createMimeMessage();
521
+ msg.setSender({ addr: email.to, name: options.fromName });
522
+ msg.setRecipient(email.from);
523
+ msg.setSubject(
524
+ options.subject || `Re: ${email.headers.get("subject")}` || "No subject"
525
+ );
526
+ msg.addMessage({
527
+ contentType: options.contentType || "text/plain",
528
+ data: options.body
529
+ });
530
+ const domain = email.from.split("@")[1];
531
+ const messageId = `<${agentId}@${domain}>`;
532
+ msg.setHeader("In-Reply-To", email.headers.get("Message-ID"));
533
+ msg.setHeader("Message-ID", messageId);
534
+ msg.setHeader("X-Agent-Name", agentName);
535
+ msg.setHeader("X-Agent-ID", agentId);
536
+ if (options.headers) {
537
+ for (const [key, value] of Object.entries(options.headers)) {
538
+ msg.setHeader(key, value);
539
+ }
540
+ }
541
+ await email.reply({
542
+ from: email.to,
543
+ raw: msg.asRaw(),
544
+ to: email.from
545
+ });
546
+ });
547
+ }
382
548
  async _tryCatch(fn) {
383
549
  try {
384
550
  return await fn();
@@ -386,6 +552,49 @@ var Agent = class extends Server {
386
552
  throw this.onError(e);
387
553
  }
388
554
  }
555
+ /**
556
+ * Automatically wrap custom methods with agent context
557
+ * This ensures getCurrentAgent() works in all custom methods without decorators
558
+ */
559
+ _autoWrapCustomMethods() {
560
+ const basePrototypes = [_Agent.prototype, Server.prototype];
561
+ const baseMethods = /* @__PURE__ */ new Set();
562
+ for (const baseProto of basePrototypes) {
563
+ let proto2 = baseProto;
564
+ while (proto2 && proto2 !== Object.prototype) {
565
+ const methodNames = Object.getOwnPropertyNames(proto2);
566
+ for (const methodName of methodNames) {
567
+ baseMethods.add(methodName);
568
+ }
569
+ proto2 = Object.getPrototypeOf(proto2);
570
+ }
571
+ }
572
+ let proto = Object.getPrototypeOf(this);
573
+ let depth = 0;
574
+ while (proto && proto !== Object.prototype && depth < 10) {
575
+ const methodNames = Object.getOwnPropertyNames(proto);
576
+ for (const methodName of methodNames) {
577
+ const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
578
+ if (baseMethods.has(methodName) || methodName.startsWith("_") || !descriptor || !!descriptor.get || typeof descriptor.value !== "function") {
579
+ continue;
580
+ }
581
+ const wrappedFunction = withAgentContext(
582
+ // biome-ignore lint/suspicious/noExplicitAny: I can't typescript
583
+ this[methodName]
584
+ // biome-ignore lint/suspicious/noExplicitAny: I can't typescript
585
+ );
586
+ if (this._isCallable(methodName)) {
587
+ callableMetadata.set(
588
+ wrappedFunction,
589
+ callableMetadata.get(this[methodName])
590
+ );
591
+ }
592
+ this.constructor.prototype[methodName] = wrappedFunction;
593
+ }
594
+ proto = Object.getPrototypeOf(proto);
595
+ depth++;
596
+ }
597
+ }
389
598
  onError(connectionOrError, error) {
390
599
  let theError;
391
600
  if (connectionOrError && error) {
@@ -411,6 +620,108 @@ var Agent = class extends Server {
411
620
  render() {
412
621
  throw new Error("Not implemented");
413
622
  }
623
+ /**
624
+ * Queue a task to be executed in the future
625
+ * @param payload Payload to pass to the callback
626
+ * @param callback Name of the method to call
627
+ * @returns The ID of the queued task
628
+ */
629
+ async queue(callback, payload) {
630
+ const id = nanoid(9);
631
+ if (typeof callback !== "string") {
632
+ throw new Error("Callback must be a string");
633
+ }
634
+ if (typeof this[callback] !== "function") {
635
+ throw new Error(`this.${callback} is not a function`);
636
+ }
637
+ this.sql`
638
+ INSERT OR REPLACE INTO cf_agents_queues (id, payload, callback)
639
+ VALUES (${id}, ${JSON.stringify(payload)}, ${callback})
640
+ `;
641
+ void this._flushQueue().catch((e) => {
642
+ console.error("Error flushing queue:", e);
643
+ });
644
+ return id;
645
+ }
646
+ async _flushQueue() {
647
+ if (this._flushingQueue) {
648
+ return;
649
+ }
650
+ this._flushingQueue = true;
651
+ while (true) {
652
+ const result = this.sql`
653
+ SELECT * FROM cf_agents_queues
654
+ ORDER BY created_at ASC
655
+ `;
656
+ if (!result || result.length === 0) {
657
+ break;
658
+ }
659
+ for (const row of result || []) {
660
+ const callback = this[row.callback];
661
+ if (!callback) {
662
+ console.error(`callback ${row.callback} not found`);
663
+ continue;
664
+ }
665
+ const { connection, request, email } = agentContext.getStore() || {};
666
+ await agentContext.run(
667
+ {
668
+ agent: this,
669
+ connection,
670
+ request,
671
+ email
672
+ },
673
+ async () => {
674
+ await callback.bind(this)(JSON.parse(row.payload), row);
675
+ await this.dequeue(row.id);
676
+ }
677
+ );
678
+ }
679
+ }
680
+ this._flushingQueue = false;
681
+ }
682
+ /**
683
+ * Dequeue a task by ID
684
+ * @param id ID of the task to dequeue
685
+ */
686
+ async dequeue(id) {
687
+ this.sql`DELETE FROM cf_agents_queues WHERE id = ${id}`;
688
+ }
689
+ /**
690
+ * Dequeue all tasks
691
+ */
692
+ async dequeueAll() {
693
+ this.sql`DELETE FROM cf_agents_queues`;
694
+ }
695
+ /**
696
+ * Dequeue all tasks by callback
697
+ * @param callback Name of the callback to dequeue
698
+ */
699
+ async dequeueAllByCallback(callback) {
700
+ this.sql`DELETE FROM cf_agents_queues WHERE callback = ${callback}`;
701
+ }
702
+ /**
703
+ * Get a queued task by ID
704
+ * @param id ID of the task to get
705
+ * @returns The task or undefined if not found
706
+ */
707
+ async getQueue(id) {
708
+ const result = this.sql`
709
+ SELECT * FROM cf_agents_queues WHERE id = ${id}
710
+ `;
711
+ return result ? { ...result[0], payload: JSON.parse(result[0].payload) } : void 0;
712
+ }
713
+ /**
714
+ * Get all queues by key and value
715
+ * @param key Key to filter by
716
+ * @param value Value to filter by
717
+ * @returns Array of matching QueueItem objects
718
+ */
719
+ async getQueues(key, value) {
720
+ const result = this.sql`
721
+ SELECT * FROM cf_agents_queues
722
+ `;
723
+ return result.filter((row) => JSON.parse(row.payload)[key] === value);
724
+ }
414
725
  /**
415
726
  * Schedule a task to be executed in the future
416
727
  * @template T Type of the payload data
@@ -421,6 +732,19 @@ var Agent = class extends Server {
421
732
  */
422
733
  async schedule(when, callback, payload) {
423
734
  const id = nanoid(9);
735
+ const emitScheduleCreate = (schedule) => this.observability?.emit(
736
+ {
737
+ displayMessage: `Schedule ${schedule.id} created`,
738
+ id: nanoid(),
739
+ payload: {
740
+ callback,
741
+ id
742
+ },
743
+ timestamp: Date.now(),
744
+ type: "schedule:create"
745
+ },
746
+ this.ctx
747
+ );
424
748
  if (typeof callback !== "string") {
425
749
  throw new Error("Callback must be a string");
426
750
  }
@@ -436,13 +760,15 @@ var Agent = class extends Server {
436
760
  )}, 'scheduled', ${timestamp})
437
761
  `;
438
762
  await this._scheduleNextAlarm();
439
- return {
763
+ const schedule = {
440
764
  callback,
441
765
  id,
442
766
  payload,
443
767
  time: timestamp,
444
768
  type: "scheduled"
445
769
  };
770
+ emitScheduleCreate(schedule);
771
+ return schedule;
446
772
  }
447
773
  if (typeof when === "number") {
448
774
  const time = new Date(Date.now() + when * 1e3);
@@ -454,7 +780,7 @@ var Agent = class extends Server {
454
780
  )}, 'delayed', ${when}, ${timestamp})
455
781
  `;
456
782
  await this._scheduleNextAlarm();
457
- return {
783
+ const schedule = {
458
784
  callback,
459
785
  delayInSeconds: when,
460
786
  id,
@@ -462,6 +788,8 @@ var Agent = class extends Server {
462
788
  time: timestamp,
463
789
  type: "delayed"
464
790
  };
791
+ emitScheduleCreate(schedule);
792
+ return schedule;
465
793
  }
466
794
  if (typeof when === "string") {
467
795
  const nextExecutionTime = getNextCronTime(when);
@@ -473,7 +801,7 @@ var Agent = class extends Server {
473
801
  )}, 'cron', ${when}, ${timestamp})
474
802
  `;
475
803
  await this._scheduleNextAlarm();
476
- return {
804
+ const schedule = {
477
805
  callback,
478
806
  cron: when,
479
807
  id,
@@ -481,6 +809,8 @@ var Agent = class extends Server {
481
809
  time: timestamp,
482
810
  type: "cron"
483
811
  };
812
+ emitScheduleCreate(schedule);
813
+ return schedule;
484
814
  }
485
815
  throw new Error("Invalid schedule type");
486
816
  }
@@ -538,15 +868,31 @@ var Agent = class extends Server {
538
868
  * @returns true if the task was cancelled, false otherwise
539
869
  */
540
870
  async cancelSchedule(id) {
871
+ const schedule = await this.getSchedule(id);
872
+ if (schedule) {
873
+ this.observability?.emit(
874
+ {
875
+ displayMessage: `Schedule ${id} cancelled`,
876
+ id: nanoid(),
877
+ payload: {
878
+ callback: schedule.callback,
879
+ id: schedule.id
880
+ },
881
+ timestamp: Date.now(),
882
+ type: "schedule:cancel"
883
+ },
884
+ this.ctx
885
+ );
886
+ }
541
887
  this.sql`DELETE FROM cf_agents_schedules WHERE id = ${id}`;
542
888
  await this._scheduleNextAlarm();
543
889
  return true;
544
890
  }
545
891
  async _scheduleNextAlarm() {
546
892
  const result = this.sql`
547
- SELECT time FROM cf_agents_schedules
893
+ SELECT time FROM cf_agents_schedules
548
894
  WHERE time > ${Math.floor(Date.now() / 1e3)}
549
- ORDER BY time ASC
895
+ ORDER BY time ASC
550
896
  LIMIT 1
551
897
  `;
552
898
  if (!result) return;
@@ -562,9 +908,20 @@ var Agent = class extends Server {
562
908
  this.sql`DROP TABLE IF EXISTS cf_agents_state`;
563
909
  this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;
564
910
  this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
911
+ this.sql`DROP TABLE IF EXISTS cf_agents_queues`;
565
912
  await this.ctx.storage.deleteAlarm();
566
913
  await this.ctx.storage.deleteAll();
567
914
  this.ctx.abort("destroyed");
915
+ this.observability?.emit(
916
+ {
917
+ displayMessage: "Agent destroyed",
918
+ id: nanoid(),
919
+ payload: {},
920
+ timestamp: Date.now(),
921
+ type: "destroy"
922
+ },
923
+ this.ctx
924
+ );
568
925
  }
569
926
  /**
570
927
  * Get all methods marked as callable on this Agent
@@ -606,7 +963,7 @@ var Agent = class extends Server {
606
963
  this.broadcast(
607
964
  JSON.stringify({
608
965
  mcp: this.getMcpServers(),
609
- type: "cf_agent_mcp_servers"
966
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
610
967
  })
611
968
  );
612
969
  return result;
@@ -659,7 +1016,7 @@ var Agent = class extends Server {
659
1016
  this.broadcast(
660
1017
  JSON.stringify({
661
1018
  mcp: this.getMcpServers(),
662
- type: "cf_agent_mcp_servers"
1019
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
663
1020
  })
664
1021
  );
665
1022
  }
@@ -673,17 +1030,19 @@ var Agent = class extends Server {
673
1030
  const servers = this.sql`
674
1031
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
675
1032
  `;
676
- for (const server of servers) {
677
- const serverConn = this.mcp.mcpConnections[server.id];
678
- mcpState.servers[server.id] = {
679
- auth_url: server.auth_url,
680
- capabilities: serverConn?.serverCapabilities ?? null,
681
- instructions: serverConn?.instructions ?? null,
682
- name: server.name,
683
- server_url: server.server_url,
684
- // mark as "authenticating" because the server isn't automatically connected, so it's pending authenticating
685
- state: serverConn?.connectionState ?? "authenticating"
686
- };
1033
+ if (servers && Array.isArray(servers) && servers.length > 0) {
1034
+ for (const server of servers) {
1035
+ const serverConn = this.mcp.mcpConnections[server.id];
1036
+ mcpState.servers[server.id] = {
1037
+ auth_url: server.auth_url,
1038
+ capabilities: serverConn?.serverCapabilities ?? null,
1039
+ instructions: serverConn?.instructions ?? null,
1040
+ name: server.name,
1041
+ server_url: server.server_url,
1042
+ // mark as "authenticating" because the server isn't automatically connected, so it's pending authenticating
1043
+ state: serverConn?.connectionState ?? "authenticating"
1044
+ };
1045
+ }
687
1046
  }
688
1047
  return mcpState;
689
1048
  }
@@ -691,11 +1050,13 @@ var Agent = class extends Server {
691
1050
  /**
692
1051
  * Agent configuration options
693
1052
  */
694
- Agent.options = {
1053
+ _Agent.options = {
695
1054
  /** Whether the Agent should hibernate when inactive */
696
1055
  hibernate: true
697
1056
  // default to hibernate
698
1057
  };
1058
+ var Agent = _Agent;
1059
+ var wrappedClasses = /* @__PURE__ */ new Set();
699
1060
  async function routeAgentRequest(request, env, options) {
700
1061
  const corsHeaders = options?.cors === true ? {
701
1062
  "Access-Control-Allow-Credentials": "true",
@@ -731,7 +1092,126 @@ async function routeAgentRequest(request, env, options) {
731
1092
  }
732
1093
  return response;
733
1094
  }
734
- async function routeAgentEmail(_email, _env, _options) {
1095
+ function createHeaderBasedEmailResolver() {
1096
+ return async (email, _env) => {
1097
+ const messageId = email.headers.get("message-id");
1098
+ if (messageId) {
1099
+ const messageIdMatch = messageId.match(/<([^@]+)@([^>]+)>/);
1100
+ if (messageIdMatch) {
1101
+ const [, agentId2, domain] = messageIdMatch;
1102
+ const agentName2 = domain.split(".")[0];
1103
+ return { agentName: agentName2, agentId: agentId2 };
1104
+ }
1105
+ }
1106
+ const references = email.headers.get("references");
1107
+ if (references) {
1108
+ const referencesMatch = references.match(
1109
+ /<([A-Za-z0-9+/]{43}=)@([^>]+)>/
1110
+ );
1111
+ if (referencesMatch) {
1112
+ const [, base64Id, domain] = referencesMatch;
1113
+ const agentId2 = Buffer.from(base64Id, "base64").toString("hex");
1114
+ const agentName2 = domain.split(".")[0];
1115
+ return { agentName: agentName2, agentId: agentId2 };
1116
+ }
1117
+ }
1118
+ const agentName = email.headers.get("x-agent-name");
1119
+ const agentId = email.headers.get("x-agent-id");
1120
+ if (agentName && agentId) {
1121
+ return { agentName, agentId };
1122
+ }
1123
+ return null;
1124
+ };
1125
+ }
1126
+ function createAddressBasedEmailResolver(defaultAgentName) {
1127
+ return async (email, _env) => {
1128
+ const emailMatch = email.to.match(/^([^+@]+)(?:\+([^@]+))?@(.+)$/);
1129
+ if (!emailMatch) {
1130
+ return null;
1131
+ }
1132
+ const [, localPart, subAddress] = emailMatch;
1133
+ if (subAddress) {
1134
+ return {
1135
+ agentName: localPart,
1136
+ agentId: subAddress
1137
+ };
1138
+ }
1139
+ return {
1140
+ agentName: defaultAgentName,
1141
+ agentId: localPart
1142
+ };
1143
+ };
1144
+ }
1145
+ function createCatchAllEmailResolver(agentName, agentId) {
1146
+ return async () => ({ agentName, agentId });
1147
+ }
1148
+ var agentMapCache = /* @__PURE__ */ new WeakMap();
1149
+ async function routeAgentEmail(email, env, options) {
1150
+ const routingInfo = await options.resolver(email, env);
1151
+ if (!routingInfo) {
1152
+ console.warn("No routing information found for email, dropping message");
1153
+ return;
1154
+ }
1155
+ if (!agentMapCache.has(env)) {
1156
+ const map = {};
1157
+ for (const [key, value] of Object.entries(env)) {
1158
+ if (value && typeof value === "object" && "idFromName" in value && typeof value.idFromName === "function") {
1159
+ map[key] = value;
1160
+ map[camelCaseToKebabCase(key)] = value;
1161
+ }
1162
+ }
1163
+ agentMapCache.set(env, map);
1164
+ }
1165
+ const agentMap = agentMapCache.get(env);
1166
+ const namespace = agentMap[routingInfo.agentName];
1167
+ if (!namespace) {
1168
+ const availableAgents = Object.keys(agentMap).filter((key) => !key.includes("-")).join(", ");
1169
+ throw new Error(
1170
+ `Agent namespace '${routingInfo.agentName}' not found in environment. Available agents: ${availableAgents}`
1171
+ );
1172
+ }
1173
+ const agent = await getAgentByName(
1174
+ namespace,
1175
+ routingInfo.agentId
1176
+ );
1177
+ const serialisableEmail = {
1178
+ getRaw: async () => {
1179
+ const reader = email.raw.getReader();
1180
+ const chunks = [];
1181
+ let done = false;
1182
+ while (!done) {
1183
+ const { value, done: readerDone } = await reader.read();
1184
+ done = readerDone;
1185
+ if (value) {
1186
+ chunks.push(value);
1187
+ }
1188
+ }
1189
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
1190
+ const combined = new Uint8Array(totalLength);
1191
+ let offset = 0;
1192
+ for (const chunk of chunks) {
1193
+ combined.set(chunk, offset);
1194
+ offset += chunk.length;
1195
+ }
1196
+ return combined;
1197
+ },
1198
+ headers: email.headers,
1199
+ rawSize: email.rawSize,
1200
+ setReject: (reason) => {
1201
+ email.setReject(reason);
1202
+ },
1203
+ forward: (rcptTo, headers) => {
1204
+ return email.forward(rcptTo, headers);
1205
+ },
1206
+ reply: (options2) => {
1207
+ return email.reply(
1208
+ new EmailMessage(options2.from, options2.to, options2.raw)
1209
+ );
1210
+ },
1211
+ from: email.from,
1212
+ to: email.to
1213
+ };
1214
+ await agent._onEmail(serialisableEmail);
735
1215
  }
736
1216
  async function getAgentByName(namespace, name, options) {
737
1217
  return getServerByName(namespace, name, options);
@@ -755,7 +1235,7 @@ var StreamingResponse = class {
755
1235
  id: this._id,
756
1236
  result: chunk,
757
1237
  success: true,
758
- type: "rpc"
1238
+ type: "rpc" /* RPC */
759
1239
  };
760
1240
  this._connection.send(JSON.stringify(response));
761
1241
  }
@@ -773,19 +1253,48 @@ var StreamingResponse = class {
773
1253
  id: this._id,
774
1254
  result: finalChunk,
775
1255
  success: true,
776
- type: "rpc"
1256
+ type: "rpc" /* RPC */
777
1257
  };
778
1258
  this._connection.send(JSON.stringify(response));
779
1259
  }
780
1260
  };
781
1261
 
1262
+ // src/observability/index.ts
1263
+ var genericObservability = {
1264
+ emit(event) {
1265
+ if (isLocalMode()) {
1266
+ console.log(event.displayMessage);
1267
+ return;
1268
+ }
1269
+ console.log(event);
1270
+ }
1271
+ };
1272
+ var localMode = false;
1273
+ function isLocalMode() {
1274
+ if (localMode) {
1275
+ return true;
1276
+ }
1277
+ const { request } = getCurrentAgent();
1278
+ if (!request) {
1279
+ return false;
1280
+ }
1281
+ const url = new URL(request.url);
1282
+ localMode = url.hostname === "localhost";
1283
+ return localMode;
1284
+ }
1285
+
782
1286
  export {
1287
+ genericObservability,
1288
+ callable,
783
1289
  unstable_callable,
784
1290
  getCurrentAgent,
785
1291
  Agent,
786
1292
  routeAgentRequest,
1293
+ createHeaderBasedEmailResolver,
1294
+ createAddressBasedEmailResolver,
1295
+ createCatchAllEmailResolver,
787
1296
  routeAgentEmail,
788
1297
  getAgentByName,
789
1298
  StreamingResponse
790
1299
  };
791
- //# sourceMappingURL=chunk-4CIGD73X.js.map
1300
+ //# sourceMappingURL=chunk-HS7VEROK.js.map