agents 0.0.103 → 0.0.104

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.
@@ -1,21 +1,22 @@
1
1
  import {
2
2
  MCPClientManager
3
- } from "./chunk-E3LCYPCB.js";
3
+ } from "./chunk-MW5BQ2FW.js";
4
4
  import {
5
5
  DurableObjectOAuthClientProvider
6
- } from "./chunk-767EASBA.js";
6
+ } from "./chunk-PVQZBKN7.js";
7
7
  import {
8
8
  camelCaseToKebabCase
9
- } from "./chunk-NKZZ66QY.js";
9
+ } from "./chunk-KUH345EY.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
22
  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);
@@ -46,12 +47,21 @@ function getCurrentAgent() {
46
47
  return {
47
48
  agent: void 0,
48
49
  connection: void 0,
49
- request: void 0
50
+ request: void 0,
51
+ email: void 0
50
52
  };
51
53
  }
52
54
  return store;
53
55
  }
54
- var Agent = class extends Server {
56
+ function withAgentContext(method) {
57
+ return function(...args) {
58
+ const { connection, request, email } = getCurrentAgent();
59
+ return agentContext.run({ agent: this, connection, request, email }, () => {
60
+ return method.apply(this, args);
61
+ });
62
+ };
63
+ }
64
+ var _Agent = class _Agent extends Server {
55
65
  constructor(ctx, env) {
56
66
  super(ctx, env);
57
67
  this._state = DEFAULT_STATE;
@@ -66,6 +76,7 @@ var Agent = class extends Server {
66
76
  * The observability implementation to use for the Agent
67
77
  */
68
78
  this.observability = genericObservability;
79
+ this._flushingQueue = false;
69
80
  /**
70
81
  * Method called when an alarm fires.
71
82
  * Executes any scheduled tasks that are due.
@@ -79,52 +90,68 @@ var Agent = class extends Server {
79
90
  const result = this.sql`
80
91
  SELECT * FROM cf_agents_schedules WHERE time <= ${now}
81
92
  `;
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
- }
93
+ if (result && Array.isArray(result)) {
94
+ for (const row of result) {
95
+ const callback = this[row.callback];
96
+ if (!callback) {
97
+ console.error(`callback ${row.callback} not found`);
98
+ continue;
106
99
  }
107
- );
108
- if (row.type === "cron") {
109
- const nextExecutionTime = getNextCronTime(row.cron);
110
- const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1e3);
111
- this.sql`
100
+ await agentContext.run(
101
+ {
102
+ agent: this,
103
+ connection: void 0,
104
+ request: void 0,
105
+ email: void 0
106
+ },
107
+ async () => {
108
+ try {
109
+ this.observability?.emit(
110
+ {
111
+ displayMessage: `Schedule ${row.id} executed`,
112
+ id: nanoid(),
113
+ payload: row,
114
+ timestamp: Date.now(),
115
+ type: "schedule:execute"
116
+ },
117
+ this.ctx
118
+ );
119
+ await callback.bind(this)(JSON.parse(row.payload), row);
120
+ } catch (e) {
121
+ console.error(`error executing callback "${row.callback}"`, e);
122
+ }
123
+ }
124
+ );
125
+ if (row.type === "cron") {
126
+ const nextExecutionTime = getNextCronTime(row.cron);
127
+ const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1e3);
128
+ this.sql`
112
129
  UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}
113
130
  `;
114
- } else {
115
- this.sql`
131
+ } else {
132
+ this.sql`
116
133
  DELETE FROM cf_agents_schedules WHERE id = ${row.id}
117
134
  `;
135
+ }
118
136
  }
119
137
  }
120
138
  await this._scheduleNextAlarm();
121
139
  };
140
+ this._autoWrapCustomMethods();
122
141
  this.sql`
123
142
  CREATE TABLE IF NOT EXISTS cf_agents_state (
124
143
  id TEXT PRIMARY KEY NOT NULL,
125
144
  state TEXT
126
145
  )
127
146
  `;
147
+ this.sql`
148
+ CREATE TABLE IF NOT EXISTS cf_agents_queues (
149
+ id TEXT PRIMARY KEY NOT NULL,
150
+ payload TEXT,
151
+ callback TEXT,
152
+ created_at INTEGER DEFAULT (unixepoch())
153
+ )
154
+ `;
128
155
  void this.ctx.blockConcurrencyWhile(async () => {
129
156
  return this._tryCatch(async () => {
130
157
  this.sql`
@@ -156,7 +183,7 @@ var Agent = class extends Server {
156
183
  const _onRequest = this.onRequest.bind(this);
157
184
  this.onRequest = (request) => {
158
185
  return agentContext.run(
159
- { agent: this, connection: void 0, request },
186
+ { agent: this, connection: void 0, request, email: void 0 },
160
187
  async () => {
161
188
  if (this.mcp.isCallbackRequest(request)) {
162
189
  await this.mcp.handleCallbackRequest(request);
@@ -178,7 +205,7 @@ var Agent = class extends Server {
178
205
  const _onMessage = this.onMessage.bind(this);
179
206
  this.onMessage = async (connection, message) => {
180
207
  return agentContext.run(
181
- { agent: this, connection, request: void 0 },
208
+ { agent: this, connection, request: void 0, email: void 0 },
182
209
  async () => {
183
210
  if (typeof message !== "string") {
184
211
  return this._tryCatch(() => _onMessage(connection, message));
@@ -252,7 +279,7 @@ var Agent = class extends Server {
252
279
  const _onConnect = this.onConnect.bind(this);
253
280
  this.onConnect = (connection, ctx2) => {
254
281
  return agentContext.run(
255
- { agent: this, connection, request: ctx2.request },
282
+ { agent: this, connection, request: ctx2.request, email: void 0 },
256
283
  async () => {
257
284
  setTimeout(() => {
258
285
  if (this.state) {
@@ -289,32 +316,39 @@ var Agent = class extends Server {
289
316
  const _onStart = this.onStart.bind(this);
290
317
  this.onStart = async () => {
291
318
  return agentContext.run(
292
- { agent: this, connection: void 0, request: void 0 },
319
+ {
320
+ agent: this,
321
+ connection: void 0,
322
+ request: void 0,
323
+ email: void 0
324
+ },
293
325
  async () => {
294
326
  const servers = this.sql`
295
327
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
296
328
  `;
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
- this.broadcast(
312
- JSON.stringify({
313
- mcp: this.getMcpServers(),
314
- type: "cf_agent_mcp_servers"
329
+ if (servers && Array.isArray(servers) && servers.length > 0) {
330
+ Promise.allSettled(
331
+ servers.map((server) => {
332
+ return this._connectToMcpServerInternal(
333
+ server.name,
334
+ server.server_url,
335
+ server.callback_url,
336
+ server.server_options ? JSON.parse(server.server_options) : void 0,
337
+ {
338
+ id: server.id,
339
+ oauthClientId: server.client_id ?? void 0
340
+ }
341
+ );
315
342
  })
316
- );
317
- });
343
+ ).then((_results) => {
344
+ this.broadcast(
345
+ JSON.stringify({
346
+ mcp: this.getMcpServers(),
347
+ type: "cf_agent_mcp_servers"
348
+ })
349
+ );
350
+ });
351
+ }
318
352
  await this._tryCatch(() => _onStart());
319
353
  }
320
354
  );
@@ -384,9 +418,9 @@ var Agent = class extends Server {
384
418
  source !== "server" ? [source.id] : []
385
419
  );
386
420
  return this._tryCatch(() => {
387
- const { connection, request } = agentContext.getStore() || {};
421
+ const { connection, request, email } = agentContext.getStore() || {};
388
422
  return agentContext.run(
389
- { agent: this, connection, request },
423
+ { agent: this, connection, request, email },
390
424
  async () => {
391
425
  this.observability?.emit(
392
426
  {
@@ -422,18 +456,67 @@ var Agent = class extends Server {
422
456
  onStateUpdate(state, source) {
423
457
  }
424
458
  /**
425
- * Called when the Agent receives an email
459
+ * Called when the Agent receives an email via routeAgentEmail()
460
+ * Override this method to handle incoming emails
426
461
  * @param email Email message to process
427
462
  */
428
- // biome-ignore lint/correctness/noUnusedFunctionParameters: overridden later
429
- onEmail(email) {
463
+ async _onEmail(email) {
430
464
  return agentContext.run(
431
- { agent: this, connection: void 0, request: void 0 },
465
+ { agent: this, connection: void 0, request: void 0, email },
432
466
  async () => {
433
- console.error("onEmail not implemented");
467
+ if ("onEmail" in this && typeof this.onEmail === "function") {
468
+ return this._tryCatch(
469
+ () => this.onEmail(email)
470
+ );
471
+ } else {
472
+ console.log("Received email from:", email.from, "to:", email.to);
473
+ console.log("Subject:", email.headers.get("subject"));
474
+ console.log(
475
+ "Implement onEmail(email: AgentEmail): Promise<void> in your agent to process emails"
476
+ );
477
+ }
434
478
  }
435
479
  );
436
480
  }
481
+ /**
482
+ * Reply to an email
483
+ * @param email The email to reply to
484
+ * @param options Options for the reply
485
+ * @returns void
486
+ */
487
+ async replyToEmail(email, options) {
488
+ return this._tryCatch(async () => {
489
+ const agentName = camelCaseToKebabCase(this._ParentClass.name);
490
+ const agentId = this.name;
491
+ const { createMimeMessage } = await import("mimetext");
492
+ const msg = createMimeMessage();
493
+ msg.setSender({ addr: email.to, name: options.fromName });
494
+ msg.setRecipient(email.from);
495
+ msg.setSubject(
496
+ options.subject || `Re: ${email.headers.get("subject")}` || "No subject"
497
+ );
498
+ msg.addMessage({
499
+ contentType: options.contentType || "text/plain",
500
+ data: options.body
501
+ });
502
+ const domain = email.from.split("@")[1];
503
+ const messageId = `<${agentId}@${domain}>`;
504
+ msg.setHeader("In-Reply-To", email.headers.get("Message-ID"));
505
+ msg.setHeader("Message-ID", messageId);
506
+ msg.setHeader("X-Agent-Name", agentName);
507
+ msg.setHeader("X-Agent-ID", agentId);
508
+ if (options.headers) {
509
+ for (const [key, value] of Object.entries(options.headers)) {
510
+ msg.setHeader(key, value);
511
+ }
512
+ }
513
+ await email.reply({
514
+ from: email.to,
515
+ raw: msg.asRaw(),
516
+ to: email.from
517
+ });
518
+ });
519
+ }
437
520
  async _tryCatch(fn) {
438
521
  try {
439
522
  return await fn();
@@ -441,6 +524,55 @@ var Agent = class extends Server {
441
524
  throw this.onError(e);
442
525
  }
443
526
  }
527
+ /**
528
+ * Automatically wrap custom methods with agent context
529
+ * This ensures getCurrentAgent() works in all custom methods without decorators
530
+ */
531
+ _autoWrapCustomMethods() {
532
+ const basePrototypes = [_Agent.prototype, Server.prototype];
533
+ const baseMethods = /* @__PURE__ */ new Set();
534
+ for (const baseProto of basePrototypes) {
535
+ let proto2 = baseProto;
536
+ while (proto2 && proto2 !== Object.prototype) {
537
+ const methodNames = Object.getOwnPropertyNames(proto2);
538
+ for (const methodName of methodNames) {
539
+ baseMethods.add(methodName);
540
+ }
541
+ proto2 = Object.getPrototypeOf(proto2);
542
+ }
543
+ }
544
+ let proto = Object.getPrototypeOf(this);
545
+ let depth = 0;
546
+ while (proto && proto !== Object.prototype && depth < 10) {
547
+ const methodNames = Object.getOwnPropertyNames(proto);
548
+ for (const methodName of methodNames) {
549
+ if (baseMethods.has(methodName) || methodName.startsWith("_") || typeof this[methodName] !== "function") {
550
+ continue;
551
+ }
552
+ if (!baseMethods.has(methodName)) {
553
+ const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
554
+ if (descriptor && typeof descriptor.value === "function") {
555
+ const wrappedFunction = withAgentContext(
556
+ // biome-ignore lint/suspicious/noExplicitAny: I can't typescript
557
+ this[methodName]
558
+ // biome-ignore lint/suspicious/noExplicitAny: I can't typescript
559
+ );
560
+ if (this._isCallable(methodName)) {
561
+ callableMetadata.set(
562
+ wrappedFunction,
563
+ callableMetadata.get(
564
+ this[methodName]
565
+ )
566
+ );
567
+ }
568
+ this.constructor.prototype[methodName] = wrappedFunction;
569
+ }
570
+ }
571
+ }
572
+ proto = Object.getPrototypeOf(proto);
573
+ depth++;
574
+ }
575
+ }
444
576
  onError(connectionOrError, error) {
445
577
  let theError;
446
578
  if (connectionOrError && error) {
@@ -466,6 +598,112 @@ var Agent = class extends Server {
466
598
  render() {
467
599
  throw new Error("Not implemented");
468
600
  }
601
+ /**
602
+ * Queue a task to be executed in the future
603
+ * @param payload Payload to pass to the callback
604
+ * @param callback Name of the method to call
605
+ * @returns The ID of the queued task
606
+ */
607
+ async queue(callback, payload) {
608
+ const id = nanoid(9);
609
+ if (typeof callback !== "string") {
610
+ throw new Error("Callback must be a string");
611
+ }
612
+ if (typeof this[callback] !== "function") {
613
+ throw new Error(`this.${callback} is not a function`);
614
+ }
615
+ this.sql`
616
+ INSERT OR REPLACE INTO cf_agents_queues (id, payload, callback)
617
+ VALUES (${id}, ${JSON.stringify(payload)}, ${callback})
618
+ `;
619
+ void this._flushQueue().catch((e) => {
620
+ console.error("Error flushing queue:", e);
621
+ });
622
+ return id;
623
+ }
624
+ async _flushQueue() {
625
+ if (this._flushingQueue) {
626
+ return;
627
+ }
628
+ this._flushingQueue = true;
629
+ while (true) {
630
+ const executed = [];
631
+ const result = this.sql`
632
+ SELECT * FROM cf_agents_queues
633
+ ORDER BY created_at ASC
634
+ `;
635
+ if (!result || result.length === 0) {
636
+ break;
637
+ }
638
+ for (const row of result || []) {
639
+ const callback = this[row.callback];
640
+ if (!callback) {
641
+ console.error(`callback ${row.callback} not found`);
642
+ continue;
643
+ }
644
+ const { connection, request, email } = agentContext.getStore() || {};
645
+ await agentContext.run(
646
+ {
647
+ agent: this,
648
+ connection,
649
+ request,
650
+ email
651
+ },
652
+ async () => {
653
+ await callback.bind(this)(JSON.parse(row.payload), row);
654
+ executed.push(row.id);
655
+ }
656
+ );
657
+ }
658
+ for (const id of executed) {
659
+ await this.dequeue(id);
660
+ }
661
+ }
662
+ this._flushingQueue = false;
663
+ }
664
+ /**
665
+ * Dequeue a task by ID
666
+ * @param id ID of the task to dequeue
667
+ */
668
+ async dequeue(id) {
669
+ this.sql`DELETE FROM cf_agents_queues WHERE id = ${id}`;
670
+ }
671
+ /**
672
+ * Dequeue all tasks
673
+ */
674
+ async dequeueAll() {
675
+ this.sql`DELETE FROM cf_agents_queues`;
676
+ }
677
+ /**
678
+ * Dequeue all tasks by callback
679
+ * @param callback Name of the callback to dequeue
680
+ */
681
+ async dequeueAllByCallback(callback) {
682
+ this.sql`DELETE FROM cf_agents_queues WHERE callback = ${callback}`;
683
+ }
684
+ /**
685
+ * Get a queued task by ID
686
+ * @param id ID of the task to get
687
+ * @returns The task or undefined if not found
688
+ */
689
+ async getQueue(id) {
690
+ const result = this.sql`
691
+ SELECT * FROM cf_agents_queues WHERE id = ${id}
692
+ `;
693
+ return result ? { ...result[0], payload: JSON.parse(result[0].payload) } : void 0;
694
+ }
695
+ /**
696
+ * Get all queues by key and value
697
+ * @param key Key to filter by
698
+ * @param value Value to filter by
699
+ * @returns Array of matching QueueItem objects
700
+ */
701
+ async getQueues(key, value) {
702
+ const result = this.sql`
703
+ SELECT * FROM cf_agents_queues
704
+ `;
705
+ return result.filter((row) => JSON.parse(row.payload)[key] === value);
706
+ }
469
707
  /**
470
708
  * Schedule a task to be executed in the future
471
709
  * @template T Type of the payload data
@@ -646,6 +884,7 @@ var Agent = class extends Server {
646
884
  this.sql`DROP TABLE IF EXISTS cf_agents_state`;
647
885
  this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;
648
886
  this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
887
+ this.sql`DROP TABLE IF EXISTS cf_agents_queues`;
649
888
  await this.ctx.storage.deleteAlarm();
650
889
  await this.ctx.storage.deleteAll();
651
890
  this.ctx.abort("destroyed");
@@ -767,17 +1006,19 @@ var Agent = class extends Server {
767
1006
  const servers = this.sql`
768
1007
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
769
1008
  `;
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
- };
1009
+ if (servers && Array.isArray(servers) && servers.length > 0) {
1010
+ for (const server of servers) {
1011
+ const serverConn = this.mcp.mcpConnections[server.id];
1012
+ mcpState.servers[server.id] = {
1013
+ auth_url: server.auth_url,
1014
+ capabilities: serverConn?.serverCapabilities ?? null,
1015
+ instructions: serverConn?.instructions ?? null,
1016
+ name: server.name,
1017
+ server_url: server.server_url,
1018
+ // mark as "authenticating" because the server isn't automatically connected, so it's pending authenticating
1019
+ state: serverConn?.connectionState ?? "authenticating"
1020
+ };
1021
+ }
781
1022
  }
782
1023
  return mcpState;
783
1024
  }
@@ -785,11 +1026,12 @@ var Agent = class extends Server {
785
1026
  /**
786
1027
  * Agent configuration options
787
1028
  */
788
- Agent.options = {
1029
+ _Agent.options = {
789
1030
  /** Whether the Agent should hibernate when inactive */
790
1031
  hibernate: true
791
1032
  // default to hibernate
792
1033
  };
1034
+ var Agent = _Agent;
793
1035
  async function routeAgentRequest(request, env, options) {
794
1036
  const corsHeaders = options?.cors === true ? {
795
1037
  "Access-Control-Allow-Credentials": "true",
@@ -825,7 +1067,116 @@ async function routeAgentRequest(request, env, options) {
825
1067
  }
826
1068
  return response;
827
1069
  }
828
- async function routeAgentEmail(_email, _env, _options) {
1070
+ function createHeaderBasedEmailResolver() {
1071
+ return async (email, _env) => {
1072
+ const messageId = email.headers.get("message-id");
1073
+ if (messageId) {
1074
+ const messageIdMatch = messageId.match(/<([^@]+)@([^>]+)>/);
1075
+ if (messageIdMatch) {
1076
+ const [, agentId2, domain] = messageIdMatch;
1077
+ const agentName2 = domain.split(".")[0];
1078
+ return { agentName: agentName2, agentId: agentId2 };
1079
+ }
1080
+ }
1081
+ const references = email.headers.get("references");
1082
+ if (references) {
1083
+ const referencesMatch = references.match(
1084
+ /<([A-Za-z0-9+/]{43}=)@([^>]+)>/
1085
+ );
1086
+ if (referencesMatch) {
1087
+ const [, base64Id, domain] = referencesMatch;
1088
+ const agentId2 = Buffer.from(base64Id, "base64").toString("hex");
1089
+ const agentName2 = domain.split(".")[0];
1090
+ return { agentName: agentName2, agentId: agentId2 };
1091
+ }
1092
+ }
1093
+ const agentName = email.headers.get("x-agent-name");
1094
+ const agentId = email.headers.get("x-agent-id");
1095
+ if (agentName && agentId) {
1096
+ return { agentName, agentId };
1097
+ }
1098
+ return null;
1099
+ };
1100
+ }
1101
+ function createAddressBasedEmailResolver(defaultAgentName) {
1102
+ return async (email, _env) => {
1103
+ const emailMatch = email.to.match(/^([^+@]+)(?:\+([^@]+))?@(.+)$/);
1104
+ if (!emailMatch) {
1105
+ return null;
1106
+ }
1107
+ const [, localPart, subAddress] = emailMatch;
1108
+ if (subAddress) {
1109
+ return {
1110
+ agentName: localPart,
1111
+ agentId: subAddress
1112
+ };
1113
+ }
1114
+ return {
1115
+ agentName: defaultAgentName,
1116
+ agentId: localPart
1117
+ };
1118
+ };
1119
+ }
1120
+ function createCatchAllEmailResolver(agentName, agentId) {
1121
+ return async () => ({ agentName, agentId });
1122
+ }
1123
+ async function routeAgentEmail(email, env, options) {
1124
+ const routingInfo = await options.resolver(email, env);
1125
+ if (!routingInfo) {
1126
+ console.warn("No routing information found for email, dropping message");
1127
+ return;
1128
+ }
1129
+ const namespaceBinding = env[routingInfo.agentName];
1130
+ if (!namespaceBinding) {
1131
+ throw new Error(
1132
+ `Agent namespace '${routingInfo.agentName}' not found in environment`
1133
+ );
1134
+ }
1135
+ if (typeof namespaceBinding !== "object" || !("idFromName" in namespaceBinding) || typeof namespaceBinding.idFromName !== "function") {
1136
+ throw new Error(
1137
+ `Environment binding '${routingInfo.agentName}' is not an AgentNamespace (found: ${typeof namespaceBinding})`
1138
+ );
1139
+ }
1140
+ const namespace = namespaceBinding;
1141
+ const agent = await getAgentByName(namespace, routingInfo.agentId);
1142
+ const serialisableEmail = {
1143
+ getRaw: async () => {
1144
+ const reader = email.raw.getReader();
1145
+ const chunks = [];
1146
+ let done = false;
1147
+ while (!done) {
1148
+ const { value, done: readerDone } = await reader.read();
1149
+ done = readerDone;
1150
+ if (value) {
1151
+ chunks.push(value);
1152
+ }
1153
+ }
1154
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
1155
+ const combined = new Uint8Array(totalLength);
1156
+ let offset = 0;
1157
+ for (const chunk of chunks) {
1158
+ combined.set(chunk, offset);
1159
+ offset += chunk.length;
1160
+ }
1161
+ return combined;
1162
+ },
1163
+ headers: email.headers,
1164
+ rawSize: email.rawSize,
1165
+ setReject: (reason) => {
1166
+ email.setReject(reason);
1167
+ },
1168
+ forward: (rcptTo, headers) => {
1169
+ return email.forward(rcptTo, headers);
1170
+ },
1171
+ reply: (options2) => {
1172
+ return email.reply(
1173
+ new EmailMessage(options2.from, options2.to, options2.raw)
1174
+ );
1175
+ },
1176
+ from: email.from,
1177
+ to: email.to
1178
+ };
1179
+ await agent._onEmail(serialisableEmail);
829
1180
  }
830
1181
  async function getAgentByName(namespace, name, options) {
831
1182
  return getServerByName(namespace, name, options);
@@ -903,8 +1254,11 @@ export {
903
1254
  getCurrentAgent,
904
1255
  Agent,
905
1256
  routeAgentRequest,
1257
+ createHeaderBasedEmailResolver,
1258
+ createAddressBasedEmailResolver,
1259
+ createCatchAllEmailResolver,
906
1260
  routeAgentEmail,
907
1261
  getAgentByName,
908
1262
  StreamingResponse
909
1263
  };
910
- //# sourceMappingURL=chunk-JFRK72K3.js.map
1264
+ //# sourceMappingURL=chunk-5YIRLLUX.js.map