agents 0.0.0-8157d08 → 0.0.0-8234d41

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 (51) hide show
  1. package/README.md +255 -27
  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 +68 -71
  9. package/dist/ai-react.js +177 -37
  10. package/dist/ai-react.js.map +1 -1
  11. package/dist/ai-types.d.ts +37 -19
  12. package/dist/ai-types.js +6 -0
  13. package/dist/chunk-BER7KXUJ.js +18 -0
  14. package/dist/chunk-BER7KXUJ.js.map +1 -0
  15. package/dist/{chunk-767EASBA.js → chunk-LL2AFX7V.js} +5 -2
  16. package/dist/chunk-LL2AFX7V.js.map +1 -0
  17. package/dist/{chunk-JFRK72K3.js → chunk-M5SZRJTA.js} +519 -129
  18. package/dist/chunk-M5SZRJTA.js.map +1 -0
  19. package/dist/{chunk-E3LCYPCB.js → chunk-MH46VMM4.js} +163 -20
  20. package/dist/chunk-MH46VMM4.js.map +1 -0
  21. package/dist/{chunk-NKZZ66QY.js → chunk-QEVM4BVL.js} +5 -5
  22. package/dist/chunk-QEVM4BVL.js.map +1 -0
  23. package/dist/chunk-UJVEAURM.js +150 -0
  24. package/dist/chunk-UJVEAURM.js.map +1 -0
  25. package/dist/client-CvaJdLQA.d.ts +5015 -0
  26. package/dist/client.d.ts +2 -2
  27. package/dist/client.js +2 -1
  28. package/dist/index.d.ts +557 -24
  29. package/dist/index.js +13 -4
  30. package/dist/mcp/client.d.ts +9 -1053
  31. package/dist/mcp/client.js +1 -1
  32. package/dist/mcp/do-oauth-client-provider.d.ts +1 -0
  33. package/dist/mcp/do-oauth-client-provider.js +1 -1
  34. package/dist/mcp/index.d.ts +64 -56
  35. package/dist/mcp/index.js +952 -637
  36. package/dist/mcp/index.js.map +1 -1
  37. package/dist/observability/index.d.ts +46 -12
  38. package/dist/observability/index.js +5 -4
  39. package/dist/react.d.ts +10 -6
  40. package/dist/react.js +7 -5
  41. package/dist/react.js.map +1 -1
  42. package/dist/schedule.d.ts +83 -9
  43. package/dist/schedule.js +15 -2
  44. package/dist/schedule.js.map +1 -1
  45. package/package.json +21 -10
  46. package/src/index.ts +761 -173
  47. package/dist/chunk-767EASBA.js.map +0 -1
  48. package/dist/chunk-E3LCYPCB.js.map +0 -1
  49. package/dist/chunk-JFRK72K3.js.map +0 -1
  50. package/dist/chunk-NKZZ66QY.js.map +0 -1
  51. package/dist/index-CITGJflw.d.ts +0 -486
@@ -1,30 +1,31 @@
1
1
  import {
2
2
  MCPClientManager
3
- } from "./chunk-E3LCYPCB.js";
3
+ } from "./chunk-MH46VMM4.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;
@@ -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,74 @@ 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
+ if (!wrappedClasses.has(this.constructor)) {
157
+ this._autoWrapCustomMethods();
158
+ wrappedClasses.add(this.constructor);
159
+ }
122
160
  this.sql`
123
161
  CREATE TABLE IF NOT EXISTS cf_agents_state (
124
162
  id TEXT PRIMARY KEY NOT NULL,
125
163
  state TEXT
126
164
  )
127
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
+ `;
128
174
  void this.ctx.blockConcurrencyWhile(async () => {
129
175
  return this._tryCatch(async () => {
130
176
  this.sql`
@@ -156,14 +202,14 @@ var Agent = class extends Server {
156
202
  const _onRequest = this.onRequest.bind(this);
157
203
  this.onRequest = (request) => {
158
204
  return agentContext.run(
159
- { agent: this, connection: void 0, request },
205
+ { agent: this, connection: void 0, request, email: void 0 },
160
206
  async () => {
161
207
  if (this.mcp.isCallbackRequest(request)) {
162
208
  await this.mcp.handleCallbackRequest(request);
163
209
  this.broadcast(
164
210
  JSON.stringify({
165
211
  mcp: this.getMcpServers(),
166
- type: "cf_agent_mcp_servers"
212
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
167
213
  })
168
214
  );
169
215
  return new Response("<script>window.close();</script>", {
@@ -178,7 +224,7 @@ var Agent = class extends Server {
178
224
  const _onMessage = this.onMessage.bind(this);
179
225
  this.onMessage = async (connection, message) => {
180
226
  return agentContext.run(
181
- { agent: this, connection, request: void 0 },
227
+ { agent: this, connection, request: void 0, email: void 0 },
182
228
  async () => {
183
229
  if (typeof message !== "string") {
184
230
  return this._tryCatch(() => _onMessage(connection, message));
@@ -215,10 +261,8 @@ var Agent = class extends Server {
215
261
  displayMessage: `RPC call to ${method}`,
216
262
  id: nanoid(),
217
263
  payload: {
218
- args,
219
264
  method,
220
- streaming: metadata?.streaming,
221
- success: true
265
+ streaming: metadata?.streaming
222
266
  },
223
267
  timestamp: Date.now(),
224
268
  type: "rpc"
@@ -230,7 +274,7 @@ var Agent = class extends Server {
230
274
  id,
231
275
  result,
232
276
  success: true,
233
- type: "rpc"
277
+ type: "rpc" /* RPC */
234
278
  };
235
279
  connection.send(JSON.stringify(response));
236
280
  } catch (e) {
@@ -238,7 +282,7 @@ var Agent = class extends Server {
238
282
  error: e instanceof Error ? e.message : "Unknown error occurred",
239
283
  id: parsed.id,
240
284
  success: false,
241
- type: "rpc"
285
+ type: "rpc" /* RPC */
242
286
  };
243
287
  connection.send(JSON.stringify(response));
244
288
  console.error("RPC error:", e);
@@ -252,70 +296,92 @@ var Agent = class extends Server {
252
296
  const _onConnect = this.onConnect.bind(this);
253
297
  this.onConnect = (connection, ctx2) => {
254
298
  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
- }
299
+ { agent: this, connection, request: ctx2.request, email: void 0 },
300
+ () => {
301
+ if (this.state) {
266
302
  connection.send(
267
303
  JSON.stringify({
268
- mcp: this.getMcpServers(),
269
- type: "cf_agent_mcp_servers"
304
+ state: this.state,
305
+ type: "cf_agent_state" /* CF_AGENT_STATE */
270
306
  })
271
307
  );
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"
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
281
321
  },
282
- this.ctx
283
- );
284
- return this._tryCatch(() => _onConnect(connection, ctx2));
285
- }, 20);
322
+ timestamp: Date.now(),
323
+ type: "connect"
324
+ },
325
+ this.ctx
326
+ );
327
+ return this._tryCatch(() => _onConnect(connection, ctx2));
286
328
  }
287
329
  );
288
330
  };
289
331
  const _onStart = this.onStart.bind(this);
290
- this.onStart = async () => {
332
+ this.onStart = async (props) => {
291
333
  return agentContext.run(
292
- { 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
+ },
293
340
  async () => {
294
- const servers = this.sql`
341
+ await this._tryCatch(() => {
342
+ const servers = this.sql`
295
343
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
296
344
  `;
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
345
  this.broadcast(
312
346
  JSON.stringify({
313
347
  mcp: this.getMcpServers(),
314
- type: "cf_agent_mcp_servers"
348
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
315
349
  })
316
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);
317
384
  });
318
- await this._tryCatch(() => _onStart());
319
385
  }
320
386
  );
321
387
  };
@@ -366,7 +432,6 @@ var Agent = class extends Server {
366
432
  }
367
433
  }
368
434
  _setStateInternal(state, source = "server") {
369
- const previousState = this._state;
370
435
  this._state = state;
371
436
  this.sql`
372
437
  INSERT OR REPLACE INTO cf_agents_state (id, state)
@@ -379,23 +444,20 @@ var Agent = class extends Server {
379
444
  this.broadcast(
380
445
  JSON.stringify({
381
446
  state,
382
- type: "cf_agent_state"
447
+ type: "cf_agent_state" /* CF_AGENT_STATE */
383
448
  }),
384
449
  source !== "server" ? [source.id] : []
385
450
  );
386
451
  return this._tryCatch(() => {
387
- const { connection, request } = agentContext.getStore() || {};
452
+ const { connection, request, email } = agentContext.getStore() || {};
388
453
  return agentContext.run(
389
- { agent: this, connection, request },
454
+ { agent: this, connection, request, email },
390
455
  async () => {
391
456
  this.observability?.emit(
392
457
  {
393
458
  displayMessage: "State updated",
394
459
  id: nanoid(),
395
- payload: {
396
- previousState,
397
- state
398
- },
460
+ payload: {},
399
461
  timestamp: Date.now(),
400
462
  type: "state:update"
401
463
  },
@@ -422,18 +484,67 @@ var Agent = class extends Server {
422
484
  onStateUpdate(state, source) {
423
485
  }
424
486
  /**
425
- * 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
426
489
  * @param email Email message to process
427
490
  */
428
- // biome-ignore lint/correctness/noUnusedFunctionParameters: overridden later
429
- onEmail(email) {
491
+ async _onEmail(email) {
430
492
  return agentContext.run(
431
- { agent: this, connection: void 0, request: void 0 },
493
+ { agent: this, connection: void 0, request: void 0, email },
432
494
  async () => {
433
- 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
+ }
434
506
  }
435
507
  );
436
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
+ }
437
548
  async _tryCatch(fn) {
438
549
  try {
439
550
  return await fn();
@@ -441,6 +552,49 @@ var Agent = class extends Server {
441
552
  throw this.onError(e);
442
553
  }
443
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
+ }
444
598
  onError(connectionOrError, error) {
445
599
  let theError;
446
600
  if (connectionOrError && error) {
@@ -466,6 +620,108 @@ var Agent = class extends Server {
466
620
  render() {
467
621
  throw new Error("Not implemented");
468
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
+ }
469
725
  /**
470
726
  * Schedule a task to be executed in the future
471
727
  * @template T Type of the payload data
@@ -480,7 +736,10 @@ var Agent = class extends Server {
480
736
  {
481
737
  displayMessage: `Schedule ${schedule.id} created`,
482
738
  id: nanoid(),
483
- payload: schedule,
739
+ payload: {
740
+ callback,
741
+ id
742
+ },
484
743
  timestamp: Date.now(),
485
744
  type: "schedule:create"
486
745
  },
@@ -615,7 +874,10 @@ var Agent = class extends Server {
615
874
  {
616
875
  displayMessage: `Schedule ${id} cancelled`,
617
876
  id: nanoid(),
618
- payload: schedule,
877
+ payload: {
878
+ callback: schedule.callback,
879
+ id: schedule.id
880
+ },
619
881
  timestamp: Date.now(),
620
882
  type: "schedule:cancel"
621
883
  },
@@ -628,9 +890,9 @@ var Agent = class extends Server {
628
890
  }
629
891
  async _scheduleNextAlarm() {
630
892
  const result = this.sql`
631
- SELECT time FROM cf_agents_schedules
893
+ SELECT time FROM cf_agents_schedules
632
894
  WHERE time > ${Math.floor(Date.now() / 1e3)}
633
- ORDER BY time ASC
895
+ ORDER BY time ASC
634
896
  LIMIT 1
635
897
  `;
636
898
  if (!result) return;
@@ -646,6 +908,7 @@ var Agent = class extends Server {
646
908
  this.sql`DROP TABLE IF EXISTS cf_agents_state`;
647
909
  this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;
648
910
  this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
911
+ this.sql`DROP TABLE IF EXISTS cf_agents_queues`;
649
912
  await this.ctx.storage.deleteAlarm();
650
913
  await this.ctx.storage.deleteAll();
651
914
  this.ctx.abort("destroyed");
@@ -700,7 +963,7 @@ var Agent = class extends Server {
700
963
  this.broadcast(
701
964
  JSON.stringify({
702
965
  mcp: this.getMcpServers(),
703
- type: "cf_agent_mcp_servers"
966
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
704
967
  })
705
968
  );
706
969
  return result;
@@ -753,7 +1016,7 @@ var Agent = class extends Server {
753
1016
  this.broadcast(
754
1017
  JSON.stringify({
755
1018
  mcp: this.getMcpServers(),
756
- type: "cf_agent_mcp_servers"
1019
+ type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
757
1020
  })
758
1021
  );
759
1022
  }
@@ -767,17 +1030,19 @@ var Agent = class extends Server {
767
1030
  const servers = this.sql`
768
1031
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
769
1032
  `;
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
- };
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
+ }
781
1046
  }
782
1047
  return mcpState;
783
1048
  }
@@ -785,11 +1050,13 @@ var Agent = class extends Server {
785
1050
  /**
786
1051
  * Agent configuration options
787
1052
  */
788
- Agent.options = {
1053
+ _Agent.options = {
789
1054
  /** Whether the Agent should hibernate when inactive */
790
1055
  hibernate: true
791
1056
  // default to hibernate
792
1057
  };
1058
+ var Agent = _Agent;
1059
+ var wrappedClasses = /* @__PURE__ */ new Set();
793
1060
  async function routeAgentRequest(request, env, options) {
794
1061
  const corsHeaders = options?.cors === true ? {
795
1062
  "Access-Control-Allow-Credentials": "true",
@@ -825,7 +1092,126 @@ async function routeAgentRequest(request, env, options) {
825
1092
  }
826
1093
  return response;
827
1094
  }
828
- 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);
829
1215
  }
830
1216
  async function getAgentByName(namespace, name, options) {
831
1217
  return getServerByName(namespace, name, options);
@@ -849,7 +1235,7 @@ var StreamingResponse = class {
849
1235
  id: this._id,
850
1236
  result: chunk,
851
1237
  success: true,
852
- type: "rpc"
1238
+ type: "rpc" /* RPC */
853
1239
  };
854
1240
  this._connection.send(JSON.stringify(response));
855
1241
  }
@@ -867,7 +1253,7 @@ var StreamingResponse = class {
867
1253
  id: this._id,
868
1254
  result: finalChunk,
869
1255
  success: true,
870
- type: "rpc"
1256
+ type: "rpc" /* RPC */
871
1257
  };
872
1258
  this._connection.send(JSON.stringify(response));
873
1259
  }
@@ -899,12 +1285,16 @@ function isLocalMode() {
899
1285
 
900
1286
  export {
901
1287
  genericObservability,
1288
+ callable,
902
1289
  unstable_callable,
903
1290
  getCurrentAgent,
904
1291
  Agent,
905
1292
  routeAgentRequest,
1293
+ createHeaderBasedEmailResolver,
1294
+ createAddressBasedEmailResolver,
1295
+ createCatchAllEmailResolver,
906
1296
  routeAgentEmail,
907
1297
  getAgentByName,
908
1298
  StreamingResponse
909
1299
  };
910
- //# sourceMappingURL=chunk-JFRK72K3.js.map
1300
+ //# sourceMappingURL=chunk-M5SZRJTA.js.map