agents 0.0.0-569680f → 0.0.0-579b228
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 +1 -1
- package/dist/ai-chat-agent.js +4 -4
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.d.ts +2 -2
- package/dist/ai-react.js.map +1 -1
- package/dist/{chunk-RX76B6DL.js → chunk-CKHRUXM5.js} +380 -135
- package/dist/chunk-CKHRUXM5.js.map +1 -0
- package/dist/{chunk-NKZZ66QY.js → chunk-KUH345EY.js} +1 -1
- package/dist/chunk-KUH345EY.js.map +1 -0
- package/dist/{chunk-TN7QOY4S.js → chunk-MW5BQ2FW.js} +1 -1
- package/dist/chunk-MW5BQ2FW.js.map +1 -0
- package/dist/{chunk-767EASBA.js → chunk-PVQZBKN7.js} +1 -1
- package/dist/chunk-PVQZBKN7.js.map +1 -0
- package/dist/client.d.ts +2 -2
- package/dist/client.js +1 -1
- package/dist/{index-aBwVVXj7.d.ts → index-BIJvkfYt.d.ts} +112 -27
- package/dist/index.d.ts +9 -8
- package/dist/index.js +10 -12
- package/dist/mcp/client.js +1 -1
- package/dist/mcp/do-oauth-client-provider.js +1 -1
- package/dist/mcp/index.d.ts +3 -3
- package/dist/mcp/index.js +4 -4
- package/dist/mcp/index.js.map +1 -1
- package/dist/observability/index.d.ts +1 -1
- package/dist/observability/index.js +4 -4
- package/dist/react.d.ts +4 -4
- package/dist/react.js.map +1 -1
- package/dist/schedule.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +555 -199
- package/dist/chunk-767EASBA.js.map +0 -1
- package/dist/chunk-NKZZ66QY.js.map +0 -1
- package/dist/chunk-RX76B6DL.js.map +0 -1
- package/dist/chunk-TN7QOY4S.js.map +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MCPClientManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-MW5BQ2FW.js";
|
|
4
4
|
import {
|
|
5
5
|
DurableObjectOAuthClientProvider
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PVQZBKN7.js";
|
|
7
7
|
import {
|
|
8
8
|
camelCaseToKebabCase
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KUH345EY.js";
|
|
10
10
|
|
|
11
11
|
// src/index.ts
|
|
12
12
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -47,12 +47,21 @@ function getCurrentAgent() {
|
|
|
47
47
|
return {
|
|
48
48
|
agent: void 0,
|
|
49
49
|
connection: void 0,
|
|
50
|
-
request: void 0
|
|
50
|
+
request: void 0,
|
|
51
|
+
email: void 0
|
|
51
52
|
};
|
|
52
53
|
}
|
|
53
54
|
return store;
|
|
54
55
|
}
|
|
55
|
-
|
|
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 {
|
|
56
65
|
constructor(ctx, env) {
|
|
57
66
|
super(ctx, env);
|
|
58
67
|
this._state = DEFAULT_STATE;
|
|
@@ -67,6 +76,7 @@ var Agent = class extends Server {
|
|
|
67
76
|
* The observability implementation to use for the Agent
|
|
68
77
|
*/
|
|
69
78
|
this.observability = genericObservability;
|
|
79
|
+
this._flushingQueue = false;
|
|
70
80
|
/**
|
|
71
81
|
* Method called when an alarm fires.
|
|
72
82
|
* Executes any scheduled tasks that are due.
|
|
@@ -80,52 +90,68 @@ var Agent = class extends Server {
|
|
|
80
90
|
const result = this.sql`
|
|
81
91
|
SELECT * FROM cf_agents_schedules WHERE time <= ${now}
|
|
82
92
|
`;
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
await agentContext.run(
|
|
90
|
-
{ agent: this, connection: void 0, request: void 0 },
|
|
91
|
-
async () => {
|
|
92
|
-
try {
|
|
93
|
-
this.observability?.emit(
|
|
94
|
-
{
|
|
95
|
-
displayMessage: `Schedule ${row.id} executed`,
|
|
96
|
-
id: nanoid(),
|
|
97
|
-
payload: row,
|
|
98
|
-
timestamp: Date.now(),
|
|
99
|
-
type: "schedule:execute"
|
|
100
|
-
},
|
|
101
|
-
this.ctx
|
|
102
|
-
);
|
|
103
|
-
await callback.bind(this)(JSON.parse(row.payload), row);
|
|
104
|
-
} catch (e) {
|
|
105
|
-
console.error(`error executing callback "${row.callback}"`, e);
|
|
106
|
-
}
|
|
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;
|
|
107
99
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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`
|
|
113
129
|
UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}
|
|
114
130
|
`;
|
|
115
|
-
|
|
116
|
-
|
|
131
|
+
} else {
|
|
132
|
+
this.sql`
|
|
117
133
|
DELETE FROM cf_agents_schedules WHERE id = ${row.id}
|
|
118
134
|
`;
|
|
135
|
+
}
|
|
119
136
|
}
|
|
120
137
|
}
|
|
121
138
|
await this._scheduleNextAlarm();
|
|
122
139
|
};
|
|
140
|
+
this._autoWrapCustomMethods();
|
|
123
141
|
this.sql`
|
|
124
142
|
CREATE TABLE IF NOT EXISTS cf_agents_state (
|
|
125
143
|
id TEXT PRIMARY KEY NOT NULL,
|
|
126
144
|
state TEXT
|
|
127
145
|
)
|
|
128
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
|
+
`;
|
|
129
155
|
void this.ctx.blockConcurrencyWhile(async () => {
|
|
130
156
|
return this._tryCatch(async () => {
|
|
131
157
|
this.sql`
|
|
@@ -157,7 +183,7 @@ var Agent = class extends Server {
|
|
|
157
183
|
const _onRequest = this.onRequest.bind(this);
|
|
158
184
|
this.onRequest = (request) => {
|
|
159
185
|
return agentContext.run(
|
|
160
|
-
{ agent: this, connection: void 0, request },
|
|
186
|
+
{ agent: this, connection: void 0, request, email: void 0 },
|
|
161
187
|
async () => {
|
|
162
188
|
if (this.mcp.isCallbackRequest(request)) {
|
|
163
189
|
await this.mcp.handleCallbackRequest(request);
|
|
@@ -179,7 +205,7 @@ var Agent = class extends Server {
|
|
|
179
205
|
const _onMessage = this.onMessage.bind(this);
|
|
180
206
|
this.onMessage = async (connection, message) => {
|
|
181
207
|
return agentContext.run(
|
|
182
|
-
{ agent: this, connection, request: void 0 },
|
|
208
|
+
{ agent: this, connection, request: void 0, email: void 0 },
|
|
183
209
|
async () => {
|
|
184
210
|
if (typeof message !== "string") {
|
|
185
211
|
return this._tryCatch(() => _onMessage(connection, message));
|
|
@@ -253,7 +279,7 @@ var Agent = class extends Server {
|
|
|
253
279
|
const _onConnect = this.onConnect.bind(this);
|
|
254
280
|
this.onConnect = (connection, ctx2) => {
|
|
255
281
|
return agentContext.run(
|
|
256
|
-
{ agent: this, connection, request: ctx2.request },
|
|
282
|
+
{ agent: this, connection, request: ctx2.request, email: void 0 },
|
|
257
283
|
async () => {
|
|
258
284
|
setTimeout(() => {
|
|
259
285
|
if (this.state) {
|
|
@@ -290,32 +316,39 @@ var Agent = class extends Server {
|
|
|
290
316
|
const _onStart = this.onStart.bind(this);
|
|
291
317
|
this.onStart = async () => {
|
|
292
318
|
return agentContext.run(
|
|
293
|
-
{
|
|
319
|
+
{
|
|
320
|
+
agent: this,
|
|
321
|
+
connection: void 0,
|
|
322
|
+
request: void 0,
|
|
323
|
+
email: void 0
|
|
324
|
+
},
|
|
294
325
|
async () => {
|
|
295
326
|
const servers = this.sql`
|
|
296
327
|
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
297
328
|
`;
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
).then((_results) => {
|
|
312
|
-
this.broadcast(
|
|
313
|
-
JSON.stringify({
|
|
314
|
-
mcp: this.getMcpServers(),
|
|
315
|
-
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
|
+
);
|
|
316
342
|
})
|
|
317
|
-
)
|
|
318
|
-
|
|
343
|
+
).then((_results) => {
|
|
344
|
+
this.broadcast(
|
|
345
|
+
JSON.stringify({
|
|
346
|
+
mcp: this.getMcpServers(),
|
|
347
|
+
type: "cf_agent_mcp_servers"
|
|
348
|
+
})
|
|
349
|
+
);
|
|
350
|
+
});
|
|
351
|
+
}
|
|
319
352
|
await this._tryCatch(() => _onStart());
|
|
320
353
|
}
|
|
321
354
|
);
|
|
@@ -385,9 +418,9 @@ var Agent = class extends Server {
|
|
|
385
418
|
source !== "server" ? [source.id] : []
|
|
386
419
|
);
|
|
387
420
|
return this._tryCatch(() => {
|
|
388
|
-
const { connection, request } = agentContext.getStore() || {};
|
|
421
|
+
const { connection, request, email } = agentContext.getStore() || {};
|
|
389
422
|
return agentContext.run(
|
|
390
|
-
{ agent: this, connection, request },
|
|
423
|
+
{ agent: this, connection, request, email },
|
|
391
424
|
async () => {
|
|
392
425
|
this.observability?.emit(
|
|
393
426
|
{
|
|
@@ -423,28 +456,65 @@ var Agent = class extends Server {
|
|
|
423
456
|
onStateUpdate(state, source) {
|
|
424
457
|
}
|
|
425
458
|
/**
|
|
426
|
-
* Called when the Agent receives an email
|
|
459
|
+
* Called when the Agent receives an email via routeAgentEmail()
|
|
427
460
|
* Override this method to handle incoming emails
|
|
428
461
|
* @param email Email message to process
|
|
429
462
|
*/
|
|
430
|
-
async
|
|
463
|
+
async _onEmail(email) {
|
|
431
464
|
return agentContext.run(
|
|
432
|
-
{ agent: this, connection: void 0, request: void 0 },
|
|
465
|
+
{ agent: this, connection: void 0, request: void 0, email },
|
|
433
466
|
async () => {
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
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
|
+
}
|
|
437
478
|
}
|
|
438
479
|
);
|
|
439
480
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
+
});
|
|
448
518
|
});
|
|
449
519
|
}
|
|
450
520
|
async _tryCatch(fn) {
|
|
@@ -454,6 +524,55 @@ var Agent = class extends Server {
|
|
|
454
524
|
throw this.onError(e);
|
|
455
525
|
}
|
|
456
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
|
+
}
|
|
457
576
|
onError(connectionOrError, error) {
|
|
458
577
|
let theError;
|
|
459
578
|
if (connectionOrError && error) {
|
|
@@ -479,6 +598,108 @@ var Agent = class extends Server {
|
|
|
479
598
|
render() {
|
|
480
599
|
throw new Error("Not implemented");
|
|
481
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 result = this.sql`
|
|
631
|
+
SELECT * FROM cf_agents_queues
|
|
632
|
+
ORDER BY created_at ASC
|
|
633
|
+
`;
|
|
634
|
+
if (!result || result.length === 0) {
|
|
635
|
+
break;
|
|
636
|
+
}
|
|
637
|
+
for (const row of result || []) {
|
|
638
|
+
const callback = this[row.callback];
|
|
639
|
+
if (!callback) {
|
|
640
|
+
console.error(`callback ${row.callback} not found`);
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
const { connection, request, email } = agentContext.getStore() || {};
|
|
644
|
+
await agentContext.run(
|
|
645
|
+
{
|
|
646
|
+
agent: this,
|
|
647
|
+
connection,
|
|
648
|
+
request,
|
|
649
|
+
email
|
|
650
|
+
},
|
|
651
|
+
async () => {
|
|
652
|
+
await callback.bind(this)(JSON.parse(row.payload), row);
|
|
653
|
+
await this.dequeue(row.id);
|
|
654
|
+
}
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
this._flushingQueue = false;
|
|
659
|
+
}
|
|
660
|
+
/**
|
|
661
|
+
* Dequeue a task by ID
|
|
662
|
+
* @param id ID of the task to dequeue
|
|
663
|
+
*/
|
|
664
|
+
async dequeue(id) {
|
|
665
|
+
this.sql`DELETE FROM cf_agents_queues WHERE id = ${id}`;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Dequeue all tasks
|
|
669
|
+
*/
|
|
670
|
+
async dequeueAll() {
|
|
671
|
+
this.sql`DELETE FROM cf_agents_queues`;
|
|
672
|
+
}
|
|
673
|
+
/**
|
|
674
|
+
* Dequeue all tasks by callback
|
|
675
|
+
* @param callback Name of the callback to dequeue
|
|
676
|
+
*/
|
|
677
|
+
async dequeueAllByCallback(callback) {
|
|
678
|
+
this.sql`DELETE FROM cf_agents_queues WHERE callback = ${callback}`;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* Get a queued task by ID
|
|
682
|
+
* @param id ID of the task to get
|
|
683
|
+
* @returns The task or undefined if not found
|
|
684
|
+
*/
|
|
685
|
+
async getQueue(id) {
|
|
686
|
+
const result = this.sql`
|
|
687
|
+
SELECT * FROM cf_agents_queues WHERE id = ${id}
|
|
688
|
+
`;
|
|
689
|
+
return result ? { ...result[0], payload: JSON.parse(result[0].payload) } : void 0;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Get all queues by key and value
|
|
693
|
+
* @param key Key to filter by
|
|
694
|
+
* @param value Value to filter by
|
|
695
|
+
* @returns Array of matching QueueItem objects
|
|
696
|
+
*/
|
|
697
|
+
async getQueues(key, value) {
|
|
698
|
+
const result = this.sql`
|
|
699
|
+
SELECT * FROM cf_agents_queues
|
|
700
|
+
`;
|
|
701
|
+
return result.filter((row) => JSON.parse(row.payload)[key] === value);
|
|
702
|
+
}
|
|
482
703
|
/**
|
|
483
704
|
* Schedule a task to be executed in the future
|
|
484
705
|
* @template T Type of the payload data
|
|
@@ -641,9 +862,9 @@ var Agent = class extends Server {
|
|
|
641
862
|
}
|
|
642
863
|
async _scheduleNextAlarm() {
|
|
643
864
|
const result = this.sql`
|
|
644
|
-
SELECT time FROM cf_agents_schedules
|
|
865
|
+
SELECT time FROM cf_agents_schedules
|
|
645
866
|
WHERE time > ${Math.floor(Date.now() / 1e3)}
|
|
646
|
-
ORDER BY time ASC
|
|
867
|
+
ORDER BY time ASC
|
|
647
868
|
LIMIT 1
|
|
648
869
|
`;
|
|
649
870
|
if (!result) return;
|
|
@@ -659,6 +880,7 @@ var Agent = class extends Server {
|
|
|
659
880
|
this.sql`DROP TABLE IF EXISTS cf_agents_state`;
|
|
660
881
|
this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;
|
|
661
882
|
this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
|
|
883
|
+
this.sql`DROP TABLE IF EXISTS cf_agents_queues`;
|
|
662
884
|
await this.ctx.storage.deleteAlarm();
|
|
663
885
|
await this.ctx.storage.deleteAll();
|
|
664
886
|
this.ctx.abort("destroyed");
|
|
@@ -780,17 +1002,19 @@ var Agent = class extends Server {
|
|
|
780
1002
|
const servers = this.sql`
|
|
781
1003
|
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
782
1004
|
`;
|
|
783
|
-
|
|
784
|
-
const
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
1005
|
+
if (servers && Array.isArray(servers) && servers.length > 0) {
|
|
1006
|
+
for (const server of servers) {
|
|
1007
|
+
const serverConn = this.mcp.mcpConnections[server.id];
|
|
1008
|
+
mcpState.servers[server.id] = {
|
|
1009
|
+
auth_url: server.auth_url,
|
|
1010
|
+
capabilities: serverConn?.serverCapabilities ?? null,
|
|
1011
|
+
instructions: serverConn?.instructions ?? null,
|
|
1012
|
+
name: server.name,
|
|
1013
|
+
server_url: server.server_url,
|
|
1014
|
+
// mark as "authenticating" because the server isn't automatically connected, so it's pending authenticating
|
|
1015
|
+
state: serverConn?.connectionState ?? "authenticating"
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
794
1018
|
}
|
|
795
1019
|
return mcpState;
|
|
796
1020
|
}
|
|
@@ -798,11 +1022,12 @@ var Agent = class extends Server {
|
|
|
798
1022
|
/**
|
|
799
1023
|
* Agent configuration options
|
|
800
1024
|
*/
|
|
801
|
-
|
|
1025
|
+
_Agent.options = {
|
|
802
1026
|
/** Whether the Agent should hibernate when inactive */
|
|
803
1027
|
hibernate: true
|
|
804
1028
|
// default to hibernate
|
|
805
1029
|
};
|
|
1030
|
+
var Agent = _Agent;
|
|
806
1031
|
async function routeAgentRequest(request, env, options) {
|
|
807
1032
|
const corsHeaders = options?.cors === true ? {
|
|
808
1033
|
"Access-Control-Allow-Credentials": "true",
|
|
@@ -838,7 +1063,7 @@ async function routeAgentRequest(request, env, options) {
|
|
|
838
1063
|
}
|
|
839
1064
|
return response;
|
|
840
1065
|
}
|
|
841
|
-
function
|
|
1066
|
+
function createHeaderBasedEmailResolver() {
|
|
842
1067
|
return async (email, _env) => {
|
|
843
1068
|
const messageId = email.headers.get("message-id");
|
|
844
1069
|
if (messageId) {
|
|
@@ -869,7 +1094,7 @@ function createHeaderBasedResolver() {
|
|
|
869
1094
|
return null;
|
|
870
1095
|
};
|
|
871
1096
|
}
|
|
872
|
-
function
|
|
1097
|
+
function createAddressBasedEmailResolver(defaultAgentName) {
|
|
873
1098
|
return async (email, _env) => {
|
|
874
1099
|
const emailMatch = email.to.match(/^([^+@]+)(?:\+([^@]+))?@(.+)$/);
|
|
875
1100
|
if (!emailMatch) {
|
|
@@ -888,55 +1113,76 @@ function createAddressBasedResolver(defaultAgentName) {
|
|
|
888
1113
|
};
|
|
889
1114
|
};
|
|
890
1115
|
}
|
|
891
|
-
function
|
|
1116
|
+
function createCatchAllEmailResolver(agentName, agentId) {
|
|
892
1117
|
return async () => ({ agentName, agentId });
|
|
893
1118
|
}
|
|
1119
|
+
var agentMapCache = /* @__PURE__ */ new WeakMap();
|
|
894
1120
|
async function routeAgentEmail(email, env, options) {
|
|
895
1121
|
const routingInfo = await options.resolver(email, env);
|
|
896
1122
|
if (!routingInfo) {
|
|
897
1123
|
console.warn("No routing information found for email, dropping message");
|
|
898
1124
|
return;
|
|
899
1125
|
}
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
1126
|
+
if (!agentMapCache.has(env)) {
|
|
1127
|
+
const map = {};
|
|
1128
|
+
for (const [key, value] of Object.entries(env)) {
|
|
1129
|
+
if (value && typeof value === "object" && "idFromName" in value && typeof value.idFromName === "function") {
|
|
1130
|
+
map[key] = value;
|
|
1131
|
+
map[camelCaseToKebabCase(key)] = value;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
agentMapCache.set(env, map);
|
|
906
1135
|
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
1136
|
+
const agentMap = agentMapCache.get(env);
|
|
1137
|
+
const namespace = agentMap[routingInfo.agentName];
|
|
1138
|
+
if (!namespace) {
|
|
1139
|
+
const availableAgents = Object.keys(agentMap).filter((key) => !key.includes("-")).join(", ");
|
|
1140
|
+
throw new Error(
|
|
1141
|
+
`Agent namespace '${routingInfo.agentName}' not found in environment. Available agents: ${availableAgents}`
|
|
910
1142
|
);
|
|
911
|
-
return;
|
|
912
|
-
}
|
|
913
|
-
const namespace = namespaceBinding;
|
|
914
|
-
const agent = await getAgentByName(namespace, routingInfo.agentId);
|
|
915
|
-
await agent.onEmail(email);
|
|
916
|
-
}
|
|
917
|
-
async function sendEmailWithRouting(emailBinding, from, fromName, options) {
|
|
918
|
-
const { createMimeMessage } = await import("mimetext");
|
|
919
|
-
const msg = createMimeMessage();
|
|
920
|
-
msg.setSender({ addr: from, name: fromName });
|
|
921
|
-
msg.setRecipient(options.to);
|
|
922
|
-
msg.setSubject(options.subject);
|
|
923
|
-
msg.addMessage({
|
|
924
|
-
contentType: options.contentType || "text/plain",
|
|
925
|
-
data: options.body
|
|
926
|
-
});
|
|
927
|
-
if (options.includeRoutingHeaders && options.agentName && options.agentId) {
|
|
928
|
-
const domain = options.domain || from.split("@")[1];
|
|
929
|
-
const messageId = `<${options.agentId}@${domain}>`;
|
|
930
|
-
msg.setHeader("Message-ID", messageId);
|
|
931
|
-
msg.setHeader("X-Agent-Name", options.agentName);
|
|
932
|
-
msg.setHeader("X-Agent-ID", options.agentId);
|
|
933
1143
|
}
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
1144
|
+
const agent = await getAgentByName(
|
|
1145
|
+
namespace,
|
|
1146
|
+
routingInfo.agentId
|
|
1147
|
+
);
|
|
1148
|
+
const serialisableEmail = {
|
|
1149
|
+
getRaw: async () => {
|
|
1150
|
+
const reader = email.raw.getReader();
|
|
1151
|
+
const chunks = [];
|
|
1152
|
+
let done = false;
|
|
1153
|
+
while (!done) {
|
|
1154
|
+
const { value, done: readerDone } = await reader.read();
|
|
1155
|
+
done = readerDone;
|
|
1156
|
+
if (value) {
|
|
1157
|
+
chunks.push(value);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
1161
|
+
const combined = new Uint8Array(totalLength);
|
|
1162
|
+
let offset = 0;
|
|
1163
|
+
for (const chunk of chunks) {
|
|
1164
|
+
combined.set(chunk, offset);
|
|
1165
|
+
offset += chunk.length;
|
|
1166
|
+
}
|
|
1167
|
+
return combined;
|
|
1168
|
+
},
|
|
1169
|
+
headers: email.headers,
|
|
1170
|
+
rawSize: email.rawSize,
|
|
1171
|
+
setReject: (reason) => {
|
|
1172
|
+
email.setReject(reason);
|
|
1173
|
+
},
|
|
1174
|
+
forward: (rcptTo, headers) => {
|
|
1175
|
+
return email.forward(rcptTo, headers);
|
|
1176
|
+
},
|
|
1177
|
+
reply: (options2) => {
|
|
1178
|
+
return email.reply(
|
|
1179
|
+
new EmailMessage(options2.from, options2.to, options2.raw)
|
|
1180
|
+
);
|
|
1181
|
+
},
|
|
1182
|
+
from: email.from,
|
|
1183
|
+
to: email.to
|
|
1184
|
+
};
|
|
1185
|
+
await agent._onEmail(serialisableEmail);
|
|
940
1186
|
}
|
|
941
1187
|
async function getAgentByName(namespace, name, options) {
|
|
942
1188
|
return getServerByName(namespace, name, options);
|
|
@@ -1014,12 +1260,11 @@ export {
|
|
|
1014
1260
|
getCurrentAgent,
|
|
1015
1261
|
Agent,
|
|
1016
1262
|
routeAgentRequest,
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1263
|
+
createHeaderBasedEmailResolver,
|
|
1264
|
+
createAddressBasedEmailResolver,
|
|
1265
|
+
createCatchAllEmailResolver,
|
|
1020
1266
|
routeAgentEmail,
|
|
1021
|
-
sendEmailWithRouting,
|
|
1022
1267
|
getAgentByName,
|
|
1023
1268
|
StreamingResponse
|
|
1024
1269
|
};
|
|
1025
|
-
//# sourceMappingURL=chunk-
|
|
1270
|
+
//# sourceMappingURL=chunk-CKHRUXM5.js.map
|