agents 0.0.0-ac74811 → 0.0.0-afd9efd
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 +255 -27
- package/dist/_esm-LV5FJ3HK.js +3922 -0
- package/dist/_esm-LV5FJ3HK.js.map +1 -0
- package/dist/ai-chat-agent.d.ts +14 -9
- package/dist/ai-chat-agent.js +485 -66
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration.d.ts +152 -0
- package/dist/ai-chat-v5-migration.js +20 -0
- package/dist/ai-chat-v5-migration.js.map +1 -0
- package/dist/ai-react.d.ts +69 -71
- package/dist/ai-react.js +246 -99
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.d.ts +37 -19
- package/dist/ai-types.js +7 -0
- package/dist/ccip-CMBYN64O.js +15 -0
- package/dist/ccip-CMBYN64O.js.map +1 -0
- package/dist/{chunk-JFRK72K3.js → chunk-2Y6KNRNP.js} +591 -158
- package/dist/chunk-2Y6KNRNP.js.map +1 -0
- package/dist/chunk-5Y6BEZDY.js +276 -0
- package/dist/chunk-5Y6BEZDY.js.map +1 -0
- package/dist/chunk-BER7KXUJ.js +18 -0
- package/dist/chunk-BER7KXUJ.js.map +1 -0
- package/dist/{chunk-767EASBA.js → chunk-C2OEBJZ2.js} +14 -7
- package/dist/chunk-C2OEBJZ2.js.map +1 -0
- package/dist/chunk-JJBFIGUC.js +5202 -0
- package/dist/chunk-JJBFIGUC.js.map +1 -0
- package/dist/chunk-PR4QN5HX.js +43 -0
- package/dist/chunk-PR4QN5HX.js.map +1 -0
- package/dist/{chunk-NKZZ66QY.js → chunk-QEVM4BVL.js} +5 -5
- package/dist/chunk-QEVM4BVL.js.map +1 -0
- package/dist/chunk-QUOGV3WN.js +949 -0
- package/dist/chunk-QUOGV3WN.js.map +1 -0
- package/dist/chunk-TYAY6AU6.js +159 -0
- package/dist/chunk-TYAY6AU6.js.map +1 -0
- package/dist/chunk-UJVEAURM.js +150 -0
- package/dist/chunk-UJVEAURM.js.map +1 -0
- package/dist/client-C8tswVoM.d.ts +5248 -0
- package/dist/client.d.ts +2 -2
- package/dist/client.js +3 -1
- package/dist/codemode/ai.d.ts +25 -0
- package/dist/codemode/ai.js +5200 -0
- package/dist/codemode/ai.js.map +1 -0
- package/dist/index.d.ts +550 -24
- package/dist/index.js +14 -4
- package/dist/mcp/client.d.ts +10 -1053
- package/dist/mcp/client.js +2 -1
- package/dist/mcp/do-oauth-client-provider.d.ts +1 -0
- package/dist/mcp/do-oauth-client-provider.js +2 -1
- package/dist/mcp/index.d.ts +58 -63
- package/dist/mcp/index.js +969 -637
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.d.ts +39 -0
- package/dist/mcp/x402.js +3195 -0
- package/dist/mcp/x402.js.map +1 -0
- package/dist/mcp-BH1fJeiU.d.ts +58 -0
- package/dist/observability/index.d.ts +34 -12
- package/dist/observability/index.js +6 -4
- package/dist/react.d.ts +19 -11
- package/dist/react.js +107 -7
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +83 -9
- package/dist/schedule.js +17 -2
- package/dist/schedule.js.map +1 -1
- package/dist/secp256k1-M22GZP2U.js +2193 -0
- package/dist/secp256k1-M22GZP2U.js.map +1 -0
- package/package.json +41 -12
- package/src/index.ts +874 -208
- package/dist/chunk-767EASBA.js.map +0 -1
- package/dist/chunk-E3LCYPCB.js +0 -469
- package/dist/chunk-E3LCYPCB.js.map +0 -1
- package/dist/chunk-JFRK72K3.js.map +0 -1
- package/dist/chunk-NKZZ66QY.js.map +0 -1
- package/dist/index-CITGJflw.d.ts +0 -486
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DisposableStore,
|
|
2
3
|
MCPClientManager
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QUOGV3WN.js";
|
|
4
5
|
import {
|
|
5
6
|
DurableObjectOAuthClientProvider
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-C2OEBJZ2.js";
|
|
7
8
|
import {
|
|
8
9
|
camelCaseToKebabCase
|
|
9
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QEVM4BVL.js";
|
|
10
11
|
|
|
11
12
|
// src/index.ts
|
|
12
13
|
import { AsyncLocalStorage } from "async_hooks";
|
|
13
14
|
import { parseCronExpression } from "cron-schedule";
|
|
14
15
|
import { nanoid } from "nanoid";
|
|
16
|
+
import { EmailMessage } from "cloudflare:email";
|
|
15
17
|
import {
|
|
18
|
+
Server,
|
|
16
19
|
getServerByName,
|
|
17
|
-
routePartykitRequest
|
|
18
|
-
Server
|
|
20
|
+
routePartykitRequest
|
|
19
21
|
} from "partyserver";
|
|
20
22
|
function isRPCRequest(msg) {
|
|
21
|
-
return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "rpc" && "id" in msg && typeof msg.id === "string" && "method" in msg && typeof msg.method === "string" && "args" in msg && Array.isArray(msg.args);
|
|
23
|
+
return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "rpc" /* RPC */ && "id" in msg && typeof msg.id === "string" && "method" in msg && typeof msg.method === "string" && "args" in msg && Array.isArray(msg.args);
|
|
22
24
|
}
|
|
23
25
|
function isStateUpdateMessage(msg) {
|
|
24
|
-
return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "cf_agent_state" && "state" in msg;
|
|
26
|
+
return typeof msg === "object" && msg !== null && "type" in msg && msg.type === "cf_agent_state" /* CF_AGENT_STATE */ && "state" in msg;
|
|
25
27
|
}
|
|
26
28
|
var callableMetadata = /* @__PURE__ */ new Map();
|
|
27
|
-
function
|
|
29
|
+
function callable(metadata = {}) {
|
|
28
30
|
return function callableDecorator(target, context) {
|
|
29
31
|
if (!callableMetadata.has(target)) {
|
|
30
32
|
callableMetadata.set(target, metadata);
|
|
@@ -32,6 +34,16 @@ function unstable_callable(metadata = {}) {
|
|
|
32
34
|
return target;
|
|
33
35
|
};
|
|
34
36
|
}
|
|
37
|
+
var didWarnAboutUnstableCallable = false;
|
|
38
|
+
var unstable_callable = (metadata = {}) => {
|
|
39
|
+
if (!didWarnAboutUnstableCallable) {
|
|
40
|
+
didWarnAboutUnstableCallable = true;
|
|
41
|
+
console.warn(
|
|
42
|
+
"unstable_callable is deprecated, use callable instead. unstable_callable will be removed in the next major version."
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
callable(metadata);
|
|
46
|
+
};
|
|
35
47
|
function getNextCronTime(cron) {
|
|
36
48
|
const interval = parseCronExpression(cron);
|
|
37
49
|
return interval.getNextDate();
|
|
@@ -46,17 +58,33 @@ function getCurrentAgent() {
|
|
|
46
58
|
return {
|
|
47
59
|
agent: void 0,
|
|
48
60
|
connection: void 0,
|
|
49
|
-
request: void 0
|
|
61
|
+
request: void 0,
|
|
62
|
+
email: void 0
|
|
50
63
|
};
|
|
51
64
|
}
|
|
52
65
|
return store;
|
|
53
66
|
}
|
|
54
|
-
|
|
67
|
+
function withAgentContext(method) {
|
|
68
|
+
return function(...args) {
|
|
69
|
+
const { connection, request, email, agent } = getCurrentAgent();
|
|
70
|
+
if (agent === this) {
|
|
71
|
+
return method.apply(this, args);
|
|
72
|
+
}
|
|
73
|
+
return agentContext.run({ agent: this, connection, request, email }, () => {
|
|
74
|
+
return method.apply(this, args);
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
var _Agent = class _Agent extends Server {
|
|
55
79
|
constructor(ctx, env) {
|
|
56
80
|
super(ctx, env);
|
|
57
81
|
this._state = DEFAULT_STATE;
|
|
82
|
+
this._disposables = new DisposableStore();
|
|
58
83
|
this._ParentClass = Object.getPrototypeOf(this).constructor;
|
|
59
|
-
this.mcp = new MCPClientManager(
|
|
84
|
+
this.mcp = new MCPClientManager(
|
|
85
|
+
this._ParentClass.name,
|
|
86
|
+
"0.0.1"
|
|
87
|
+
);
|
|
60
88
|
/**
|
|
61
89
|
* Initial state for the Agent
|
|
62
90
|
* Override to provide default state values
|
|
@@ -66,6 +94,7 @@ var Agent = class extends Server {
|
|
|
66
94
|
* The observability implementation to use for the Agent
|
|
67
95
|
*/
|
|
68
96
|
this.observability = genericObservability;
|
|
97
|
+
this._flushingQueue = false;
|
|
69
98
|
/**
|
|
70
99
|
* Method called when an alarm fires.
|
|
71
100
|
* Executes any scheduled tasks that are due.
|
|
@@ -79,52 +108,84 @@ var Agent = class extends Server {
|
|
|
79
108
|
const result = this.sql`
|
|
80
109
|
SELECT * FROM cf_agents_schedules WHERE time <= ${now}
|
|
81
110
|
`;
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
}
|
|
111
|
+
if (result && Array.isArray(result)) {
|
|
112
|
+
for (const row of result) {
|
|
113
|
+
const callback = this[row.callback];
|
|
114
|
+
if (!callback) {
|
|
115
|
+
console.error(`callback ${row.callback} not found`);
|
|
116
|
+
continue;
|
|
106
117
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
await agentContext.run(
|
|
119
|
+
{
|
|
120
|
+
agent: this,
|
|
121
|
+
connection: void 0,
|
|
122
|
+
request: void 0,
|
|
123
|
+
email: void 0
|
|
124
|
+
},
|
|
125
|
+
async () => {
|
|
126
|
+
try {
|
|
127
|
+
this.observability?.emit(
|
|
128
|
+
{
|
|
129
|
+
displayMessage: `Schedule ${row.id} executed`,
|
|
130
|
+
id: nanoid(),
|
|
131
|
+
payload: {
|
|
132
|
+
callback: row.callback,
|
|
133
|
+
id: row.id
|
|
134
|
+
},
|
|
135
|
+
timestamp: Date.now(),
|
|
136
|
+
type: "schedule:execute"
|
|
137
|
+
},
|
|
138
|
+
this.ctx
|
|
139
|
+
);
|
|
140
|
+
await callback.bind(this)(JSON.parse(row.payload), row);
|
|
141
|
+
} catch (e) {
|
|
142
|
+
console.error(`error executing callback "${row.callback}"`, e);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
);
|
|
146
|
+
if (row.type === "cron") {
|
|
147
|
+
const nextExecutionTime = getNextCronTime(row.cron);
|
|
148
|
+
const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1e3);
|
|
149
|
+
this.sql`
|
|
112
150
|
UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}
|
|
113
151
|
`;
|
|
114
|
-
|
|
115
|
-
|
|
152
|
+
} else {
|
|
153
|
+
this.sql`
|
|
116
154
|
DELETE FROM cf_agents_schedules WHERE id = ${row.id}
|
|
117
155
|
`;
|
|
156
|
+
}
|
|
118
157
|
}
|
|
119
158
|
}
|
|
120
159
|
await this._scheduleNextAlarm();
|
|
121
160
|
};
|
|
161
|
+
if (!wrappedClasses.has(this.constructor)) {
|
|
162
|
+
this._autoWrapCustomMethods();
|
|
163
|
+
wrappedClasses.add(this.constructor);
|
|
164
|
+
}
|
|
165
|
+
this._disposables.add(
|
|
166
|
+
this.mcp.onConnected(async () => {
|
|
167
|
+
this.broadcastMcpServers();
|
|
168
|
+
})
|
|
169
|
+
);
|
|
170
|
+
this._disposables.add(
|
|
171
|
+
this.mcp.onObservabilityEvent((event) => {
|
|
172
|
+
this.observability?.emit(event);
|
|
173
|
+
})
|
|
174
|
+
);
|
|
122
175
|
this.sql`
|
|
123
176
|
CREATE TABLE IF NOT EXISTS cf_agents_state (
|
|
124
177
|
id TEXT PRIMARY KEY NOT NULL,
|
|
125
178
|
state TEXT
|
|
126
179
|
)
|
|
127
180
|
`;
|
|
181
|
+
this.sql`
|
|
182
|
+
CREATE TABLE IF NOT EXISTS cf_agents_queues (
|
|
183
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
184
|
+
payload TEXT,
|
|
185
|
+
callback TEXT,
|
|
186
|
+
created_at INTEGER DEFAULT (unixepoch())
|
|
187
|
+
)
|
|
188
|
+
`;
|
|
128
189
|
void this.ctx.blockConcurrencyWhile(async () => {
|
|
129
190
|
return this._tryCatch(async () => {
|
|
130
191
|
this.sql`
|
|
@@ -156,20 +217,19 @@ var Agent = class extends Server {
|
|
|
156
217
|
const _onRequest = this.onRequest.bind(this);
|
|
157
218
|
this.onRequest = (request) => {
|
|
158
219
|
return agentContext.run(
|
|
159
|
-
{ agent: this, connection: void 0, request },
|
|
220
|
+
{ agent: this, connection: void 0, request, email: void 0 },
|
|
160
221
|
async () => {
|
|
161
222
|
if (this.mcp.isCallbackRequest(request)) {
|
|
162
|
-
await this.mcp.handleCallbackRequest(request);
|
|
163
|
-
this.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
});
|
|
223
|
+
const result = await this.mcp.handleCallbackRequest(request);
|
|
224
|
+
this.broadcastMcpServers();
|
|
225
|
+
if (result.authSuccess) {
|
|
226
|
+
this.mcp.establishConnection(result.serverId).catch((error) => {
|
|
227
|
+
console.error("Background connection failed:", error);
|
|
228
|
+
}).finally(() => {
|
|
229
|
+
this.broadcastMcpServers();
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
return this.handleOAuthCallbackResponse(result, request);
|
|
173
233
|
}
|
|
174
234
|
return this._tryCatch(() => _onRequest(request));
|
|
175
235
|
}
|
|
@@ -178,7 +238,7 @@ var Agent = class extends Server {
|
|
|
178
238
|
const _onMessage = this.onMessage.bind(this);
|
|
179
239
|
this.onMessage = async (connection, message) => {
|
|
180
240
|
return agentContext.run(
|
|
181
|
-
{ agent: this, connection, request: void 0 },
|
|
241
|
+
{ agent: this, connection, request: void 0, email: void 0 },
|
|
182
242
|
async () => {
|
|
183
243
|
if (typeof message !== "string") {
|
|
184
244
|
return this._tryCatch(() => _onMessage(connection, message));
|
|
@@ -215,10 +275,8 @@ var Agent = class extends Server {
|
|
|
215
275
|
displayMessage: `RPC call to ${method}`,
|
|
216
276
|
id: nanoid(),
|
|
217
277
|
payload: {
|
|
218
|
-
args,
|
|
219
278
|
method,
|
|
220
|
-
streaming: metadata?.streaming
|
|
221
|
-
success: true
|
|
279
|
+
streaming: metadata?.streaming
|
|
222
280
|
},
|
|
223
281
|
timestamp: Date.now(),
|
|
224
282
|
type: "rpc"
|
|
@@ -230,7 +288,7 @@ var Agent = class extends Server {
|
|
|
230
288
|
id,
|
|
231
289
|
result,
|
|
232
290
|
success: true,
|
|
233
|
-
type: "rpc"
|
|
291
|
+
type: "rpc" /* RPC */
|
|
234
292
|
};
|
|
235
293
|
connection.send(JSON.stringify(response));
|
|
236
294
|
} catch (e) {
|
|
@@ -238,7 +296,7 @@ var Agent = class extends Server {
|
|
|
238
296
|
error: e instanceof Error ? e.message : "Unknown error occurred",
|
|
239
297
|
id: parsed.id,
|
|
240
298
|
success: false,
|
|
241
|
-
type: "rpc"
|
|
299
|
+
type: "rpc" /* RPC */
|
|
242
300
|
};
|
|
243
301
|
connection.send(JSON.stringify(response));
|
|
244
302
|
console.error("RPC error:", e);
|
|
@@ -252,70 +310,84 @@ var Agent = class extends Server {
|
|
|
252
310
|
const _onConnect = this.onConnect.bind(this);
|
|
253
311
|
this.onConnect = (connection, ctx2) => {
|
|
254
312
|
return agentContext.run(
|
|
255
|
-
{ agent: this, connection, request: ctx2.request },
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
if (this.state) {
|
|
259
|
-
connection.send(
|
|
260
|
-
JSON.stringify({
|
|
261
|
-
state: this.state,
|
|
262
|
-
type: "cf_agent_state"
|
|
263
|
-
})
|
|
264
|
-
);
|
|
265
|
-
}
|
|
313
|
+
{ agent: this, connection, request: ctx2.request, email: void 0 },
|
|
314
|
+
() => {
|
|
315
|
+
if (this.state) {
|
|
266
316
|
connection.send(
|
|
267
317
|
JSON.stringify({
|
|
268
|
-
|
|
269
|
-
type: "
|
|
318
|
+
state: this.state,
|
|
319
|
+
type: "cf_agent_state" /* CF_AGENT_STATE */
|
|
270
320
|
})
|
|
271
321
|
);
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
322
|
+
}
|
|
323
|
+
connection.send(
|
|
324
|
+
JSON.stringify({
|
|
325
|
+
mcp: this.getMcpServers(),
|
|
326
|
+
type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
|
|
327
|
+
})
|
|
328
|
+
);
|
|
329
|
+
this.observability?.emit(
|
|
330
|
+
{
|
|
331
|
+
displayMessage: "Connection established",
|
|
332
|
+
id: nanoid(),
|
|
333
|
+
payload: {
|
|
334
|
+
connectionId: connection.id
|
|
281
335
|
},
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
336
|
+
timestamp: Date.now(),
|
|
337
|
+
type: "connect"
|
|
338
|
+
},
|
|
339
|
+
this.ctx
|
|
340
|
+
);
|
|
341
|
+
return this._tryCatch(() => _onConnect(connection, ctx2));
|
|
286
342
|
}
|
|
287
343
|
);
|
|
288
344
|
};
|
|
289
345
|
const _onStart = this.onStart.bind(this);
|
|
290
|
-
this.onStart = async () => {
|
|
346
|
+
this.onStart = async (props) => {
|
|
291
347
|
return agentContext.run(
|
|
292
|
-
{
|
|
348
|
+
{
|
|
349
|
+
agent: this,
|
|
350
|
+
connection: void 0,
|
|
351
|
+
request: void 0,
|
|
352
|
+
email: void 0
|
|
353
|
+
},
|
|
293
354
|
async () => {
|
|
294
|
-
|
|
355
|
+
await this._tryCatch(() => {
|
|
356
|
+
const servers = this.sql`
|
|
295
357
|
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
296
358
|
`;
|
|
297
|
-
|
|
298
|
-
servers.
|
|
299
|
-
|
|
300
|
-
server.
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
{
|
|
305
|
-
id: server.id,
|
|
306
|
-
oauthClientId: server.client_id ?? void 0
|
|
359
|
+
this.broadcastMcpServers();
|
|
360
|
+
if (servers && Array.isArray(servers) && servers.length > 0) {
|
|
361
|
+
servers.forEach((server) => {
|
|
362
|
+
if (server.callback_url) {
|
|
363
|
+
this.mcp.registerCallbackUrl(
|
|
364
|
+
`${server.callback_url}/${server.id}`
|
|
365
|
+
);
|
|
307
366
|
}
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
367
|
+
});
|
|
368
|
+
servers.forEach((server) => {
|
|
369
|
+
this._connectToMcpServerInternal(
|
|
370
|
+
server.name,
|
|
371
|
+
server.server_url,
|
|
372
|
+
server.callback_url,
|
|
373
|
+
server.server_options ? JSON.parse(server.server_options) : void 0,
|
|
374
|
+
{
|
|
375
|
+
id: server.id,
|
|
376
|
+
oauthClientId: server.client_id ?? void 0
|
|
377
|
+
}
|
|
378
|
+
).then(() => {
|
|
379
|
+
this.broadcastMcpServers();
|
|
380
|
+
}).catch((error) => {
|
|
381
|
+
console.error(
|
|
382
|
+
`Error connecting to MCP server: ${server.name} (${server.server_url})`,
|
|
383
|
+
error
|
|
384
|
+
);
|
|
385
|
+
this.broadcastMcpServers();
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
return _onStart(props);
|
|
317
390
|
});
|
|
318
|
-
await this._tryCatch(() => _onStart());
|
|
319
391
|
}
|
|
320
392
|
);
|
|
321
393
|
};
|
|
@@ -366,7 +438,6 @@ var Agent = class extends Server {
|
|
|
366
438
|
}
|
|
367
439
|
}
|
|
368
440
|
_setStateInternal(state, source = "server") {
|
|
369
|
-
const previousState = this._state;
|
|
370
441
|
this._state = state;
|
|
371
442
|
this.sql`
|
|
372
443
|
INSERT OR REPLACE INTO cf_agents_state (id, state)
|
|
@@ -379,23 +450,20 @@ var Agent = class extends Server {
|
|
|
379
450
|
this.broadcast(
|
|
380
451
|
JSON.stringify({
|
|
381
452
|
state,
|
|
382
|
-
type: "cf_agent_state"
|
|
453
|
+
type: "cf_agent_state" /* CF_AGENT_STATE */
|
|
383
454
|
}),
|
|
384
455
|
source !== "server" ? [source.id] : []
|
|
385
456
|
);
|
|
386
457
|
return this._tryCatch(() => {
|
|
387
|
-
const { connection, request } = agentContext.getStore() || {};
|
|
458
|
+
const { connection, request, email } = agentContext.getStore() || {};
|
|
388
459
|
return agentContext.run(
|
|
389
|
-
{ agent: this, connection, request },
|
|
460
|
+
{ agent: this, connection, request, email },
|
|
390
461
|
async () => {
|
|
391
462
|
this.observability?.emit(
|
|
392
463
|
{
|
|
393
464
|
displayMessage: "State updated",
|
|
394
465
|
id: nanoid(),
|
|
395
|
-
payload: {
|
|
396
|
-
previousState,
|
|
397
|
-
state
|
|
398
|
-
},
|
|
466
|
+
payload: {},
|
|
399
467
|
timestamp: Date.now(),
|
|
400
468
|
type: "state:update"
|
|
401
469
|
},
|
|
@@ -422,18 +490,67 @@ var Agent = class extends Server {
|
|
|
422
490
|
onStateUpdate(state, source) {
|
|
423
491
|
}
|
|
424
492
|
/**
|
|
425
|
-
* Called when the Agent receives an email
|
|
493
|
+
* Called when the Agent receives an email via routeAgentEmail()
|
|
494
|
+
* Override this method to handle incoming emails
|
|
426
495
|
* @param email Email message to process
|
|
427
496
|
*/
|
|
428
|
-
|
|
429
|
-
onEmail(email) {
|
|
497
|
+
async _onEmail(email) {
|
|
430
498
|
return agentContext.run(
|
|
431
|
-
{ agent: this, connection: void 0, request: void 0 },
|
|
499
|
+
{ agent: this, connection: void 0, request: void 0, email },
|
|
432
500
|
async () => {
|
|
433
|
-
|
|
501
|
+
if ("onEmail" in this && typeof this.onEmail === "function") {
|
|
502
|
+
return this._tryCatch(
|
|
503
|
+
() => this.onEmail(email)
|
|
504
|
+
);
|
|
505
|
+
} else {
|
|
506
|
+
console.log("Received email from:", email.from, "to:", email.to);
|
|
507
|
+
console.log("Subject:", email.headers.get("subject"));
|
|
508
|
+
console.log(
|
|
509
|
+
"Implement onEmail(email: AgentEmail): Promise<void> in your agent to process emails"
|
|
510
|
+
);
|
|
511
|
+
}
|
|
434
512
|
}
|
|
435
513
|
);
|
|
436
514
|
}
|
|
515
|
+
/**
|
|
516
|
+
* Reply to an email
|
|
517
|
+
* @param email The email to reply to
|
|
518
|
+
* @param options Options for the reply
|
|
519
|
+
* @returns void
|
|
520
|
+
*/
|
|
521
|
+
async replyToEmail(email, options) {
|
|
522
|
+
return this._tryCatch(async () => {
|
|
523
|
+
const agentName = camelCaseToKebabCase(this._ParentClass.name);
|
|
524
|
+
const agentId = this.name;
|
|
525
|
+
const { createMimeMessage } = await import("mimetext");
|
|
526
|
+
const msg = createMimeMessage();
|
|
527
|
+
msg.setSender({ addr: email.to, name: options.fromName });
|
|
528
|
+
msg.setRecipient(email.from);
|
|
529
|
+
msg.setSubject(
|
|
530
|
+
options.subject || `Re: ${email.headers.get("subject")}` || "No subject"
|
|
531
|
+
);
|
|
532
|
+
msg.addMessage({
|
|
533
|
+
contentType: options.contentType || "text/plain",
|
|
534
|
+
data: options.body
|
|
535
|
+
});
|
|
536
|
+
const domain = email.from.split("@")[1];
|
|
537
|
+
const messageId = `<${agentId}@${domain}>`;
|
|
538
|
+
msg.setHeader("In-Reply-To", email.headers.get("Message-ID"));
|
|
539
|
+
msg.setHeader("Message-ID", messageId);
|
|
540
|
+
msg.setHeader("X-Agent-Name", agentName);
|
|
541
|
+
msg.setHeader("X-Agent-ID", agentId);
|
|
542
|
+
if (options.headers) {
|
|
543
|
+
for (const [key, value] of Object.entries(options.headers)) {
|
|
544
|
+
msg.setHeader(key, value);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
await email.reply({
|
|
548
|
+
from: email.to,
|
|
549
|
+
raw: msg.asRaw(),
|
|
550
|
+
to: email.from
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
}
|
|
437
554
|
async _tryCatch(fn) {
|
|
438
555
|
try {
|
|
439
556
|
return await fn();
|
|
@@ -441,6 +558,49 @@ var Agent = class extends Server {
|
|
|
441
558
|
throw this.onError(e);
|
|
442
559
|
}
|
|
443
560
|
}
|
|
561
|
+
/**
|
|
562
|
+
* Automatically wrap custom methods with agent context
|
|
563
|
+
* This ensures getCurrentAgent() works in all custom methods without decorators
|
|
564
|
+
*/
|
|
565
|
+
_autoWrapCustomMethods() {
|
|
566
|
+
const basePrototypes = [_Agent.prototype, Server.prototype];
|
|
567
|
+
const baseMethods = /* @__PURE__ */ new Set();
|
|
568
|
+
for (const baseProto of basePrototypes) {
|
|
569
|
+
let proto2 = baseProto;
|
|
570
|
+
while (proto2 && proto2 !== Object.prototype) {
|
|
571
|
+
const methodNames = Object.getOwnPropertyNames(proto2);
|
|
572
|
+
for (const methodName of methodNames) {
|
|
573
|
+
baseMethods.add(methodName);
|
|
574
|
+
}
|
|
575
|
+
proto2 = Object.getPrototypeOf(proto2);
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
let proto = Object.getPrototypeOf(this);
|
|
579
|
+
let depth = 0;
|
|
580
|
+
while (proto && proto !== Object.prototype && depth < 10) {
|
|
581
|
+
const methodNames = Object.getOwnPropertyNames(proto);
|
|
582
|
+
for (const methodName of methodNames) {
|
|
583
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
|
|
584
|
+
if (baseMethods.has(methodName) || methodName.startsWith("_") || !descriptor || !!descriptor.get || typeof descriptor.value !== "function") {
|
|
585
|
+
continue;
|
|
586
|
+
}
|
|
587
|
+
const wrappedFunction = withAgentContext(
|
|
588
|
+
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
589
|
+
this[methodName]
|
|
590
|
+
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
591
|
+
);
|
|
592
|
+
if (this._isCallable(methodName)) {
|
|
593
|
+
callableMetadata.set(
|
|
594
|
+
wrappedFunction,
|
|
595
|
+
callableMetadata.get(this[methodName])
|
|
596
|
+
);
|
|
597
|
+
}
|
|
598
|
+
this.constructor.prototype[methodName] = wrappedFunction;
|
|
599
|
+
}
|
|
600
|
+
proto = Object.getPrototypeOf(proto);
|
|
601
|
+
depth++;
|
|
602
|
+
}
|
|
603
|
+
}
|
|
444
604
|
onError(connectionOrError, error) {
|
|
445
605
|
let theError;
|
|
446
606
|
if (connectionOrError && error) {
|
|
@@ -466,6 +626,108 @@ var Agent = class extends Server {
|
|
|
466
626
|
render() {
|
|
467
627
|
throw new Error("Not implemented");
|
|
468
628
|
}
|
|
629
|
+
/**
|
|
630
|
+
* Queue a task to be executed in the future
|
|
631
|
+
* @param payload Payload to pass to the callback
|
|
632
|
+
* @param callback Name of the method to call
|
|
633
|
+
* @returns The ID of the queued task
|
|
634
|
+
*/
|
|
635
|
+
async queue(callback, payload) {
|
|
636
|
+
const id = nanoid(9);
|
|
637
|
+
if (typeof callback !== "string") {
|
|
638
|
+
throw new Error("Callback must be a string");
|
|
639
|
+
}
|
|
640
|
+
if (typeof this[callback] !== "function") {
|
|
641
|
+
throw new Error(`this.${callback} is not a function`);
|
|
642
|
+
}
|
|
643
|
+
this.sql`
|
|
644
|
+
INSERT OR REPLACE INTO cf_agents_queues (id, payload, callback)
|
|
645
|
+
VALUES (${id}, ${JSON.stringify(payload)}, ${callback})
|
|
646
|
+
`;
|
|
647
|
+
void this._flushQueue().catch((e) => {
|
|
648
|
+
console.error("Error flushing queue:", e);
|
|
649
|
+
});
|
|
650
|
+
return id;
|
|
651
|
+
}
|
|
652
|
+
async _flushQueue() {
|
|
653
|
+
if (this._flushingQueue) {
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
656
|
+
this._flushingQueue = true;
|
|
657
|
+
while (true) {
|
|
658
|
+
const result = this.sql`
|
|
659
|
+
SELECT * FROM cf_agents_queues
|
|
660
|
+
ORDER BY created_at ASC
|
|
661
|
+
`;
|
|
662
|
+
if (!result || result.length === 0) {
|
|
663
|
+
break;
|
|
664
|
+
}
|
|
665
|
+
for (const row of result || []) {
|
|
666
|
+
const callback = this[row.callback];
|
|
667
|
+
if (!callback) {
|
|
668
|
+
console.error(`callback ${row.callback} not found`);
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
const { connection, request, email } = agentContext.getStore() || {};
|
|
672
|
+
await agentContext.run(
|
|
673
|
+
{
|
|
674
|
+
agent: this,
|
|
675
|
+
connection,
|
|
676
|
+
request,
|
|
677
|
+
email
|
|
678
|
+
},
|
|
679
|
+
async () => {
|
|
680
|
+
await callback.bind(this)(JSON.parse(row.payload), row);
|
|
681
|
+
await this.dequeue(row.id);
|
|
682
|
+
}
|
|
683
|
+
);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
this._flushingQueue = false;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Dequeue a task by ID
|
|
690
|
+
* @param id ID of the task to dequeue
|
|
691
|
+
*/
|
|
692
|
+
async dequeue(id) {
|
|
693
|
+
this.sql`DELETE FROM cf_agents_queues WHERE id = ${id}`;
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Dequeue all tasks
|
|
697
|
+
*/
|
|
698
|
+
async dequeueAll() {
|
|
699
|
+
this.sql`DELETE FROM cf_agents_queues`;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Dequeue all tasks by callback
|
|
703
|
+
* @param callback Name of the callback to dequeue
|
|
704
|
+
*/
|
|
705
|
+
async dequeueAllByCallback(callback) {
|
|
706
|
+
this.sql`DELETE FROM cf_agents_queues WHERE callback = ${callback}`;
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* Get a queued task by ID
|
|
710
|
+
* @param id ID of the task to get
|
|
711
|
+
* @returns The task or undefined if not found
|
|
712
|
+
*/
|
|
713
|
+
async getQueue(id) {
|
|
714
|
+
const result = this.sql`
|
|
715
|
+
SELECT * FROM cf_agents_queues WHERE id = ${id}
|
|
716
|
+
`;
|
|
717
|
+
return result ? { ...result[0], payload: JSON.parse(result[0].payload) } : void 0;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Get all queues by key and value
|
|
721
|
+
* @param key Key to filter by
|
|
722
|
+
* @param value Value to filter by
|
|
723
|
+
* @returns Array of matching QueueItem objects
|
|
724
|
+
*/
|
|
725
|
+
async getQueues(key, value) {
|
|
726
|
+
const result = this.sql`
|
|
727
|
+
SELECT * FROM cf_agents_queues
|
|
728
|
+
`;
|
|
729
|
+
return result.filter((row) => JSON.parse(row.payload)[key] === value);
|
|
730
|
+
}
|
|
469
731
|
/**
|
|
470
732
|
* Schedule a task to be executed in the future
|
|
471
733
|
* @template T Type of the payload data
|
|
@@ -480,7 +742,10 @@ var Agent = class extends Server {
|
|
|
480
742
|
{
|
|
481
743
|
displayMessage: `Schedule ${schedule.id} created`,
|
|
482
744
|
id: nanoid(),
|
|
483
|
-
payload:
|
|
745
|
+
payload: {
|
|
746
|
+
callback,
|
|
747
|
+
id
|
|
748
|
+
},
|
|
484
749
|
timestamp: Date.now(),
|
|
485
750
|
type: "schedule:create"
|
|
486
751
|
},
|
|
@@ -615,7 +880,10 @@ var Agent = class extends Server {
|
|
|
615
880
|
{
|
|
616
881
|
displayMessage: `Schedule ${id} cancelled`,
|
|
617
882
|
id: nanoid(),
|
|
618
|
-
payload:
|
|
883
|
+
payload: {
|
|
884
|
+
callback: schedule.callback,
|
|
885
|
+
id: schedule.id
|
|
886
|
+
},
|
|
619
887
|
timestamp: Date.now(),
|
|
620
888
|
type: "schedule:cancel"
|
|
621
889
|
},
|
|
@@ -628,9 +896,9 @@ var Agent = class extends Server {
|
|
|
628
896
|
}
|
|
629
897
|
async _scheduleNextAlarm() {
|
|
630
898
|
const result = this.sql`
|
|
631
|
-
SELECT time FROM cf_agents_schedules
|
|
899
|
+
SELECT time FROM cf_agents_schedules
|
|
632
900
|
WHERE time > ${Math.floor(Date.now() / 1e3)}
|
|
633
|
-
ORDER BY time ASC
|
|
901
|
+
ORDER BY time ASC
|
|
634
902
|
LIMIT 1
|
|
635
903
|
`;
|
|
636
904
|
if (!result) return;
|
|
@@ -646,8 +914,11 @@ var Agent = class extends Server {
|
|
|
646
914
|
this.sql`DROP TABLE IF EXISTS cf_agents_state`;
|
|
647
915
|
this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;
|
|
648
916
|
this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
|
|
917
|
+
this.sql`DROP TABLE IF EXISTS cf_agents_queues`;
|
|
649
918
|
await this.ctx.storage.deleteAlarm();
|
|
650
919
|
await this.ctx.storage.deleteAll();
|
|
920
|
+
this._disposables.dispose();
|
|
921
|
+
await this.mcp.dispose?.();
|
|
651
922
|
this.ctx.abort("destroyed");
|
|
652
923
|
this.observability?.emit(
|
|
653
924
|
{
|
|
@@ -670,14 +941,26 @@ var Agent = class extends Server {
|
|
|
670
941
|
/**
|
|
671
942
|
* Connect to a new MCP Server
|
|
672
943
|
*
|
|
944
|
+
* @param serverName Name of the MCP server
|
|
673
945
|
* @param url MCP Server SSE URL
|
|
674
|
-
* @param callbackHost Base host for the agent, used for the redirect URI.
|
|
946
|
+
* @param callbackHost Base host for the agent, used for the redirect URI. If not provided, will be derived from the current request.
|
|
675
947
|
* @param agentsPrefix agents routing prefix if not using `agents`
|
|
676
|
-
* @param options MCP client and transport
|
|
948
|
+
* @param options MCP client and transport options
|
|
677
949
|
* @returns authUrl
|
|
678
950
|
*/
|
|
679
951
|
async addMcpServer(serverName, url, callbackHost, agentsPrefix = "agents", options) {
|
|
680
|
-
|
|
952
|
+
let resolvedCallbackHost = callbackHost;
|
|
953
|
+
if (!resolvedCallbackHost) {
|
|
954
|
+
const { request } = getCurrentAgent();
|
|
955
|
+
if (!request) {
|
|
956
|
+
throw new Error(
|
|
957
|
+
"callbackHost is required when not called within a request context"
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
const requestUrl = new URL(request.url);
|
|
961
|
+
resolvedCallbackHost = `${requestUrl.protocol}//${requestUrl.host}`;
|
|
962
|
+
}
|
|
963
|
+
const callbackUrl = `${resolvedCallbackHost}/${agentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;
|
|
681
964
|
const result = await this._connectToMcpServerInternal(
|
|
682
965
|
serverName,
|
|
683
966
|
url,
|
|
@@ -697,12 +980,7 @@ var Agent = class extends Server {
|
|
|
697
980
|
${options ? JSON.stringify(options) : null}
|
|
698
981
|
);
|
|
699
982
|
`;
|
|
700
|
-
this.
|
|
701
|
-
JSON.stringify({
|
|
702
|
-
mcp: this.getMcpServers(),
|
|
703
|
-
type: "cf_agent_mcp_servers"
|
|
704
|
-
})
|
|
705
|
-
);
|
|
983
|
+
this.broadcastMcpServers();
|
|
706
984
|
return result;
|
|
707
985
|
}
|
|
708
986
|
async _connectToMcpServerInternal(_serverName, url, callbackUrl, options, reconnect) {
|
|
@@ -717,6 +995,7 @@ var Agent = class extends Server {
|
|
|
717
995
|
authProvider.clientId = reconnect.oauthClientId;
|
|
718
996
|
}
|
|
719
997
|
}
|
|
998
|
+
const transportType = options?.transport?.type ?? "auto";
|
|
720
999
|
let headerTransportOpts = {};
|
|
721
1000
|
if (options?.transport?.headers) {
|
|
722
1001
|
headerTransportOpts = {
|
|
@@ -736,7 +1015,8 @@ var Agent = class extends Server {
|
|
|
736
1015
|
reconnect,
|
|
737
1016
|
transport: {
|
|
738
1017
|
...headerTransportOpts,
|
|
739
|
-
authProvider
|
|
1018
|
+
authProvider,
|
|
1019
|
+
type: transportType
|
|
740
1020
|
}
|
|
741
1021
|
});
|
|
742
1022
|
return {
|
|
@@ -747,15 +1027,11 @@ var Agent = class extends Server {
|
|
|
747
1027
|
}
|
|
748
1028
|
async removeMcpServer(id) {
|
|
749
1029
|
this.mcp.closeConnection(id);
|
|
1030
|
+
this.mcp.unregisterCallbackUrl(id);
|
|
750
1031
|
this.sql`
|
|
751
1032
|
DELETE FROM cf_agents_mcp_servers WHERE id = ${id};
|
|
752
1033
|
`;
|
|
753
|
-
this.
|
|
754
|
-
JSON.stringify({
|
|
755
|
-
mcp: this.getMcpServers(),
|
|
756
|
-
type: "cf_agent_mcp_servers"
|
|
757
|
-
})
|
|
758
|
-
);
|
|
1034
|
+
this.broadcastMcpServers();
|
|
759
1035
|
}
|
|
760
1036
|
getMcpServers() {
|
|
761
1037
|
const mcpState = {
|
|
@@ -767,29 +1043,63 @@ var Agent = class extends Server {
|
|
|
767
1043
|
const servers = this.sql`
|
|
768
1044
|
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
769
1045
|
`;
|
|
770
|
-
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
1046
|
+
if (servers && Array.isArray(servers) && servers.length > 0) {
|
|
1047
|
+
for (const server of servers) {
|
|
1048
|
+
const serverConn = this.mcp.mcpConnections[server.id];
|
|
1049
|
+
mcpState.servers[server.id] = {
|
|
1050
|
+
auth_url: server.auth_url,
|
|
1051
|
+
capabilities: serverConn?.serverCapabilities ?? null,
|
|
1052
|
+
instructions: serverConn?.instructions ?? null,
|
|
1053
|
+
name: server.name,
|
|
1054
|
+
server_url: server.server_url,
|
|
1055
|
+
// mark as "authenticating" because the server isn't automatically connected, so it's pending authenticating
|
|
1056
|
+
state: serverConn?.connectionState ?? "authenticating"
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
781
1059
|
}
|
|
782
1060
|
return mcpState;
|
|
783
1061
|
}
|
|
1062
|
+
broadcastMcpServers() {
|
|
1063
|
+
this.broadcast(
|
|
1064
|
+
JSON.stringify({
|
|
1065
|
+
mcp: this.getMcpServers(),
|
|
1066
|
+
type: "cf_agent_mcp_servers" /* CF_AGENT_MCP_SERVERS */
|
|
1067
|
+
})
|
|
1068
|
+
);
|
|
1069
|
+
}
|
|
1070
|
+
/**
|
|
1071
|
+
* Handle OAuth callback response using MCPClientManager configuration
|
|
1072
|
+
* @param result OAuth callback result
|
|
1073
|
+
* @param request The original request (needed for base URL)
|
|
1074
|
+
* @returns Response for the OAuth callback
|
|
1075
|
+
*/
|
|
1076
|
+
handleOAuthCallbackResponse(result, request) {
|
|
1077
|
+
const config = this.mcp.getOAuthCallbackConfig();
|
|
1078
|
+
if (config?.customHandler) {
|
|
1079
|
+
return config.customHandler(result);
|
|
1080
|
+
}
|
|
1081
|
+
if (config?.successRedirect && result.authSuccess) {
|
|
1082
|
+
return Response.redirect(config.successRedirect);
|
|
1083
|
+
}
|
|
1084
|
+
if (config?.errorRedirect && !result.authSuccess) {
|
|
1085
|
+
return Response.redirect(
|
|
1086
|
+
`${config.errorRedirect}?error=${encodeURIComponent(result.authError || "Unknown error")}`
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
const baseUrl = new URL(request.url).origin;
|
|
1090
|
+
return Response.redirect(baseUrl);
|
|
1091
|
+
}
|
|
784
1092
|
};
|
|
785
1093
|
/**
|
|
786
1094
|
* Agent configuration options
|
|
787
1095
|
*/
|
|
788
|
-
|
|
1096
|
+
_Agent.options = {
|
|
789
1097
|
/** Whether the Agent should hibernate when inactive */
|
|
790
1098
|
hibernate: true
|
|
791
1099
|
// default to hibernate
|
|
792
1100
|
};
|
|
1101
|
+
var Agent = _Agent;
|
|
1102
|
+
var wrappedClasses = /* @__PURE__ */ new Set();
|
|
793
1103
|
async function routeAgentRequest(request, env, options) {
|
|
794
1104
|
const corsHeaders = options?.cors === true ? {
|
|
795
1105
|
"Access-Control-Allow-Credentials": "true",
|
|
@@ -825,7 +1135,126 @@ async function routeAgentRequest(request, env, options) {
|
|
|
825
1135
|
}
|
|
826
1136
|
return response;
|
|
827
1137
|
}
|
|
828
|
-
|
|
1138
|
+
function createHeaderBasedEmailResolver() {
|
|
1139
|
+
return async (email, _env) => {
|
|
1140
|
+
const messageId = email.headers.get("message-id");
|
|
1141
|
+
if (messageId) {
|
|
1142
|
+
const messageIdMatch = messageId.match(/<([^@]+)@([^>]+)>/);
|
|
1143
|
+
if (messageIdMatch) {
|
|
1144
|
+
const [, agentId2, domain] = messageIdMatch;
|
|
1145
|
+
const agentName2 = domain.split(".")[0];
|
|
1146
|
+
return { agentName: agentName2, agentId: agentId2 };
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
const references = email.headers.get("references");
|
|
1150
|
+
if (references) {
|
|
1151
|
+
const referencesMatch = references.match(
|
|
1152
|
+
/<([A-Za-z0-9+/]{43}=)@([^>]+)>/
|
|
1153
|
+
);
|
|
1154
|
+
if (referencesMatch) {
|
|
1155
|
+
const [, base64Id, domain] = referencesMatch;
|
|
1156
|
+
const agentId2 = Buffer.from(base64Id, "base64").toString("hex");
|
|
1157
|
+
const agentName2 = domain.split(".")[0];
|
|
1158
|
+
return { agentName: agentName2, agentId: agentId2 };
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
const agentName = email.headers.get("x-agent-name");
|
|
1162
|
+
const agentId = email.headers.get("x-agent-id");
|
|
1163
|
+
if (agentName && agentId) {
|
|
1164
|
+
return { agentName, agentId };
|
|
1165
|
+
}
|
|
1166
|
+
return null;
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
function createAddressBasedEmailResolver(defaultAgentName) {
|
|
1170
|
+
return async (email, _env) => {
|
|
1171
|
+
const emailMatch = email.to.match(/^([^+@]+)(?:\+([^@]+))?@(.+)$/);
|
|
1172
|
+
if (!emailMatch) {
|
|
1173
|
+
return null;
|
|
1174
|
+
}
|
|
1175
|
+
const [, localPart, subAddress] = emailMatch;
|
|
1176
|
+
if (subAddress) {
|
|
1177
|
+
return {
|
|
1178
|
+
agentName: localPart,
|
|
1179
|
+
agentId: subAddress
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
return {
|
|
1183
|
+
agentName: defaultAgentName,
|
|
1184
|
+
agentId: localPart
|
|
1185
|
+
};
|
|
1186
|
+
};
|
|
1187
|
+
}
|
|
1188
|
+
function createCatchAllEmailResolver(agentName, agentId) {
|
|
1189
|
+
return async () => ({ agentName, agentId });
|
|
1190
|
+
}
|
|
1191
|
+
var agentMapCache = /* @__PURE__ */ new WeakMap();
|
|
1192
|
+
async function routeAgentEmail(email, env, options) {
|
|
1193
|
+
const routingInfo = await options.resolver(email, env);
|
|
1194
|
+
if (!routingInfo) {
|
|
1195
|
+
console.warn("No routing information found for email, dropping message");
|
|
1196
|
+
return;
|
|
1197
|
+
}
|
|
1198
|
+
if (!agentMapCache.has(env)) {
|
|
1199
|
+
const map = {};
|
|
1200
|
+
for (const [key, value] of Object.entries(env)) {
|
|
1201
|
+
if (value && typeof value === "object" && "idFromName" in value && typeof value.idFromName === "function") {
|
|
1202
|
+
map[key] = value;
|
|
1203
|
+
map[camelCaseToKebabCase(key)] = value;
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
agentMapCache.set(env, map);
|
|
1207
|
+
}
|
|
1208
|
+
const agentMap = agentMapCache.get(env);
|
|
1209
|
+
const namespace = agentMap[routingInfo.agentName];
|
|
1210
|
+
if (!namespace) {
|
|
1211
|
+
const availableAgents = Object.keys(agentMap).filter((key) => !key.includes("-")).join(", ");
|
|
1212
|
+
throw new Error(
|
|
1213
|
+
`Agent namespace '${routingInfo.agentName}' not found in environment. Available agents: ${availableAgents}`
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1216
|
+
const agent = await getAgentByName(
|
|
1217
|
+
namespace,
|
|
1218
|
+
routingInfo.agentId
|
|
1219
|
+
);
|
|
1220
|
+
const serialisableEmail = {
|
|
1221
|
+
getRaw: async () => {
|
|
1222
|
+
const reader = email.raw.getReader();
|
|
1223
|
+
const chunks = [];
|
|
1224
|
+
let done = false;
|
|
1225
|
+
while (!done) {
|
|
1226
|
+
const { value, done: readerDone } = await reader.read();
|
|
1227
|
+
done = readerDone;
|
|
1228
|
+
if (value) {
|
|
1229
|
+
chunks.push(value);
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
|
|
1233
|
+
const combined = new Uint8Array(totalLength);
|
|
1234
|
+
let offset = 0;
|
|
1235
|
+
for (const chunk of chunks) {
|
|
1236
|
+
combined.set(chunk, offset);
|
|
1237
|
+
offset += chunk.length;
|
|
1238
|
+
}
|
|
1239
|
+
return combined;
|
|
1240
|
+
},
|
|
1241
|
+
headers: email.headers,
|
|
1242
|
+
rawSize: email.rawSize,
|
|
1243
|
+
setReject: (reason) => {
|
|
1244
|
+
email.setReject(reason);
|
|
1245
|
+
},
|
|
1246
|
+
forward: (rcptTo, headers) => {
|
|
1247
|
+
return email.forward(rcptTo, headers);
|
|
1248
|
+
},
|
|
1249
|
+
reply: (options2) => {
|
|
1250
|
+
return email.reply(
|
|
1251
|
+
new EmailMessage(options2.from, options2.to, options2.raw)
|
|
1252
|
+
);
|
|
1253
|
+
},
|
|
1254
|
+
from: email.from,
|
|
1255
|
+
to: email.to
|
|
1256
|
+
};
|
|
1257
|
+
await agent._onEmail(serialisableEmail);
|
|
829
1258
|
}
|
|
830
1259
|
async function getAgentByName(namespace, name, options) {
|
|
831
1260
|
return getServerByName(namespace, name, options);
|
|
@@ -849,7 +1278,7 @@ var StreamingResponse = class {
|
|
|
849
1278
|
id: this._id,
|
|
850
1279
|
result: chunk,
|
|
851
1280
|
success: true,
|
|
852
|
-
type: "rpc"
|
|
1281
|
+
type: "rpc" /* RPC */
|
|
853
1282
|
};
|
|
854
1283
|
this._connection.send(JSON.stringify(response));
|
|
855
1284
|
}
|
|
@@ -867,7 +1296,7 @@ var StreamingResponse = class {
|
|
|
867
1296
|
id: this._id,
|
|
868
1297
|
result: finalChunk,
|
|
869
1298
|
success: true,
|
|
870
|
-
type: "rpc"
|
|
1299
|
+
type: "rpc" /* RPC */
|
|
871
1300
|
};
|
|
872
1301
|
this._connection.send(JSON.stringify(response));
|
|
873
1302
|
}
|
|
@@ -899,12 +1328,16 @@ function isLocalMode() {
|
|
|
899
1328
|
|
|
900
1329
|
export {
|
|
901
1330
|
genericObservability,
|
|
1331
|
+
callable,
|
|
902
1332
|
unstable_callable,
|
|
903
1333
|
getCurrentAgent,
|
|
904
1334
|
Agent,
|
|
905
1335
|
routeAgentRequest,
|
|
1336
|
+
createHeaderBasedEmailResolver,
|
|
1337
|
+
createAddressBasedEmailResolver,
|
|
1338
|
+
createCatchAllEmailResolver,
|
|
906
1339
|
routeAgentEmail,
|
|
907
1340
|
getAgentByName,
|
|
908
1341
|
StreamingResponse
|
|
909
1342
|
};
|
|
910
|
-
//# sourceMappingURL=chunk-
|
|
1343
|
+
//# sourceMappingURL=chunk-2Y6KNRNP.js.map
|