agents 0.0.0-0ac89c6 → 0.0.0-0bb74b8

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 (44) hide show
  1. package/README.md +22 -22
  2. package/dist/ai-chat-agent.d.ts +5 -4
  3. package/dist/ai-chat-agent.js +64 -26
  4. package/dist/ai-chat-agent.js.map +1 -1
  5. package/dist/ai-react.d.ts +10 -9
  6. package/dist/ai-react.js +27 -27
  7. package/dist/ai-react.js.map +1 -1
  8. package/dist/{chunk-QSGN3REV.js → chunk-KUH345EY.js} +8 -15
  9. package/dist/chunk-KUH345EY.js.map +1 -0
  10. package/dist/{chunk-4ARKO5R4.js → chunk-MGHXAF5T.js} +390 -89
  11. package/dist/chunk-MGHXAF5T.js.map +1 -0
  12. package/dist/{chunk-Y67CHZBI.js → chunk-MW5BQ2FW.js} +23 -18
  13. package/dist/chunk-MW5BQ2FW.js.map +1 -0
  14. package/dist/{chunk-BZXOAZUX.js → chunk-PVQZBKN7.js} +5 -5
  15. package/dist/chunk-PVQZBKN7.js.map +1 -0
  16. package/dist/client.d.ts +8 -2
  17. package/dist/client.js +1 -1
  18. package/dist/index-CEVsIbwa.d.ts +565 -0
  19. package/dist/index.d.ts +32 -398
  20. package/dist/index.js +10 -4
  21. package/dist/mcp/client.d.ts +281 -9
  22. package/dist/mcp/client.js +1 -1
  23. package/dist/mcp/do-oauth-client-provider.js +1 -1
  24. package/dist/mcp/index.d.ts +9 -9
  25. package/dist/mcp/index.js +55 -51
  26. package/dist/mcp/index.js.map +1 -1
  27. package/dist/observability/index.d.ts +12 -0
  28. package/dist/observability/index.js +10 -0
  29. package/dist/observability/index.js.map +1 -0
  30. package/dist/react.d.ts +56 -38
  31. package/dist/react.js +16 -6
  32. package/dist/react.js.map +1 -1
  33. package/dist/schedule.d.ts +6 -6
  34. package/dist/schedule.js +4 -4
  35. package/dist/schedule.js.map +1 -1
  36. package/dist/serializable.d.ts +32 -0
  37. package/dist/serializable.js +1 -0
  38. package/dist/serializable.js.map +1 -0
  39. package/package.json +76 -72
  40. package/src/index.ts +517 -126
  41. package/dist/chunk-4ARKO5R4.js.map +0 -1
  42. package/dist/chunk-BZXOAZUX.js.map +0 -1
  43. package/dist/chunk-QSGN3REV.js.map +0 -1
  44. package/dist/chunk-Y67CHZBI.js.map +0 -1
@@ -1,22 +1,23 @@
1
+ import {
2
+ MCPClientManager
3
+ } from "./chunk-MW5BQ2FW.js";
1
4
  import {
2
5
  DurableObjectOAuthClientProvider
3
- } from "./chunk-BZXOAZUX.js";
6
+ } from "./chunk-PVQZBKN7.js";
4
7
  import {
5
8
  camelCaseToKebabCase
6
- } from "./chunk-QSGN3REV.js";
7
- import {
8
- MCPClientManager
9
- } from "./chunk-Y67CHZBI.js";
9
+ } from "./chunk-KUH345EY.js";
10
10
 
11
11
  // src/index.ts
12
+ import { AsyncLocalStorage } from "async_hooks";
13
+ import { parseCronExpression } from "cron-schedule";
14
+ import { nanoid } from "nanoid";
15
+ import { EmailMessage } from "cloudflare:email";
12
16
  import {
13
17
  Server,
14
- routePartykitRequest,
15
- getServerByName
18
+ getServerByName,
19
+ routePartykitRequest
16
20
  } from "partyserver";
17
- import { parseCronExpression } from "cron-schedule";
18
- import { nanoid } from "nanoid";
19
- import { AsyncLocalStorage } from "node:async_hooks";
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);
22
23
  }
@@ -62,6 +63,10 @@ var Agent = class extends Server {
62
63
  * Override to provide default state values
63
64
  */
64
65
  this.initialState = DEFAULT_STATE;
66
+ /**
67
+ * The observability implementation to use for the Agent
68
+ */
69
+ this.observability = genericObservability;
65
70
  /**
66
71
  * Method called when an alarm fires.
67
72
  * Executes any scheduled tasks that are due.
@@ -82,9 +87,24 @@ var Agent = class extends Server {
82
87
  continue;
83
88
  }
84
89
  await agentContext.run(
85
- { agent: this, connection: void 0, request: void 0 },
90
+ {
91
+ agent: this,
92
+ connection: void 0,
93
+ request: void 0,
94
+ email: void 0
95
+ },
86
96
  async () => {
87
97
  try {
98
+ this.observability?.emit(
99
+ {
100
+ displayMessage: `Schedule ${row.id} executed`,
101
+ id: nanoid(),
102
+ payload: row,
103
+ timestamp: Date.now(),
104
+ type: "schedule:execute"
105
+ },
106
+ this.ctx
107
+ );
88
108
  await callback.bind(this)(JSON.parse(row.payload), row);
89
109
  } catch (e) {
90
110
  console.error(`error executing callback "${row.callback}"`, e);
@@ -142,19 +162,19 @@ var Agent = class extends Server {
142
162
  const _onRequest = this.onRequest.bind(this);
143
163
  this.onRequest = (request) => {
144
164
  return agentContext.run(
145
- { agent: this, connection: void 0, request },
165
+ { agent: this, connection: void 0, request, email: void 0 },
146
166
  async () => {
147
167
  if (this.mcp.isCallbackRequest(request)) {
148
168
  await this.mcp.handleCallbackRequest(request);
149
169
  this.broadcast(
150
170
  JSON.stringify({
151
- type: "cf_agent_mcp_servers",
152
- mcp: this._getMcpServerStateInternal()
171
+ mcp: this.getMcpServers(),
172
+ type: "cf_agent_mcp_servers"
153
173
  })
154
174
  );
155
175
  return new Response("<script>window.close();</script>", {
156
- status: 200,
157
- headers: { "content-type": "text/html" }
176
+ headers: { "content-type": "text/html" },
177
+ status: 200
158
178
  });
159
179
  }
160
180
  return this._tryCatch(() => _onRequest(request));
@@ -164,7 +184,7 @@ var Agent = class extends Server {
164
184
  const _onMessage = this.onMessage.bind(this);
165
185
  this.onMessage = async (connection, message) => {
166
186
  return agentContext.run(
167
- { agent: this, connection, request: void 0 },
187
+ { agent: this, connection, request: void 0, email: void 0 },
168
188
  async () => {
169
189
  if (typeof message !== "string") {
170
190
  return this._tryCatch(() => _onMessage(connection, message));
@@ -172,7 +192,7 @@ var Agent = class extends Server {
172
192
  let parsed;
173
193
  try {
174
194
  parsed = JSON.parse(message);
175
- } catch (e) {
195
+ } catch (_e) {
176
196
  return this._tryCatch(() => _onMessage(connection, message));
177
197
  }
178
198
  if (isStateUpdateMessage(parsed)) {
@@ -196,20 +216,35 @@ var Agent = class extends Server {
196
216
  return;
197
217
  }
198
218
  const result = await methodFn.apply(this, args);
219
+ this.observability?.emit(
220
+ {
221
+ displayMessage: `RPC call to ${method}`,
222
+ id: nanoid(),
223
+ payload: {
224
+ args,
225
+ method,
226
+ streaming: metadata?.streaming,
227
+ success: true
228
+ },
229
+ timestamp: Date.now(),
230
+ type: "rpc"
231
+ },
232
+ this.ctx
233
+ );
199
234
  const response = {
200
- type: "rpc",
235
+ done: true,
201
236
  id,
202
- success: true,
203
237
  result,
204
- done: true
238
+ success: true,
239
+ type: "rpc"
205
240
  };
206
241
  connection.send(JSON.stringify(response));
207
242
  } catch (e) {
208
243
  const response = {
209
- type: "rpc",
244
+ error: e instanceof Error ? e.message : "Unknown error occurred",
210
245
  id: parsed.id,
211
246
  success: false,
212
- error: e instanceof Error ? e.message : "Unknown error occurred"
247
+ type: "rpc"
213
248
  };
214
249
  connection.send(JSON.stringify(response));
215
250
  console.error("RPC error:", e);
@@ -223,23 +258,35 @@ var Agent = class extends Server {
223
258
  const _onConnect = this.onConnect.bind(this);
224
259
  this.onConnect = (connection, ctx2) => {
225
260
  return agentContext.run(
226
- { agent: this, connection, request: ctx2.request },
261
+ { agent: this, connection, request: ctx2.request, email: void 0 },
227
262
  async () => {
228
263
  setTimeout(() => {
229
264
  if (this.state) {
230
265
  connection.send(
231
266
  JSON.stringify({
232
- type: "cf_agent_state",
233
- state: this.state
267
+ state: this.state,
268
+ type: "cf_agent_state"
234
269
  })
235
270
  );
236
271
  }
237
272
  connection.send(
238
273
  JSON.stringify({
239
- type: "cf_agent_mcp_servers",
240
- mcp: this._getMcpServerStateInternal()
274
+ mcp: this.getMcpServers(),
275
+ type: "cf_agent_mcp_servers"
241
276
  })
242
277
  );
278
+ this.observability?.emit(
279
+ {
280
+ displayMessage: "Connection established",
281
+ id: nanoid(),
282
+ payload: {
283
+ connectionId: connection.id
284
+ },
285
+ timestamp: Date.now(),
286
+ type: "connect"
287
+ },
288
+ this.ctx
289
+ );
243
290
  return this._tryCatch(() => _onConnect(connection, ctx2));
244
291
  }, 20);
245
292
  }
@@ -248,12 +295,17 @@ var Agent = class extends Server {
248
295
  const _onStart = this.onStart.bind(this);
249
296
  this.onStart = async () => {
250
297
  return agentContext.run(
251
- { agent: this, connection: void 0, request: void 0 },
298
+ {
299
+ agent: this,
300
+ connection: void 0,
301
+ request: void 0,
302
+ email: void 0
303
+ },
252
304
  async () => {
253
305
  const servers = this.sql`
254
306
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
255
307
  `;
256
- await Promise.allSettled(
308
+ Promise.allSettled(
257
309
  servers.map((server) => {
258
310
  return this._connectToMcpServerInternal(
259
311
  server.name,
@@ -266,13 +318,14 @@ var Agent = class extends Server {
266
318
  }
267
319
  );
268
320
  })
269
- );
270
- this.broadcast(
271
- JSON.stringify({
272
- type: "cf_agent_mcp_servers",
273
- mcp: this._getMcpServerStateInternal()
274
- })
275
- );
321
+ ).then((_results) => {
322
+ this.broadcast(
323
+ JSON.stringify({
324
+ mcp: this.getMcpServers(),
325
+ type: "cf_agent_mcp_servers"
326
+ })
327
+ );
328
+ });
276
329
  await this._tryCatch(() => _onStart());
277
330
  }
278
331
  );
@@ -324,6 +377,7 @@ var Agent = class extends Server {
324
377
  }
325
378
  }
326
379
  _setStateInternal(state, source = "server") {
380
+ const previousState = this._state;
327
381
  this._state = state;
328
382
  this.sql`
329
383
  INSERT OR REPLACE INTO cf_agents_state (id, state)
@@ -335,16 +389,29 @@ var Agent = class extends Server {
335
389
  `;
336
390
  this.broadcast(
337
391
  JSON.stringify({
338
- type: "cf_agent_state",
339
- state
392
+ state,
393
+ type: "cf_agent_state"
340
394
  }),
341
395
  source !== "server" ? [source.id] : []
342
396
  );
343
397
  return this._tryCatch(() => {
344
- const { connection, request } = agentContext.getStore() || {};
398
+ const { connection, request, email } = agentContext.getStore() || {};
345
399
  return agentContext.run(
346
- { agent: this, connection, request },
400
+ { agent: this, connection, request, email },
347
401
  async () => {
402
+ this.observability?.emit(
403
+ {
404
+ displayMessage: "State updated",
405
+ id: nanoid(),
406
+ payload: {
407
+ previousState,
408
+ state
409
+ },
410
+ timestamp: Date.now(),
411
+ type: "state:update"
412
+ },
413
+ this.ctx
414
+ );
348
415
  return this.onStateUpdate(state, source);
349
416
  }
350
417
  );
@@ -362,20 +429,71 @@ var Agent = class extends Server {
362
429
  * @param state Updated state
363
430
  * @param source Source of the state update ("server" or a client connection)
364
431
  */
432
+ // biome-ignore lint/correctness/noUnusedFunctionParameters: overridden later
365
433
  onStateUpdate(state, source) {
366
434
  }
367
435
  /**
368
- * Called when the Agent receives an email
436
+ * Called when the Agent receives an email via routeAgentEmail()
437
+ * Override this method to handle incoming emails
369
438
  * @param email Email message to process
370
439
  */
371
- onEmail(email) {
440
+ async _onEmail(email) {
372
441
  return agentContext.run(
373
- { agent: this, connection: void 0, request: void 0 },
442
+ { agent: this, connection: void 0, request: void 0, email },
374
443
  async () => {
375
- console.error("onEmail not implemented");
444
+ if ("onEmail" in this && typeof this.onEmail === "function") {
445
+ return this._tryCatch(
446
+ () => this.onEmail(email)
447
+ );
448
+ } else {
449
+ console.log("Received email from:", email.from, "to:", email.to);
450
+ console.log("Subject:", email.headers.get("subject"));
451
+ console.log(
452
+ "Implement onEmail(email: AgentEmail): Promise<void> in your agent to process emails"
453
+ );
454
+ }
376
455
  }
377
456
  );
378
457
  }
458
+ /**
459
+ * Reply to an email
460
+ * @param email The email to reply to
461
+ * @param options Options for the reply
462
+ * @returns void
463
+ */
464
+ async replyToEmail(email, options) {
465
+ return this._tryCatch(async () => {
466
+ const agentName = camelCaseToKebabCase(this._ParentClass.name);
467
+ const agentId = this.name;
468
+ const { createMimeMessage } = await import("mimetext");
469
+ const msg = createMimeMessage();
470
+ msg.setSender({ addr: email.to, name: options.fromName });
471
+ msg.setRecipient(email.from);
472
+ msg.setSubject(
473
+ options.subject || `Re: ${email.headers.get("subject")}` || "No subject"
474
+ );
475
+ msg.addMessage({
476
+ contentType: options.contentType || "text/plain",
477
+ data: options.body
478
+ });
479
+ const domain = email.from.split("@")[1];
480
+ const messageId = `<${agentId}@${domain}>`;
481
+ msg.setHeader("In-Reply-To", email.headers.get("Message-ID"));
482
+ msg.setHeader("Message-ID", messageId);
483
+ msg.setHeader("X-Agent-Name", agentName);
484
+ msg.setHeader("X-Agent-ID", agentId);
485
+ if (options.headers) {
486
+ for (const [key, value] of Object.entries(options.headers)) {
487
+ msg.setHeader(key, value);
488
+ }
489
+ }
490
+ await email.reply({
491
+ from: email.to,
492
+ raw: msg.asRaw(),
493
+ to: email.from
494
+ });
495
+ });
496
+ }
379
497
  async _tryCatch(fn) {
380
498
  try {
381
499
  return await fn();
@@ -418,6 +536,16 @@ var Agent = class extends Server {
418
536
  */
419
537
  async schedule(when, callback, payload) {
420
538
  const id = nanoid(9);
539
+ const emitScheduleCreate = (schedule) => this.observability?.emit(
540
+ {
541
+ displayMessage: `Schedule ${schedule.id} created`,
542
+ id: nanoid(),
543
+ payload: schedule,
544
+ timestamp: Date.now(),
545
+ type: "schedule:create"
546
+ },
547
+ this.ctx
548
+ );
421
549
  if (typeof callback !== "string") {
422
550
  throw new Error("Callback must be a string");
423
551
  }
@@ -433,13 +561,15 @@ var Agent = class extends Server {
433
561
  )}, 'scheduled', ${timestamp})
434
562
  `;
435
563
  await this._scheduleNextAlarm();
436
- return {
437
- id,
564
+ const schedule = {
438
565
  callback,
566
+ id,
439
567
  payload,
440
568
  time: timestamp,
441
569
  type: "scheduled"
442
570
  };
571
+ emitScheduleCreate(schedule);
572
+ return schedule;
443
573
  }
444
574
  if (typeof when === "number") {
445
575
  const time = new Date(Date.now() + when * 1e3);
@@ -451,14 +581,16 @@ var Agent = class extends Server {
451
581
  )}, 'delayed', ${when}, ${timestamp})
452
582
  `;
453
583
  await this._scheduleNextAlarm();
454
- return {
455
- id,
584
+ const schedule = {
456
585
  callback,
457
- payload,
458
586
  delayInSeconds: when,
587
+ id,
588
+ payload,
459
589
  time: timestamp,
460
590
  type: "delayed"
461
591
  };
592
+ emitScheduleCreate(schedule);
593
+ return schedule;
462
594
  }
463
595
  if (typeof when === "string") {
464
596
  const nextExecutionTime = getNextCronTime(when);
@@ -470,14 +602,16 @@ var Agent = class extends Server {
470
602
  )}, 'cron', ${when}, ${timestamp})
471
603
  `;
472
604
  await this._scheduleNextAlarm();
473
- return {
474
- id,
605
+ const schedule = {
475
606
  callback,
476
- payload,
477
607
  cron: when,
608
+ id,
609
+ payload,
478
610
  time: timestamp,
479
611
  type: "cron"
480
612
  };
613
+ emitScheduleCreate(schedule);
614
+ return schedule;
481
615
  }
482
616
  throw new Error("Invalid schedule type");
483
617
  }
@@ -535,6 +669,19 @@ var Agent = class extends Server {
535
669
  * @returns true if the task was cancelled, false otherwise
536
670
  */
537
671
  async cancelSchedule(id) {
672
+ const schedule = await this.getSchedule(id);
673
+ if (schedule) {
674
+ this.observability?.emit(
675
+ {
676
+ displayMessage: `Schedule ${id} cancelled`,
677
+ id: nanoid(),
678
+ payload: schedule,
679
+ timestamp: Date.now(),
680
+ type: "schedule:cancel"
681
+ },
682
+ this.ctx
683
+ );
684
+ }
538
685
  this.sql`DELETE FROM cf_agents_schedules WHERE id = ${id}`;
539
686
  await this._scheduleNextAlarm();
540
687
  return true;
@@ -561,6 +708,17 @@ var Agent = class extends Server {
561
708
  this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
562
709
  await this.ctx.storage.deleteAlarm();
563
710
  await this.ctx.storage.deleteAll();
711
+ this.ctx.abort("destroyed");
712
+ this.observability?.emit(
713
+ {
714
+ displayMessage: "Agent destroyed",
715
+ id: nanoid(),
716
+ payload: {},
717
+ timestamp: Date.now(),
718
+ type: "destroy"
719
+ },
720
+ this.ctx
721
+ );
564
722
  }
565
723
  /**
566
724
  * Get all methods marked as callable on this Agent
@@ -586,15 +744,28 @@ var Agent = class extends Server {
586
744
  callbackUrl,
587
745
  options
588
746
  );
747
+ this.sql`
748
+ INSERT
749
+ OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)
750
+ VALUES (
751
+ ${result.id},
752
+ ${serverName},
753
+ ${url},
754
+ ${result.clientId ?? null},
755
+ ${result.authUrl ?? null},
756
+ ${callbackUrl},
757
+ ${options ? JSON.stringify(options) : null}
758
+ );
759
+ `;
589
760
  this.broadcast(
590
761
  JSON.stringify({
591
- type: "cf_agent_mcp_servers",
592
- mcp: this._getMcpServerStateInternal()
762
+ mcp: this.getMcpServers(),
763
+ type: "cf_agent_mcp_servers"
593
764
  })
594
765
  );
595
766
  return result;
596
767
  }
597
- async _connectToMcpServerInternal(serverName, url, callbackUrl, options, reconnect) {
768
+ async _connectToMcpServerInternal(_serverName, url, callbackUrl, options, reconnect) {
598
769
  const authProvider = new DurableObjectOAuthClientProvider(
599
770
  this.ctx.storage,
600
771
  this.name,
@@ -621,28 +792,17 @@ var Agent = class extends Server {
621
792
  };
622
793
  }
623
794
  const { id, authUrl, clientId } = await this.mcp.connect(url, {
795
+ client: options?.client,
624
796
  reconnect,
625
797
  transport: {
626
798
  ...headerTransportOpts,
627
799
  authProvider
628
- },
629
- client: options?.client
800
+ }
630
801
  });
631
- this.sql`
632
- INSERT OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)
633
- VALUES (
634
- ${id},
635
- ${serverName},
636
- ${url},
637
- ${clientId ?? null},
638
- ${authUrl ?? null},
639
- ${callbackUrl},
640
- ${options ? JSON.stringify(options) : null}
641
- );
642
- `;
643
802
  return {
644
- id,
645
- authUrl
803
+ authUrl,
804
+ clientId,
805
+ id
646
806
  };
647
807
  }
648
808
  async removeMcpServer(id) {
@@ -652,27 +812,31 @@ var Agent = class extends Server {
652
812
  `;
653
813
  this.broadcast(
654
814
  JSON.stringify({
655
- type: "cf_agent_mcp_servers",
656
- mcp: this._getMcpServerStateInternal()
815
+ mcp: this.getMcpServers(),
816
+ type: "cf_agent_mcp_servers"
657
817
  })
658
818
  );
659
819
  }
660
- _getMcpServerStateInternal() {
820
+ getMcpServers() {
661
821
  const mcpState = {
662
- servers: {},
663
- tools: this.mcp.listTools(),
664
822
  prompts: this.mcp.listPrompts(),
665
- resources: this.mcp.listResources()
823
+ resources: this.mcp.listResources(),
824
+ servers: {},
825
+ tools: this.mcp.listTools()
666
826
  };
667
827
  const servers = this.sql`
668
828
  SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
669
829
  `;
670
830
  for (const server of servers) {
831
+ const serverConn = this.mcp.mcpConnections[server.id];
671
832
  mcpState.servers[server.id] = {
833
+ auth_url: server.auth_url,
834
+ capabilities: serverConn?.serverCapabilities ?? null,
835
+ instructions: serverConn?.instructions ?? null,
672
836
  name: server.name,
673
837
  server_url: server.server_url,
674
- auth_url: server.auth_url,
675
- state: this.mcp.mcpConnections[server.id].connectionState
838
+ // mark as "authenticating" because the server isn't automatically connected, so it's pending authenticating
839
+ state: serverConn?.connectionState ?? "authenticating"
676
840
  };
677
841
  }
678
842
  return mcpState;
@@ -688,9 +852,9 @@ Agent.options = {
688
852
  };
689
853
  async function routeAgentRequest(request, env, options) {
690
854
  const corsHeaders = options?.cors === true ? {
691
- "Access-Control-Allow-Origin": "*",
692
- "Access-Control-Allow-Methods": "GET, POST, HEAD, OPTIONS",
693
855
  "Access-Control-Allow-Credentials": "true",
856
+ "Access-Control-Allow-Methods": "GET, POST, HEAD, OPTIONS",
857
+ "Access-Control-Allow-Origin": "*",
694
858
  "Access-Control-Max-Age": "86400"
695
859
  } : options?.cors;
696
860
  if (request.method === "OPTIONS") {
@@ -721,7 +885,116 @@ async function routeAgentRequest(request, env, options) {
721
885
  }
722
886
  return response;
723
887
  }
888
+ function createHeaderBasedEmailResolver() {
889
+ return async (email, _env) => {
890
+ const messageId = email.headers.get("message-id");
891
+ if (messageId) {
892
+ const messageIdMatch = messageId.match(/<([^@]+)@([^>]+)>/);
893
+ if (messageIdMatch) {
894
+ const [, agentId2, domain] = messageIdMatch;
895
+ const agentName2 = domain.split(".")[0];
896
+ return { agentName: agentName2, agentId: agentId2 };
897
+ }
898
+ }
899
+ const references = email.headers.get("references");
900
+ if (references) {
901
+ const referencesMatch = references.match(
902
+ /<([A-Za-z0-9+/]{43}=)@([^>]+)>/
903
+ );
904
+ if (referencesMatch) {
905
+ const [, base64Id, domain] = referencesMatch;
906
+ const agentId2 = Buffer.from(base64Id, "base64").toString("hex");
907
+ const agentName2 = domain.split(".")[0];
908
+ return { agentName: agentName2, agentId: agentId2 };
909
+ }
910
+ }
911
+ const agentName = email.headers.get("x-agent-name");
912
+ const agentId = email.headers.get("x-agent-id");
913
+ if (agentName && agentId) {
914
+ return { agentName, agentId };
915
+ }
916
+ return null;
917
+ };
918
+ }
919
+ function createAddressBasedEmailResolver(defaultAgentName) {
920
+ return async (email, _env) => {
921
+ const emailMatch = email.to.match(/^([^+@]+)(?:\+([^@]+))?@(.+)$/);
922
+ if (!emailMatch) {
923
+ return null;
924
+ }
925
+ const [, localPart, subAddress] = emailMatch;
926
+ if (subAddress) {
927
+ return {
928
+ agentName: localPart,
929
+ agentId: subAddress
930
+ };
931
+ }
932
+ return {
933
+ agentName: defaultAgentName,
934
+ agentId: localPart
935
+ };
936
+ };
937
+ }
938
+ function createCatchAllEmailResolver(agentName, agentId) {
939
+ return async () => ({ agentName, agentId });
940
+ }
724
941
  async function routeAgentEmail(email, env, options) {
942
+ const routingInfo = await options.resolver(email, env);
943
+ if (!routingInfo) {
944
+ console.warn("No routing information found for email, dropping message");
945
+ return;
946
+ }
947
+ const namespaceBinding = env[routingInfo.agentName];
948
+ if (!namespaceBinding) {
949
+ throw new Error(
950
+ `Agent namespace '${routingInfo.agentName}' not found in environment`
951
+ );
952
+ }
953
+ if (typeof namespaceBinding !== "object" || !("idFromName" in namespaceBinding) || typeof namespaceBinding.idFromName !== "function") {
954
+ throw new Error(
955
+ `Environment binding '${routingInfo.agentName}' is not an AgentNamespace (found: ${typeof namespaceBinding})`
956
+ );
957
+ }
958
+ const namespace = namespaceBinding;
959
+ const agent = await getAgentByName(namespace, routingInfo.agentId);
960
+ const serialisableEmail = {
961
+ getRaw: async () => {
962
+ const reader = email.raw.getReader();
963
+ const chunks = [];
964
+ let done = false;
965
+ while (!done) {
966
+ const { value, done: readerDone } = await reader.read();
967
+ done = readerDone;
968
+ if (value) {
969
+ chunks.push(value);
970
+ }
971
+ }
972
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
973
+ const combined = new Uint8Array(totalLength);
974
+ let offset = 0;
975
+ for (const chunk of chunks) {
976
+ combined.set(chunk, offset);
977
+ offset += chunk.length;
978
+ }
979
+ return combined;
980
+ },
981
+ headers: email.headers,
982
+ rawSize: email.rawSize,
983
+ setReject: (reason) => {
984
+ email.setReject(reason);
985
+ },
986
+ forward: (rcptTo, headers) => {
987
+ return email.forward(rcptTo, headers);
988
+ },
989
+ reply: (options2) => {
990
+ return email.reply(
991
+ new EmailMessage(options2.from, options2.to, options2.raw)
992
+ );
993
+ },
994
+ from: email.from,
995
+ to: email.to
996
+ };
997
+ await agent._onEmail(serialisableEmail);
725
998
  }
726
999
  async function getAgentByName(namespace, name, options) {
727
1000
  return getServerByName(namespace, name, options);
@@ -741,11 +1014,11 @@ var StreamingResponse = class {
741
1014
  throw new Error("StreamingResponse is already closed");
742
1015
  }
743
1016
  const response = {
744
- type: "rpc",
1017
+ done: false,
745
1018
  id: this._id,
746
- success: true,
747
1019
  result: chunk,
748
- done: false
1020
+ success: true,
1021
+ type: "rpc"
749
1022
  };
750
1023
  this._connection.send(JSON.stringify(response));
751
1024
  }
@@ -759,23 +1032,51 @@ var StreamingResponse = class {
759
1032
  }
760
1033
  this._closed = true;
761
1034
  const response = {
762
- type: "rpc",
1035
+ done: true,
763
1036
  id: this._id,
764
- success: true,
765
1037
  result: finalChunk,
766
- done: true
1038
+ success: true,
1039
+ type: "rpc"
767
1040
  };
768
1041
  this._connection.send(JSON.stringify(response));
769
1042
  }
770
1043
  };
771
1044
 
1045
+ // src/observability/index.ts
1046
+ var genericObservability = {
1047
+ emit(event) {
1048
+ if (isLocalMode()) {
1049
+ console.log(event.displayMessage);
1050
+ return;
1051
+ }
1052
+ console.log(event);
1053
+ }
1054
+ };
1055
+ var localMode = false;
1056
+ function isLocalMode() {
1057
+ if (localMode) {
1058
+ return true;
1059
+ }
1060
+ const { request } = getCurrentAgent();
1061
+ if (!request) {
1062
+ return false;
1063
+ }
1064
+ const url = new URL(request.url);
1065
+ localMode = url.hostname === "localhost";
1066
+ return localMode;
1067
+ }
1068
+
772
1069
  export {
1070
+ genericObservability,
773
1071
  unstable_callable,
774
1072
  getCurrentAgent,
775
1073
  Agent,
776
1074
  routeAgentRequest,
1075
+ createHeaderBasedEmailResolver,
1076
+ createAddressBasedEmailResolver,
1077
+ createCatchAllEmailResolver,
777
1078
  routeAgentEmail,
778
1079
  getAgentByName,
779
1080
  StreamingResponse
780
1081
  };
781
- //# sourceMappingURL=chunk-4ARKO5R4.js.map
1082
+ //# sourceMappingURL=chunk-MGHXAF5T.js.map