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.
- package/README.md +22 -22
- package/dist/ai-chat-agent.d.ts +5 -4
- package/dist/ai-chat-agent.js +64 -26
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.d.ts +10 -9
- package/dist/ai-react.js +27 -27
- package/dist/ai-react.js.map +1 -1
- package/dist/{chunk-QSGN3REV.js → chunk-KUH345EY.js} +8 -15
- package/dist/chunk-KUH345EY.js.map +1 -0
- package/dist/{chunk-4ARKO5R4.js → chunk-MGHXAF5T.js} +390 -89
- package/dist/chunk-MGHXAF5T.js.map +1 -0
- package/dist/{chunk-Y67CHZBI.js → chunk-MW5BQ2FW.js} +23 -18
- package/dist/chunk-MW5BQ2FW.js.map +1 -0
- package/dist/{chunk-BZXOAZUX.js → chunk-PVQZBKN7.js} +5 -5
- package/dist/chunk-PVQZBKN7.js.map +1 -0
- package/dist/client.d.ts +8 -2
- package/dist/client.js +1 -1
- package/dist/index-CEVsIbwa.d.ts +565 -0
- package/dist/index.d.ts +32 -398
- package/dist/index.js +10 -4
- package/dist/mcp/client.d.ts +281 -9
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/do-oauth-client-provider.js +1 -1
- package/dist/mcp/index.d.ts +9 -9
- package/dist/mcp/index.js +55 -51
- package/dist/mcp/index.js.map +1 -1
- package/dist/observability/index.d.ts +12 -0
- package/dist/observability/index.js +10 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/react.d.ts +56 -38
- package/dist/react.js +16 -6
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +6 -6
- package/dist/schedule.js +4 -4
- package/dist/schedule.js.map +1 -1
- package/dist/serializable.d.ts +32 -0
- package/dist/serializable.js +1 -0
- package/dist/serializable.js.map +1 -0
- package/package.json +76 -72
- package/src/index.ts +517 -126
- package/dist/chunk-4ARKO5R4.js.map +0 -1
- package/dist/chunk-BZXOAZUX.js.map +0 -1
- package/dist/chunk-QSGN3REV.js.map +0 -1
- 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-
|
|
6
|
+
} from "./chunk-PVQZBKN7.js";
|
|
4
7
|
import {
|
|
5
8
|
camelCaseToKebabCase
|
|
6
|
-
} from "./chunk-
|
|
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
|
-
|
|
15
|
-
|
|
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
|
-
{
|
|
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
|
-
|
|
152
|
-
|
|
171
|
+
mcp: this.getMcpServers(),
|
|
172
|
+
type: "cf_agent_mcp_servers"
|
|
153
173
|
})
|
|
154
174
|
);
|
|
155
175
|
return new Response("<script>window.close();</script>", {
|
|
156
|
-
|
|
157
|
-
|
|
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 (
|
|
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
|
-
|
|
235
|
+
done: true,
|
|
201
236
|
id,
|
|
202
|
-
success: true,
|
|
203
237
|
result,
|
|
204
|
-
|
|
238
|
+
success: true,
|
|
239
|
+
type: "rpc"
|
|
205
240
|
};
|
|
206
241
|
connection.send(JSON.stringify(response));
|
|
207
242
|
} catch (e) {
|
|
208
243
|
const response = {
|
|
209
|
-
|
|
244
|
+
error: e instanceof Error ? e.message : "Unknown error occurred",
|
|
210
245
|
id: parsed.id,
|
|
211
246
|
success: false,
|
|
212
|
-
|
|
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
|
-
|
|
233
|
-
|
|
267
|
+
state: this.state,
|
|
268
|
+
type: "cf_agent_state"
|
|
234
269
|
})
|
|
235
270
|
);
|
|
236
271
|
}
|
|
237
272
|
connection.send(
|
|
238
273
|
JSON.stringify({
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
{
|
|
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
|
-
|
|
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
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
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
|
-
|
|
339
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
592
|
-
|
|
762
|
+
mcp: this.getMcpServers(),
|
|
763
|
+
type: "cf_agent_mcp_servers"
|
|
593
764
|
})
|
|
594
765
|
);
|
|
595
766
|
return result;
|
|
596
767
|
}
|
|
597
|
-
async _connectToMcpServerInternal(
|
|
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
|
-
|
|
645
|
-
|
|
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
|
-
|
|
656
|
-
|
|
815
|
+
mcp: this.getMcpServers(),
|
|
816
|
+
type: "cf_agent_mcp_servers"
|
|
657
817
|
})
|
|
658
818
|
);
|
|
659
819
|
}
|
|
660
|
-
|
|
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
|
-
|
|
675
|
-
state:
|
|
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
|
-
|
|
1017
|
+
done: false,
|
|
745
1018
|
id: this._id,
|
|
746
|
-
success: true,
|
|
747
1019
|
result: chunk,
|
|
748
|
-
|
|
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
|
-
|
|
1035
|
+
done: true,
|
|
763
1036
|
id: this._id,
|
|
764
|
-
success: true,
|
|
765
1037
|
result: finalChunk,
|
|
766
|
-
|
|
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-
|
|
1082
|
+
//# sourceMappingURL=chunk-MGHXAF5T.js.map
|