agents 0.0.0-d40512c → 0.0.0-d72c6a2

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 (50) hide show
  1. package/README.md +234 -6
  2. package/dist/ai-chat-agent.d.ts +12 -9
  3. package/dist/ai-chat-agent.js +150 -59
  4. package/dist/ai-chat-agent.js.map +1 -1
  5. package/dist/ai-chat-v5-migration.d.ts +152 -0
  6. package/dist/ai-chat-v5-migration.js +19 -0
  7. package/dist/ai-chat-v5-migration.js.map +1 -0
  8. package/dist/ai-react.d.ts +62 -71
  9. package/dist/ai-react.js +144 -37
  10. package/dist/ai-react.js.map +1 -1
  11. package/dist/ai-types.d.ts +36 -19
  12. package/dist/ai-types.js +6 -0
  13. package/dist/chunk-AVYJQSLW.js +17 -0
  14. package/dist/chunk-AVYJQSLW.js.map +1 -0
  15. package/dist/{chunk-PVQZBKN7.js → chunk-LL2AFX7V.js} +5 -2
  16. package/dist/chunk-LL2AFX7V.js.map +1 -0
  17. package/dist/{chunk-4RBEYCWK.js → chunk-MH46VMM4.js} +163 -20
  18. package/dist/chunk-MH46VMM4.js.map +1 -0
  19. package/dist/{chunk-KUH345EY.js → chunk-QEVM4BVL.js} +5 -5
  20. package/dist/chunk-QEVM4BVL.js.map +1 -0
  21. package/dist/chunk-UJVEAURM.js +150 -0
  22. package/dist/chunk-UJVEAURM.js.map +1 -0
  23. package/dist/{chunk-LU2RSO54.js → chunk-YDUDMOL6.js} +515 -129
  24. package/dist/chunk-YDUDMOL6.js.map +1 -0
  25. package/dist/client-CvaJdLQA.d.ts +5015 -0
  26. package/dist/client.js +2 -1
  27. package/dist/index.d.ts +557 -24
  28. package/dist/index.js +13 -4
  29. package/dist/mcp/client.d.ts +9 -1053
  30. package/dist/mcp/client.js +1 -1
  31. package/dist/mcp/do-oauth-client-provider.d.ts +1 -0
  32. package/dist/mcp/do-oauth-client-provider.js +1 -1
  33. package/dist/mcp/index.d.ts +68 -55
  34. package/dist/mcp/index.js +854 -608
  35. package/dist/mcp/index.js.map +1 -1
  36. package/dist/observability/index.d.ts +46 -12
  37. package/dist/observability/index.js +5 -4
  38. package/dist/react.d.ts +7 -3
  39. package/dist/react.js +7 -5
  40. package/dist/react.js.map +1 -1
  41. package/dist/schedule.d.ts +83 -9
  42. package/dist/schedule.js +15 -2
  43. package/dist/schedule.js.map +1 -1
  44. package/package.json +19 -8
  45. package/src/index.ts +731 -149
  46. package/dist/chunk-4RBEYCWK.js.map +0 -1
  47. package/dist/chunk-KUH345EY.js.map +0 -1
  48. package/dist/chunk-LU2RSO54.js.map +0 -1
  49. package/dist/chunk-PVQZBKN7.js.map +0 -1
  50. package/dist/index-CITGJflw.d.ts +0 -486
@@ -1,30 +1,31 @@
1
1
  import {
2
2
  MCPClientManager
3
- } from "./chunk-4RBEYCWK.js";
3
+ } from "./chunk-MH46VMM4.js";
4
4
  import {
5
5
  DurableObjectOAuthClientProvider
6
- } from "./chunk-PVQZBKN7.js";
6
+ } from "./chunk-LL2AFX7V.js";
7
7
  import {
8
8
  camelCaseToKebabCase
9
- } from "./chunk-KUH345EY.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;
@@ -66,6 +89,7 @@ var Agent = class extends Server {
66
89
  * The observability implementation to use for the Agent
67
90
  */
68
91
  this.observability = genericObservability;
92
+ this._flushingQueue = false;
69
93
  /**
70
94
  * Method called when an alarm fires.
71
95
  * Executes any scheduled tasks that are due.
@@ -79,52 +103,71 @@ var Agent = class extends Server {
79
103
  const result = this.sql`
80
104
  SELECT * FROM cf_agents_schedules WHERE time <= ${now}
81
105
  `;
82
- for (const row of result || []) {
83
- const callback = this[row.callback];
84
- if (!callback) {
85
- console.error(`callback ${row.callback} not found`);
86
- continue;
87
- }
88
- await agentContext.run(
89
- { agent: this, connection: void 0, request: void 0 },
90
- async () => {
91
- try {
92
- this.observability?.emit(
93
- {
94
- displayMessage: `Schedule ${row.id} executed`,
95
- id: nanoid(),
96
- payload: row,
97
- timestamp: Date.now(),
98
- type: "schedule:execute"
99
- },
100
- this.ctx
101
- );
102
- await callback.bind(this)(JSON.parse(row.payload), row);
103
- } catch (e) {
104
- console.error(`error executing callback "${row.callback}"`, e);
105
- }
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;
106
112
  }
107
- );
108
- if (row.type === "cron") {
109
- const nextExecutionTime = getNextCronTime(row.cron);
110
- const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1e3);
111
- 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`
112
145
  UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}
113
146
  `;
114
- } else {
115
- this.sql`
147
+ } else {
148
+ this.sql`
116
149
  DELETE FROM cf_agents_schedules WHERE id = ${row.id}
117
150
  `;
151
+ }
118
152
  }
119
153
  }
120
154
  await this._scheduleNextAlarm();
121
155
  };
156
+ this._autoWrapCustomMethods();
122
157
  this.sql`
123
158
  CREATE TABLE IF NOT EXISTS cf_agents_state (
124
159
  id TEXT PRIMARY KEY NOT NULL,
125
160
  state TEXT
126
161
  )
127
162
  `;
163
+ this.sql`
164
+ CREATE TABLE IF NOT EXISTS cf_agents_queues (
165
+ id TEXT PRIMARY KEY NOT NULL,
166
+ payload TEXT,
167
+ callback TEXT,
168
+ created_at INTEGER DEFAULT (unixepoch())
169
+ )
170
+ `;
128
171
  void this.ctx.blockConcurrencyWhile(async () => {
129
172
  return this._tryCatch(async () => {
130
173
  this.sql`
@@ -156,14 +199,14 @@ var Agent = class extends Server {
156
199
  const _onRequest = this.onRequest.bind(this);
157
200
  this.onRequest = (request) => {
158
201
  return agentContext.run(
159
- { agent: this, connection: void 0, request },
202
+ { agent: this, connection: void 0, request, email: void 0 },
160
203
  async () => {
161
204
  if (this.mcp.isCallbackRequest(request)) {
162
205
  await this.mcp.handleCallbackRequest(request);
163
206
  this.broadcast(
164
207
  JSON.stringify({
165
208
  mcp: this.getMcpServers(),
166
- type: "cf_agent_mcp_servers"
209
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
167
210
  })
168
211
  );
169
212
  return new Response("<script>window.close();</script>", {
@@ -178,7 +221,7 @@ var Agent = class extends Server {
178
221
  const _onMessage = this.onMessage.bind(this);
179
222
  this.onMessage = async (connection, message) => {
180
223
  return agentContext.run(
181
- { agent: this, connection, request: void 0 },
224
+ { agent: this, connection, request: void 0, email: void 0 },
182
225
  async () => {
183
226
  if (typeof message !== "string") {
184
227
  return this._tryCatch(() => _onMessage(connection, message));
@@ -215,10 +258,8 @@ var Agent = class extends Server {
215
258
  displayMessage: `RPC call to ${method}`,
216
259
  id: nanoid(),
217
260
  payload: {
218
- args,
219
261
  method,
220
- streaming: metadata?.streaming,
221
- success: true
262
+ streaming: metadata?.streaming
222
263
  },
223
264
  timestamp: Date.now(),
224
265
  type: "rpc"
@@ -230,7 +271,7 @@ var Agent = class extends Server {
230
271
  id,
231
272
  result,
232
273
  success: true,
233
- type: "rpc"
274
+ type: "rpc" /* RPC */
234
275
  };
235
276
  connection.send(JSON.stringify(response));
236
277
  } catch (e) {
@@ -238,7 +279,7 @@ var Agent = class extends Server {
238
279
  error: e instanceof Error ? e.message : "Unknown error occurred",
239
280
  id: parsed.id,
240
281
  success: false,
241
- type: "rpc"
282
+ type: "rpc" /* RPC */
242
283
  };
243
284
  connection.send(JSON.stringify(response));
244
285
  console.error("RPC error:", e);
@@ -252,70 +293,92 @@ var Agent = class extends Server {
252
293
  const _onConnect = this.onConnect.bind(this);
253
294
  this.onConnect = (connection, ctx2) => {
254
295
  return agentContext.run(
255
- { agent: this, connection, request: ctx2.request },
256
- async () => {
257
- setTimeout(() => {
258
- if (this.state) {
259
- connection.send(
260
- JSON.stringify({
261
- state: this.state,
262
- type: "cf_agent_state"
263
- })
264
- );
265
- }
296
+ { agent: this, connection, request: ctx2.request, email: void 0 },
297
+ () => {
298
+ if (this.state) {
266
299
  connection.send(
267
300
  JSON.stringify({
268
- mcp: this.getMcpServers(),
269
- type: "cf_agent_mcp_servers"
301
+ state: this.state,
302
+ type: "cf_agent_state" /* CF_AGENT_STATE */
270
303
  })
271
304
  );
272
- this.observability?.emit(
273
- {
274
- displayMessage: "Connection established",
275
- id: nanoid(),
276
- payload: {
277
- connectionId: connection.id
278
- },
279
- timestamp: Date.now(),
280
- type: "connect"
305
+ }
306
+ connection.send(
307
+ JSON.stringify({
308
+ mcp: this.getMcpServers(),
309
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
310
+ })
311
+ );
312
+ this.observability?.emit(
313
+ {
314
+ displayMessage: "Connection established",
315
+ id: nanoid(),
316
+ payload: {
317
+ connectionId: connection.id
281
318
  },
282
- this.ctx
283
- );
284
- return this._tryCatch(() => _onConnect(connection, ctx2));
285
- }, 20);
319
+ timestamp: Date.now(),
320
+ type: "connect"
321
+ },
322
+ this.ctx
323
+ );
324
+ return this._tryCatch(() => _onConnect(connection, ctx2));
286
325
  }
287
326
  );
288
327
  };
289
328
  const _onStart = this.onStart.bind(this);
290
- this.onStart = async () => {
329
+ this.onStart = async (props) => {
291
330
  return agentContext.run(
292
- { agent: this, connection: void 0, request: void 0 },
331
+ {
332
+ agent: this,
333
+ connection: void 0,
334
+ request: void 0,
335
+ email: void 0
336
+ },
293
337
  async () => {
294
- const servers = this.sql`
338
+ await this._tryCatch(() => {
339
+ const servers = this.sql`
295
340
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
296
341
  `;
297
- Promise.allSettled(
298
- servers.map((server) => {
299
- return this._connectToMcpServerInternal(
300
- server.name,
301
- server.server_url,
302
- server.callback_url,
303
- server.server_options ? JSON.parse(server.server_options) : void 0,
304
- {
305
- id: server.id,
306
- oauthClientId: server.client_id ?? void 0
307
- }
308
- );
309
- })
310
- ).then((_results) => {
311
342
  this.broadcast(
312
343
  JSON.stringify({
313
344
  mcp: this.getMcpServers(),
314
- type: "cf_agent_mcp_servers"
345
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
315
346
  })
316
347
  );
348
+ if (servers && Array.isArray(servers) && servers.length > 0) {
349
+ servers.forEach((server) => {
350
+ this._connectToMcpServerInternal(
351
+ server.name,
352
+ server.server_url,
353
+ server.callback_url,
354
+ server.server_options ? JSON.parse(server.server_options) : void 0,
355
+ {
356
+ id: server.id,
357
+ oauthClientId: server.client_id ?? void 0
358
+ }
359
+ ).then(() => {
360
+ this.broadcast(
361
+ JSON.stringify({
362
+ mcp: this.getMcpServers(),
363
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
364
+ })
365
+ );
366
+ }).catch((error) => {
367
+ console.error(
368
+ `Error connecting to MCP server: ${server.name} (${server.server_url})`,
369
+ error
370
+ );
371
+ this.broadcast(
372
+ JSON.stringify({
373
+ mcp: this.getMcpServers(),
374
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
375
+ })
376
+ );
377
+ });
378
+ });
379
+ }
380
+ return _onStart(props);
317
381
  });
318
- await this._tryCatch(() => _onStart());
319
382
  }
320
383
  );
321
384
  };
@@ -366,7 +429,6 @@ var Agent = class extends Server {
366
429
  }
367
430
  }
368
431
  _setStateInternal(state, source = "server") {
369
- const previousState = this._state;
370
432
  this._state = state;
371
433
  this.sql`
372
434
  INSERT OR REPLACE INTO cf_agents_state (id, state)
@@ -379,23 +441,20 @@ var Agent = class extends Server {
379
441
  this.broadcast(
380
442
  JSON.stringify({
381
443
  state,
382
- type: "cf_agent_state"
444
+ type: "cf_agent_state" /* CF_AGENT_STATE */
383
445
  }),
384
446
  source !== "server" ? [source.id] : []
385
447
  );
386
448
  return this._tryCatch(() => {
387
- const { connection, request } = agentContext.getStore() || {};
449
+ const { connection, request, email } = agentContext.getStore() || {};
388
450
  return agentContext.run(
389
- { agent: this, connection, request },
451
+ { agent: this, connection, request, email },
390
452
  async () => {
391
453
  this.observability?.emit(
392
454
  {
393
455
  displayMessage: "State updated",
394
456
  id: nanoid(),
395
- payload: {
396
- previousState,
397
- state
398
- },
457
+ payload: {},
399
458
  timestamp: Date.now(),
400
459
  type: "state:update"
401
460
  },
@@ -422,18 +481,67 @@ var Agent = class extends Server {
422
481
  onStateUpdate(state, source) {
423
482
  }
424
483
  /**
425
- * Called when the Agent receives an email
484
+ * Called when the Agent receives an email via routeAgentEmail()
485
+ * Override this method to handle incoming emails
426
486
  * @param email Email message to process
427
487
  */
428
- // biome-ignore lint/correctness/noUnusedFunctionParameters: overridden later
429
- onEmail(email) {
488
+ async _onEmail(email) {
430
489
  return agentContext.run(
431
- { agent: this, connection: void 0, request: void 0 },
490
+ { agent: this, connection: void 0, request: void 0, email },
432
491
  async () => {
433
- console.error("onEmail not implemented");
492
+ if ("onEmail" in this && typeof this.onEmail === "function") {
493
+ return this._tryCatch(
494
+ () => this.onEmail(email)
495
+ );
496
+ } else {
497
+ console.log("Received email from:", email.from, "to:", email.to);
498
+ console.log("Subject:", email.headers.get("subject"));
499
+ console.log(
500
+ "Implement onEmail(email: AgentEmail): Promise<void> in your agent to process emails"
501
+ );
502
+ }
434
503
  }
435
504
  );
436
505
  }
506
+ /**
507
+ * Reply to an email
508
+ * @param email The email to reply to
509
+ * @param options Options for the reply
510
+ * @returns void
511
+ */
512
+ async replyToEmail(email, options) {
513
+ return this._tryCatch(async () => {
514
+ const agentName = camelCaseToKebabCase(this._ParentClass.name);
515
+ const agentId = this.name;
516
+ const { createMimeMessage } = await import("mimetext");
517
+ const msg = createMimeMessage();
518
+ msg.setSender({ addr: email.to, name: options.fromName });
519
+ msg.setRecipient(email.from);
520
+ msg.setSubject(
521
+ options.subject || `Re: ${email.headers.get("subject")}` || "No subject"
522
+ );
523
+ msg.addMessage({
524
+ contentType: options.contentType || "text/plain",
525
+ data: options.body
526
+ });
527
+ const domain = email.from.split("@")[1];
528
+ const messageId = `<${agentId}@${domain}>`;
529
+ msg.setHeader("In-Reply-To", email.headers.get("Message-ID"));
530
+ msg.setHeader("Message-ID", messageId);
531
+ msg.setHeader("X-Agent-Name", agentName);
532
+ msg.setHeader("X-Agent-ID", agentId);
533
+ if (options.headers) {
534
+ for (const [key, value] of Object.entries(options.headers)) {
535
+ msg.setHeader(key, value);
536
+ }
537
+ }
538
+ await email.reply({
539
+ from: email.to,
540
+ raw: msg.asRaw(),
541
+ to: email.from
542
+ });
543
+ });
544
+ }
437
545
  async _tryCatch(fn) {
438
546
  try {
439
547
  return await fn();
@@ -441,6 +549,49 @@ var Agent = class extends Server {
441
549
  throw this.onError(e);
442
550
  }
443
551
  }
552
+ /**
553
+ * Automatically wrap custom methods with agent context
554
+ * This ensures getCurrentAgent() works in all custom methods without decorators
555
+ */
556
+ _autoWrapCustomMethods() {
557
+ const basePrototypes = [_Agent.prototype, Server.prototype];
558
+ const baseMethods = /* @__PURE__ */ new Set();
559
+ for (const baseProto of basePrototypes) {
560
+ let proto2 = baseProto;
561
+ while (proto2 && proto2 !== Object.prototype) {
562
+ const methodNames = Object.getOwnPropertyNames(proto2);
563
+ for (const methodName of methodNames) {
564
+ baseMethods.add(methodName);
565
+ }
566
+ proto2 = Object.getPrototypeOf(proto2);
567
+ }
568
+ }
569
+ let proto = Object.getPrototypeOf(this);
570
+ let depth = 0;
571
+ while (proto && proto !== Object.prototype && depth < 10) {
572
+ const methodNames = Object.getOwnPropertyNames(proto);
573
+ for (const methodName of methodNames) {
574
+ const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
575
+ if (baseMethods.has(methodName) || methodName.startsWith("_") || !descriptor || !!descriptor.get || typeof descriptor.value !== "function") {
576
+ continue;
577
+ }
578
+ const wrappedFunction = withAgentContext(
579
+ // biome-ignore lint/suspicious/noExplicitAny: I can't typescript
580
+ this[methodName]
581
+ // biome-ignore lint/suspicious/noExplicitAny: I can't typescript
582
+ );
583
+ if (this._isCallable(methodName)) {
584
+ callableMetadata.set(
585
+ wrappedFunction,
586
+ callableMetadata.get(this[methodName])
587
+ );
588
+ }
589
+ this.constructor.prototype[methodName] = wrappedFunction;
590
+ }
591
+ proto = Object.getPrototypeOf(proto);
592
+ depth++;
593
+ }
594
+ }
444
595
  onError(connectionOrError, error) {
445
596
  let theError;
446
597
  if (connectionOrError && error) {
@@ -466,6 +617,108 @@ var Agent = class extends Server {
466
617
  render() {
467
618
  throw new Error("Not implemented");
468
619
  }
620
+ /**
621
+ * Queue a task to be executed in the future
622
+ * @param payload Payload to pass to the callback
623
+ * @param callback Name of the method to call
624
+ * @returns The ID of the queued task
625
+ */
626
+ async queue(callback, payload) {
627
+ const id = nanoid(9);
628
+ if (typeof callback !== "string") {
629
+ throw new Error("Callback must be a string");
630
+ }
631
+ if (typeof this[callback] !== "function") {
632
+ throw new Error(`this.${callback} is not a function`);
633
+ }
634
+ this.sql`
635
+ INSERT OR REPLACE INTO cf_agents_queues (id, payload, callback)
636
+ VALUES (${id}, ${JSON.stringify(payload)}, ${callback})
637
+ `;
638
+ void this._flushQueue().catch((e) => {
639
+ console.error("Error flushing queue:", e);
640
+ });
641
+ return id;
642
+ }
643
+ async _flushQueue() {
644
+ if (this._flushingQueue) {
645
+ return;
646
+ }
647
+ this._flushingQueue = true;
648
+ while (true) {
649
+ const result = this.sql`
650
+ SELECT * FROM cf_agents_queues
651
+ ORDER BY created_at ASC
652
+ `;
653
+ if (!result || result.length === 0) {
654
+ break;
655
+ }
656
+ for (const row of result || []) {
657
+ const callback = this[row.callback];
658
+ if (!callback) {
659
+ console.error(`callback ${row.callback} not found`);
660
+ continue;
661
+ }
662
+ const { connection, request, email } = agentContext.getStore() || {};
663
+ await agentContext.run(
664
+ {
665
+ agent: this,
666
+ connection,
667
+ request,
668
+ email
669
+ },
670
+ async () => {
671
+ await callback.bind(this)(JSON.parse(row.payload), row);
672
+ await this.dequeue(row.id);
673
+ }
674
+ );
675
+ }
676
+ }
677
+ this._flushingQueue = false;
678
+ }
679
+ /**
680
+ * Dequeue a task by ID
681
+ * @param id ID of the task to dequeue
682
+ */
683
+ async dequeue(id) {
684
+ this.sql`DELETE FROM cf_agents_queues WHERE id = ${id}`;
685
+ }
686
+ /**
687
+ * Dequeue all tasks
688
+ */
689
+ async dequeueAll() {
690
+ this.sql`DELETE FROM cf_agents_queues`;
691
+ }
692
+ /**
693
+ * Dequeue all tasks by callback
694
+ * @param callback Name of the callback to dequeue
695
+ */
696
+ async dequeueAllByCallback(callback) {
697
+ this.sql`DELETE FROM cf_agents_queues WHERE callback = ${callback}`;
698
+ }
699
+ /**
700
+ * Get a queued task by ID
701
+ * @param id ID of the task to get
702
+ * @returns The task or undefined if not found
703
+ */
704
+ async getQueue(id) {
705
+ const result = this.sql`
706
+ SELECT * FROM cf_agents_queues WHERE id = ${id}
707
+ `;
708
+ return result ? { ...result[0], payload: JSON.parse(result[0].payload) } : void 0;
709
+ }
710
+ /**
711
+ * Get all queues by key and value
712
+ * @param key Key to filter by
713
+ * @param value Value to filter by
714
+ * @returns Array of matching QueueItem objects
715
+ */
716
+ async getQueues(key, value) {
717
+ const result = this.sql`
718
+ SELECT * FROM cf_agents_queues
719
+ `;
720
+ return result.filter((row) => JSON.parse(row.payload)[key] === value);
721
+ }
469
722
  /**
470
723
  * Schedule a task to be executed in the future
471
724
  * @template T Type of the payload data
@@ -480,7 +733,10 @@ var Agent = class extends Server {
480
733
  {
481
734
  displayMessage: `Schedule ${schedule.id} created`,
482
735
  id: nanoid(),
483
- payload: schedule,
736
+ payload: {
737
+ callback,
738
+ id
739
+ },
484
740
  timestamp: Date.now(),
485
741
  type: "schedule:create"
486
742
  },
@@ -615,7 +871,10 @@ var Agent = class extends Server {
615
871
  {
616
872
  displayMessage: `Schedule ${id} cancelled`,
617
873
  id: nanoid(),
618
- payload: schedule,
874
+ payload: {
875
+ callback: schedule.callback,
876
+ id: schedule.id
877
+ },
619
878
  timestamp: Date.now(),
620
879
  type: "schedule:cancel"
621
880
  },
@@ -628,9 +887,9 @@ var Agent = class extends Server {
628
887
  }
629
888
  async _scheduleNextAlarm() {
630
889
  const result = this.sql`
631
- SELECT time FROM cf_agents_schedules
890
+ SELECT time FROM cf_agents_schedules
632
891
  WHERE time > ${Math.floor(Date.now() / 1e3)}
633
- ORDER BY time ASC
892
+ ORDER BY time ASC
634
893
  LIMIT 1
635
894
  `;
636
895
  if (!result) return;
@@ -646,6 +905,7 @@ var Agent = class extends Server {
646
905
  this.sql`DROP TABLE IF EXISTS cf_agents_state`;
647
906
  this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;
648
907
  this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
908
+ this.sql`DROP TABLE IF EXISTS cf_agents_queues`;
649
909
  await this.ctx.storage.deleteAlarm();
650
910
  await this.ctx.storage.deleteAll();
651
911
  this.ctx.abort("destroyed");
@@ -700,7 +960,7 @@ var Agent = class extends Server {
700
960
  this.broadcast(
701
961
  JSON.stringify({
702
962
  mcp: this.getMcpServers(),
703
- type: "cf_agent_mcp_servers"
963
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
704
964
  })
705
965
  );
706
966
  return result;
@@ -753,7 +1013,7 @@ var Agent = class extends Server {
753
1013
  this.broadcast(
754
1014
  JSON.stringify({
755
1015
  mcp: this.getMcpServers(),
756
- type: "cf_agent_mcp_servers"
1016
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
757
1017
  })
758
1018
  );
759
1019
  }
@@ -767,17 +1027,19 @@ var Agent = class extends Server {
767
1027
  const servers = this.sql`
768
1028
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
769
1029
  `;
770
- for (const server of servers) {
771
- const serverConn = this.mcp.mcpConnections[server.id];
772
- mcpState.servers[server.id] = {
773
- auth_url: server.auth_url,
774
- capabilities: serverConn?.serverCapabilities ?? null,
775
- instructions: serverConn?.instructions ?? null,
776
- name: server.name,
777
- server_url: server.server_url,
778
- // mark as "authenticating" because the server isn't automatically connected, so it's pending authenticating
779
- state: serverConn?.connectionState ?? "authenticating"
780
- };
1030
+ if (servers && Array.isArray(servers) && servers.length > 0) {
1031
+ for (const server of servers) {
1032
+ const serverConn = this.mcp.mcpConnections[server.id];
1033
+ mcpState.servers[server.id] = {
1034
+ auth_url: server.auth_url,
1035
+ capabilities: serverConn?.serverCapabilities ?? null,
1036
+ instructions: serverConn?.instructions ?? null,
1037
+ name: server.name,
1038
+ server_url: server.server_url,
1039
+ // mark as "authenticating" because the server isn't automatically connected, so it's pending authenticating
1040
+ state: serverConn?.connectionState ?? "authenticating"
1041
+ };
1042
+ }
781
1043
  }
782
1044
  return mcpState;
783
1045
  }
@@ -785,11 +1047,12 @@ var Agent = class extends Server {
785
1047
  /**
786
1048
  * Agent configuration options
787
1049
  */
788
- Agent.options = {
1050
+ _Agent.options = {
789
1051
  /** Whether the Agent should hibernate when inactive */
790
1052
  hibernate: true
791
1053
  // default to hibernate
792
1054
  };
1055
+ var Agent = _Agent;
793
1056
  async function routeAgentRequest(request, env, options) {
794
1057
  const corsHeaders = options?.cors === true ? {
795
1058
  "Access-Control-Allow-Credentials": "true",
@@ -825,7 +1088,126 @@ async function routeAgentRequest(request, env, options) {
825
1088
  }
826
1089
  return response;
827
1090
  }
828
- async function routeAgentEmail(_email, _env, _options) {
1091
+ function createHeaderBasedEmailResolver() {
1092
+ return async (email, _env) => {
1093
+ const messageId = email.headers.get("message-id");
1094
+ if (messageId) {
1095
+ const messageIdMatch = messageId.match(/<([^@]+)@([^>]+)>/);
1096
+ if (messageIdMatch) {
1097
+ const [, agentId2, domain] = messageIdMatch;
1098
+ const agentName2 = domain.split(".")[0];
1099
+ return { agentName: agentName2, agentId: agentId2 };
1100
+ }
1101
+ }
1102
+ const references = email.headers.get("references");
1103
+ if (references) {
1104
+ const referencesMatch = references.match(
1105
+ /<([A-Za-z0-9+/]{43}=)@([^>]+)>/
1106
+ );
1107
+ if (referencesMatch) {
1108
+ const [, base64Id, domain] = referencesMatch;
1109
+ const agentId2 = Buffer.from(base64Id, "base64").toString("hex");
1110
+ const agentName2 = domain.split(".")[0];
1111
+ return { agentName: agentName2, agentId: agentId2 };
1112
+ }
1113
+ }
1114
+ const agentName = email.headers.get("x-agent-name");
1115
+ const agentId = email.headers.get("x-agent-id");
1116
+ if (agentName && agentId) {
1117
+ return { agentName, agentId };
1118
+ }
1119
+ return null;
1120
+ };
1121
+ }
1122
+ function createAddressBasedEmailResolver(defaultAgentName) {
1123
+ return async (email, _env) => {
1124
+ const emailMatch = email.to.match(/^([^+@]+)(?:\+([^@]+))?@(.+)$/);
1125
+ if (!emailMatch) {
1126
+ return null;
1127
+ }
1128
+ const [, localPart, subAddress] = emailMatch;
1129
+ if (subAddress) {
1130
+ return {
1131
+ agentName: localPart,
1132
+ agentId: subAddress
1133
+ };
1134
+ }
1135
+ return {
1136
+ agentName: defaultAgentName,
1137
+ agentId: localPart
1138
+ };
1139
+ };
1140
+ }
1141
+ function createCatchAllEmailResolver(agentName, agentId) {
1142
+ return async () => ({ agentName, agentId });
1143
+ }
1144
+ var agentMapCache = /* @__PURE__ */ new WeakMap();
1145
+ async function routeAgentEmail(email, env, options) {
1146
+ const routingInfo = await options.resolver(email, env);
1147
+ if (!routingInfo) {
1148
+ console.warn("No routing information found for email, dropping message");
1149
+ return;
1150
+ }
1151
+ if (!agentMapCache.has(env)) {
1152
+ const map = {};
1153
+ for (const [key, value] of Object.entries(env)) {
1154
+ if (value && typeof value === "object" && "idFromName" in value && typeof value.idFromName === "function") {
1155
+ map[key] = value;
1156
+ map[camelCaseToKebabCase(key)] = value;
1157
+ }
1158
+ }
1159
+ agentMapCache.set(env, map);
1160
+ }
1161
+ const agentMap = agentMapCache.get(env);
1162
+ const namespace = agentMap[routingInfo.agentName];
1163
+ if (!namespace) {
1164
+ const availableAgents = Object.keys(agentMap).filter((key) => !key.includes("-")).join(", ");
1165
+ throw new Error(
1166
+ `Agent namespace '${routingInfo.agentName}' not found in environment. Available agents: ${availableAgents}`
1167
+ );
1168
+ }
1169
+ const agent = await getAgentByName(
1170
+ namespace,
1171
+ routingInfo.agentId
1172
+ );
1173
+ const serialisableEmail = {
1174
+ getRaw: async () => {
1175
+ const reader = email.raw.getReader();
1176
+ const chunks = [];
1177
+ let done = false;
1178
+ while (!done) {
1179
+ const { value, done: readerDone } = await reader.read();
1180
+ done = readerDone;
1181
+ if (value) {
1182
+ chunks.push(value);
1183
+ }
1184
+ }
1185
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
1186
+ const combined = new Uint8Array(totalLength);
1187
+ let offset = 0;
1188
+ for (const chunk of chunks) {
1189
+ combined.set(chunk, offset);
1190
+ offset += chunk.length;
1191
+ }
1192
+ return combined;
1193
+ },
1194
+ headers: email.headers,
1195
+ rawSize: email.rawSize,
1196
+ setReject: (reason) => {
1197
+ email.setReject(reason);
1198
+ },
1199
+ forward: (rcptTo, headers) => {
1200
+ return email.forward(rcptTo, headers);
1201
+ },
1202
+ reply: (options2) => {
1203
+ return email.reply(
1204
+ new EmailMessage(options2.from, options2.to, options2.raw)
1205
+ );
1206
+ },
1207
+ from: email.from,
1208
+ to: email.to
1209
+ };
1210
+ await agent._onEmail(serialisableEmail);
829
1211
  }
830
1212
  async function getAgentByName(namespace, name, options) {
831
1213
  return getServerByName(namespace, name, options);
@@ -849,7 +1231,7 @@ var StreamingResponse = class {
849
1231
  id: this._id,
850
1232
  result: chunk,
851
1233
  success: true,
852
- type: "rpc"
1234
+ type: "rpc" /* RPC */
853
1235
  };
854
1236
  this._connection.send(JSON.stringify(response));
855
1237
  }
@@ -867,7 +1249,7 @@ var StreamingResponse = class {
867
1249
  id: this._id,
868
1250
  result: finalChunk,
869
1251
  success: true,
870
- type: "rpc"
1252
+ type: "rpc" /* RPC */
871
1253
  };
872
1254
  this._connection.send(JSON.stringify(response));
873
1255
  }
@@ -899,12 +1281,16 @@ function isLocalMode() {
899
1281
 
900
1282
  export {
901
1283
  genericObservability,
1284
+ callable,
902
1285
  unstable_callable,
903
1286
  getCurrentAgent,
904
1287
  Agent,
905
1288
  routeAgentRequest,
1289
+ createHeaderBasedEmailResolver,
1290
+ createAddressBasedEmailResolver,
1291
+ createCatchAllEmailResolver,
906
1292
  routeAgentEmail,
907
1293
  getAgentByName,
908
1294
  StreamingResponse
909
1295
  };
910
- //# sourceMappingURL=chunk-LU2RSO54.js.map
1296
+ //# sourceMappingURL=chunk-YDUDMOL6.js.map