agents 0.0.0-de168a2 → 0.0.0-df41827
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/dist/ai-chat-agent.d.ts +46 -4
- package/dist/ai-chat-agent.js +138 -68
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.d.ts +17 -4
- package/dist/ai-react.js +49 -42
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types.d.ts +5 -0
- package/dist/chunk-767EASBA.js +106 -0
- package/dist/chunk-767EASBA.js.map +1 -0
- package/dist/chunk-E3LCYPCB.js +469 -0
- package/dist/chunk-E3LCYPCB.js.map +1 -0
- package/dist/chunk-NKZZ66QY.js +116 -0
- package/dist/chunk-NKZZ66QY.js.map +1 -0
- package/dist/{chunk-XG52S6YY.js → chunk-ZRRXJUAA.js} +357 -160
- package/dist/chunk-ZRRXJUAA.js.map +1 -0
- package/dist/client.d.ts +15 -1
- package/dist/client.js +6 -126
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +123 -14
- package/dist/index.js +8 -6
- package/dist/mcp/client.d.ts +34 -14
- package/dist/mcp/client.js +3 -402
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/do-oauth-client-provider.d.ts +3 -3
- package/dist/mcp/do-oauth-client-provider.js +3 -103
- package/dist/mcp/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/index.d.ts +44 -5
- package/dist/mcp/index.js +593 -159
- package/dist/mcp/index.js.map +1 -1
- package/dist/react.d.ts +85 -5
- package/dist/react.js +20 -8
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +2 -2
- package/dist/schedule.js +4 -6
- package/dist/schedule.js.map +1 -1
- package/dist/serializable.d.ts +32 -0
- package/dist/serializable.js +1 -0
- package/package.json +71 -56
- package/src/index.ts +429 -86
- package/dist/chunk-HMLY7DHA.js +0 -16
- package/dist/chunk-XG52S6YY.js.map +0 -1
- /package/dist/{chunk-HMLY7DHA.js.map → serializable.js.map} +0 -0
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from "./chunk-
|
|
2
|
+
MCPClientManager
|
|
3
|
+
} from "./chunk-E3LCYPCB.js";
|
|
4
|
+
import {
|
|
5
|
+
DurableObjectOAuthClientProvider
|
|
6
|
+
} from "./chunk-767EASBA.js";
|
|
7
|
+
import {
|
|
8
|
+
camelCaseToKebabCase
|
|
9
|
+
} from "./chunk-NKZZ66QY.js";
|
|
7
10
|
|
|
8
11
|
// src/index.ts
|
|
12
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
13
|
+
import { parseCronExpression } from "cron-schedule";
|
|
14
|
+
import { nanoid } from "nanoid";
|
|
9
15
|
import {
|
|
10
|
-
|
|
16
|
+
getServerByName,
|
|
11
17
|
routePartykitRequest,
|
|
12
|
-
|
|
18
|
+
Server
|
|
13
19
|
} from "partyserver";
|
|
14
|
-
import { parseCronExpression } from "cron-schedule";
|
|
15
|
-
import { nanoid } from "nanoid";
|
|
16
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
17
20
|
function isRPCRequest(msg) {
|
|
18
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);
|
|
19
22
|
}
|
|
@@ -36,18 +39,72 @@ function getNextCronTime(cron) {
|
|
|
36
39
|
var STATE_ROW_ID = "cf_state_row_id";
|
|
37
40
|
var STATE_WAS_CHANGED = "cf_state_was_changed";
|
|
38
41
|
var DEFAULT_STATE = {};
|
|
39
|
-
var
|
|
40
|
-
|
|
42
|
+
var agentContext = new AsyncLocalStorage();
|
|
43
|
+
function getCurrentAgent() {
|
|
44
|
+
const store = agentContext.getStore();
|
|
45
|
+
if (!store) {
|
|
46
|
+
return {
|
|
47
|
+
agent: void 0,
|
|
48
|
+
connection: void 0,
|
|
49
|
+
request: void 0
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return store;
|
|
53
|
+
}
|
|
41
54
|
var Agent = class extends Server {
|
|
42
55
|
constructor(ctx, env) {
|
|
43
56
|
super(ctx, env);
|
|
44
|
-
|
|
45
|
-
|
|
57
|
+
this._state = DEFAULT_STATE;
|
|
58
|
+
this._ParentClass = Object.getPrototypeOf(this).constructor;
|
|
59
|
+
this.mcp = new MCPClientManager(this._ParentClass.name, "0.0.1");
|
|
46
60
|
/**
|
|
47
61
|
* Initial state for the Agent
|
|
48
62
|
* Override to provide default state values
|
|
49
63
|
*/
|
|
50
64
|
this.initialState = DEFAULT_STATE;
|
|
65
|
+
/**
|
|
66
|
+
* Method called when an alarm fires.
|
|
67
|
+
* Executes any scheduled tasks that are due.
|
|
68
|
+
*
|
|
69
|
+
* @remarks
|
|
70
|
+
* To schedule a task, please use the `this.schedule` method instead.
|
|
71
|
+
* See {@link https://developers.cloudflare.com/agents/api-reference/schedule-tasks/}
|
|
72
|
+
*/
|
|
73
|
+
this.alarm = async () => {
|
|
74
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
75
|
+
const result = this.sql`
|
|
76
|
+
SELECT * FROM cf_agents_schedules WHERE time <= ${now}
|
|
77
|
+
`;
|
|
78
|
+
for (const row of result || []) {
|
|
79
|
+
const callback = this[row.callback];
|
|
80
|
+
if (!callback) {
|
|
81
|
+
console.error(`callback ${row.callback} not found`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
await agentContext.run(
|
|
85
|
+
{ agent: this, connection: void 0, request: void 0 },
|
|
86
|
+
async () => {
|
|
87
|
+
try {
|
|
88
|
+
await callback.bind(this)(JSON.parse(row.payload), row);
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.error(`error executing callback "${row.callback}"`, e);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
if (row.type === "cron") {
|
|
95
|
+
const nextExecutionTime = getNextCronTime(row.cron);
|
|
96
|
+
const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1e3);
|
|
97
|
+
this.sql`
|
|
98
|
+
UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}
|
|
99
|
+
`;
|
|
100
|
+
} else {
|
|
101
|
+
this.sql`
|
|
102
|
+
DELETE FROM cf_agents_schedules WHERE id = ${row.id}
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
await this._scheduleNextAlarm();
|
|
107
|
+
};
|
|
51
108
|
this.sql`
|
|
52
109
|
CREATE TABLE IF NOT EXISTS cf_agents_state (
|
|
53
110
|
id TEXT PRIMARY KEY NOT NULL,
|
|
@@ -55,7 +112,7 @@ var Agent = class extends Server {
|
|
|
55
112
|
)
|
|
56
113
|
`;
|
|
57
114
|
void this.ctx.blockConcurrencyWhile(async () => {
|
|
58
|
-
return
|
|
115
|
+
return this._tryCatch(async () => {
|
|
59
116
|
this.sql`
|
|
60
117
|
CREATE TABLE IF NOT EXISTS cf_agents_schedules (
|
|
61
118
|
id TEXT PRIMARY KEY NOT NULL DEFAULT (randomblob(9)),
|
|
@@ -71,22 +128,55 @@ var Agent = class extends Server {
|
|
|
71
128
|
await this.alarm();
|
|
72
129
|
});
|
|
73
130
|
});
|
|
131
|
+
this.sql`
|
|
132
|
+
CREATE TABLE IF NOT EXISTS cf_agents_mcp_servers (
|
|
133
|
+
id TEXT PRIMARY KEY NOT NULL,
|
|
134
|
+
name TEXT NOT NULL,
|
|
135
|
+
server_url TEXT NOT NULL,
|
|
136
|
+
callback_url TEXT NOT NULL,
|
|
137
|
+
client_id TEXT,
|
|
138
|
+
auth_url TEXT,
|
|
139
|
+
server_options TEXT
|
|
140
|
+
)
|
|
141
|
+
`;
|
|
142
|
+
const _onRequest = this.onRequest.bind(this);
|
|
143
|
+
this.onRequest = (request) => {
|
|
144
|
+
return agentContext.run(
|
|
145
|
+
{ agent: this, connection: void 0, request },
|
|
146
|
+
async () => {
|
|
147
|
+
if (this.mcp.isCallbackRequest(request)) {
|
|
148
|
+
await this.mcp.handleCallbackRequest(request);
|
|
149
|
+
this.broadcast(
|
|
150
|
+
JSON.stringify({
|
|
151
|
+
mcp: this.getMcpServers(),
|
|
152
|
+
type: "cf_agent_mcp_servers"
|
|
153
|
+
})
|
|
154
|
+
);
|
|
155
|
+
return new Response("<script>window.close();</script>", {
|
|
156
|
+
headers: { "content-type": "text/html" },
|
|
157
|
+
status: 200
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return this._tryCatch(() => _onRequest(request));
|
|
161
|
+
}
|
|
162
|
+
);
|
|
163
|
+
};
|
|
74
164
|
const _onMessage = this.onMessage.bind(this);
|
|
75
165
|
this.onMessage = async (connection, message) => {
|
|
76
|
-
return
|
|
166
|
+
return agentContext.run(
|
|
77
167
|
{ agent: this, connection, request: void 0 },
|
|
78
168
|
async () => {
|
|
79
169
|
if (typeof message !== "string") {
|
|
80
|
-
return
|
|
170
|
+
return this._tryCatch(() => _onMessage(connection, message));
|
|
81
171
|
}
|
|
82
172
|
let parsed;
|
|
83
173
|
try {
|
|
84
174
|
parsed = JSON.parse(message);
|
|
85
|
-
} catch (
|
|
86
|
-
return
|
|
175
|
+
} catch (_e) {
|
|
176
|
+
return this._tryCatch(() => _onMessage(connection, message));
|
|
87
177
|
}
|
|
88
178
|
if (isStateUpdateMessage(parsed)) {
|
|
89
|
-
|
|
179
|
+
this._setStateInternal(parsed.state, connection);
|
|
90
180
|
return;
|
|
91
181
|
}
|
|
92
182
|
if (isRPCRequest(parsed)) {
|
|
@@ -96,7 +186,7 @@ var Agent = class extends Server {
|
|
|
96
186
|
if (typeof methodFn !== "function") {
|
|
97
187
|
throw new Error(`Method ${method} does not exist`);
|
|
98
188
|
}
|
|
99
|
-
if (!
|
|
189
|
+
if (!this._isCallable(method)) {
|
|
100
190
|
throw new Error(`Method ${method} is not callable`);
|
|
101
191
|
}
|
|
102
192
|
const metadata = callableMetadata.get(methodFn);
|
|
@@ -107,55 +197,93 @@ var Agent = class extends Server {
|
|
|
107
197
|
}
|
|
108
198
|
const result = await methodFn.apply(this, args);
|
|
109
199
|
const response = {
|
|
110
|
-
|
|
200
|
+
done: true,
|
|
111
201
|
id,
|
|
112
|
-
success: true,
|
|
113
202
|
result,
|
|
114
|
-
|
|
203
|
+
success: true,
|
|
204
|
+
type: "rpc"
|
|
115
205
|
};
|
|
116
206
|
connection.send(JSON.stringify(response));
|
|
117
207
|
} catch (e) {
|
|
118
208
|
const response = {
|
|
119
|
-
|
|
209
|
+
error: e instanceof Error ? e.message : "Unknown error occurred",
|
|
120
210
|
id: parsed.id,
|
|
121
211
|
success: false,
|
|
122
|
-
|
|
212
|
+
type: "rpc"
|
|
123
213
|
};
|
|
124
214
|
connection.send(JSON.stringify(response));
|
|
125
215
|
console.error("RPC error:", e);
|
|
126
216
|
}
|
|
127
217
|
return;
|
|
128
218
|
}
|
|
129
|
-
return
|
|
219
|
+
return this._tryCatch(() => _onMessage(connection, message));
|
|
130
220
|
}
|
|
131
221
|
);
|
|
132
222
|
};
|
|
133
223
|
const _onConnect = this.onConnect.bind(this);
|
|
134
224
|
this.onConnect = (connection, ctx2) => {
|
|
135
|
-
return
|
|
225
|
+
return agentContext.run(
|
|
136
226
|
{ agent: this, connection, request: ctx2.request },
|
|
137
227
|
async () => {
|
|
138
228
|
setTimeout(() => {
|
|
139
229
|
if (this.state) {
|
|
140
230
|
connection.send(
|
|
141
231
|
JSON.stringify({
|
|
142
|
-
|
|
143
|
-
|
|
232
|
+
state: this.state,
|
|
233
|
+
type: "cf_agent_state"
|
|
144
234
|
})
|
|
145
235
|
);
|
|
146
236
|
}
|
|
147
|
-
|
|
237
|
+
connection.send(
|
|
238
|
+
JSON.stringify({
|
|
239
|
+
mcp: this.getMcpServers(),
|
|
240
|
+
type: "cf_agent_mcp_servers"
|
|
241
|
+
})
|
|
242
|
+
);
|
|
243
|
+
return this._tryCatch(() => _onConnect(connection, ctx2));
|
|
148
244
|
}, 20);
|
|
149
245
|
}
|
|
150
246
|
);
|
|
151
247
|
};
|
|
248
|
+
const _onStart = this.onStart.bind(this);
|
|
249
|
+
this.onStart = async () => {
|
|
250
|
+
return agentContext.run(
|
|
251
|
+
{ agent: this, connection: void 0, request: void 0 },
|
|
252
|
+
async () => {
|
|
253
|
+
const servers = this.sql`
|
|
254
|
+
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
255
|
+
`;
|
|
256
|
+
await Promise.allSettled(
|
|
257
|
+
servers.filter((server) => server.auth_url === null).map((server) => {
|
|
258
|
+
return this._connectToMcpServerInternal(
|
|
259
|
+
server.name,
|
|
260
|
+
server.server_url,
|
|
261
|
+
server.callback_url,
|
|
262
|
+
server.server_options ? JSON.parse(server.server_options) : void 0,
|
|
263
|
+
{
|
|
264
|
+
id: server.id,
|
|
265
|
+
oauthClientId: server.client_id ?? void 0
|
|
266
|
+
}
|
|
267
|
+
);
|
|
268
|
+
})
|
|
269
|
+
);
|
|
270
|
+
this.broadcast(
|
|
271
|
+
JSON.stringify({
|
|
272
|
+
mcp: this.getMcpServers(),
|
|
273
|
+
type: "cf_agent_mcp_servers"
|
|
274
|
+
})
|
|
275
|
+
);
|
|
276
|
+
await this._tryCatch(() => _onStart());
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
};
|
|
152
280
|
}
|
|
153
281
|
/**
|
|
154
282
|
* Current state of the Agent
|
|
155
283
|
*/
|
|
156
284
|
get state() {
|
|
157
|
-
if (
|
|
158
|
-
return
|
|
285
|
+
if (this._state !== DEFAULT_STATE) {
|
|
286
|
+
return this._state;
|
|
159
287
|
}
|
|
160
288
|
const wasChanged = this.sql`
|
|
161
289
|
SELECT state FROM cf_agents_state WHERE id = ${STATE_WAS_CHANGED}
|
|
@@ -166,8 +294,8 @@ var Agent = class extends Server {
|
|
|
166
294
|
if (wasChanged[0]?.state === "true" || // we do this check for people who updated their code before we shipped wasChanged
|
|
167
295
|
result[0]?.state) {
|
|
168
296
|
const state = result[0]?.state;
|
|
169
|
-
|
|
170
|
-
return
|
|
297
|
+
this._state = JSON.parse(state);
|
|
298
|
+
return this._state;
|
|
171
299
|
}
|
|
172
300
|
if (this.initialState === DEFAULT_STATE) {
|
|
173
301
|
return void 0;
|
|
@@ -195,32 +323,68 @@ var Agent = class extends Server {
|
|
|
195
323
|
throw this.onError(e);
|
|
196
324
|
}
|
|
197
325
|
}
|
|
326
|
+
_setStateInternal(state, source = "server") {
|
|
327
|
+
this._state = state;
|
|
328
|
+
this.sql`
|
|
329
|
+
INSERT OR REPLACE INTO cf_agents_state (id, state)
|
|
330
|
+
VALUES (${STATE_ROW_ID}, ${JSON.stringify(state)})
|
|
331
|
+
`;
|
|
332
|
+
this.sql`
|
|
333
|
+
INSERT OR REPLACE INTO cf_agents_state (id, state)
|
|
334
|
+
VALUES (${STATE_WAS_CHANGED}, ${JSON.stringify(true)})
|
|
335
|
+
`;
|
|
336
|
+
this.broadcast(
|
|
337
|
+
JSON.stringify({
|
|
338
|
+
state,
|
|
339
|
+
type: "cf_agent_state"
|
|
340
|
+
}),
|
|
341
|
+
source !== "server" ? [source.id] : []
|
|
342
|
+
);
|
|
343
|
+
return this._tryCatch(() => {
|
|
344
|
+
const { connection, request } = agentContext.getStore() || {};
|
|
345
|
+
return agentContext.run(
|
|
346
|
+
{ agent: this, connection, request },
|
|
347
|
+
async () => {
|
|
348
|
+
return this.onStateUpdate(state, source);
|
|
349
|
+
}
|
|
350
|
+
);
|
|
351
|
+
});
|
|
352
|
+
}
|
|
198
353
|
/**
|
|
199
354
|
* Update the Agent's state
|
|
200
355
|
* @param state New state to set
|
|
201
356
|
*/
|
|
202
357
|
setState(state) {
|
|
203
|
-
|
|
358
|
+
this._setStateInternal(state, "server");
|
|
204
359
|
}
|
|
205
360
|
/**
|
|
206
361
|
* Called when the Agent's state is updated
|
|
207
362
|
* @param state Updated state
|
|
208
363
|
* @param source Source of the state update ("server" or a client connection)
|
|
209
364
|
*/
|
|
365
|
+
// biome-ignore lint/correctness/noUnusedFunctionParameters: overridden later
|
|
210
366
|
onStateUpdate(state, source) {
|
|
211
367
|
}
|
|
212
368
|
/**
|
|
213
369
|
* Called when the Agent receives an email
|
|
214
370
|
* @param email Email message to process
|
|
215
371
|
*/
|
|
372
|
+
// biome-ignore lint/correctness/noUnusedFunctionParameters: overridden later
|
|
216
373
|
onEmail(email) {
|
|
217
|
-
return
|
|
374
|
+
return agentContext.run(
|
|
218
375
|
{ agent: this, connection: void 0, request: void 0 },
|
|
219
376
|
async () => {
|
|
220
377
|
console.error("onEmail not implemented");
|
|
221
378
|
}
|
|
222
379
|
);
|
|
223
380
|
}
|
|
381
|
+
async _tryCatch(fn) {
|
|
382
|
+
try {
|
|
383
|
+
return await fn();
|
|
384
|
+
} catch (e) {
|
|
385
|
+
throw this.onError(e);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
224
388
|
onError(connectionOrError, error) {
|
|
225
389
|
let theError;
|
|
226
390
|
if (connectionOrError && error) {
|
|
@@ -270,10 +434,10 @@ var Agent = class extends Server {
|
|
|
270
434
|
payload
|
|
271
435
|
)}, 'scheduled', ${timestamp})
|
|
272
436
|
`;
|
|
273
|
-
await
|
|
437
|
+
await this._scheduleNextAlarm();
|
|
274
438
|
return {
|
|
275
|
-
id,
|
|
276
439
|
callback,
|
|
440
|
+
id,
|
|
277
441
|
payload,
|
|
278
442
|
time: timestamp,
|
|
279
443
|
type: "scheduled"
|
|
@@ -288,12 +452,12 @@ var Agent = class extends Server {
|
|
|
288
452
|
payload
|
|
289
453
|
)}, 'delayed', ${when}, ${timestamp})
|
|
290
454
|
`;
|
|
291
|
-
await
|
|
455
|
+
await this._scheduleNextAlarm();
|
|
292
456
|
return {
|
|
293
|
-
id,
|
|
294
457
|
callback,
|
|
295
|
-
payload,
|
|
296
458
|
delayInSeconds: when,
|
|
459
|
+
id,
|
|
460
|
+
payload,
|
|
297
461
|
time: timestamp,
|
|
298
462
|
type: "delayed"
|
|
299
463
|
};
|
|
@@ -307,12 +471,12 @@ var Agent = class extends Server {
|
|
|
307
471
|
payload
|
|
308
472
|
)}, 'cron', ${when}, ${timestamp})
|
|
309
473
|
`;
|
|
310
|
-
await
|
|
474
|
+
await this._scheduleNextAlarm();
|
|
311
475
|
return {
|
|
312
|
-
id,
|
|
313
476
|
callback,
|
|
314
|
-
payload,
|
|
315
477
|
cron: when,
|
|
478
|
+
id,
|
|
479
|
+
payload,
|
|
316
480
|
time: timestamp,
|
|
317
481
|
type: "cron"
|
|
318
482
|
};
|
|
@@ -374,47 +538,21 @@ var Agent = class extends Server {
|
|
|
374
538
|
*/
|
|
375
539
|
async cancelSchedule(id) {
|
|
376
540
|
this.sql`DELETE FROM cf_agents_schedules WHERE id = ${id}`;
|
|
377
|
-
await
|
|
541
|
+
await this._scheduleNextAlarm();
|
|
378
542
|
return true;
|
|
379
543
|
}
|
|
380
|
-
|
|
381
|
-
* Method called when an alarm fires
|
|
382
|
-
* Executes any scheduled tasks that are due
|
|
383
|
-
*/
|
|
384
|
-
async alarm() {
|
|
385
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
544
|
+
async _scheduleNextAlarm() {
|
|
386
545
|
const result = this.sql`
|
|
387
|
-
SELECT
|
|
546
|
+
SELECT time FROM cf_agents_schedules
|
|
547
|
+
WHERE time > ${Math.floor(Date.now() / 1e3)}
|
|
548
|
+
ORDER BY time ASC
|
|
549
|
+
LIMIT 1
|
|
388
550
|
`;
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
continue;
|
|
394
|
-
}
|
|
395
|
-
await unstable_context.run(
|
|
396
|
-
{ agent: this, connection: void 0, request: void 0 },
|
|
397
|
-
async () => {
|
|
398
|
-
try {
|
|
399
|
-
await callback.bind(this)(JSON.parse(row.payload), row);
|
|
400
|
-
} catch (e) {
|
|
401
|
-
console.error(`error executing callback "${row.callback}"`, e);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
);
|
|
405
|
-
if (row.type === "cron") {
|
|
406
|
-
const nextExecutionTime = getNextCronTime(row.cron);
|
|
407
|
-
const nextTimestamp = Math.floor(nextExecutionTime.getTime() / 1e3);
|
|
408
|
-
this.sql`
|
|
409
|
-
UPDATE cf_agents_schedules SET time = ${nextTimestamp} WHERE id = ${row.id}
|
|
410
|
-
`;
|
|
411
|
-
} else {
|
|
412
|
-
this.sql`
|
|
413
|
-
DELETE FROM cf_agents_schedules WHERE id = ${row.id}
|
|
414
|
-
`;
|
|
415
|
-
}
|
|
551
|
+
if (!result) return;
|
|
552
|
+
if (result.length > 0 && "time" in result[0]) {
|
|
553
|
+
const nextTime = result[0].time * 1e3;
|
|
554
|
+
await this.ctx.storage.setAlarm(nextTime);
|
|
416
555
|
}
|
|
417
|
-
await __privateMethod(this, _Agent_instances, scheduleNextAlarm_fn).call(this);
|
|
418
556
|
}
|
|
419
557
|
/**
|
|
420
558
|
* Destroy the Agent, removing all state and scheduled tasks
|
|
@@ -422,66 +560,131 @@ var Agent = class extends Server {
|
|
|
422
560
|
async destroy() {
|
|
423
561
|
this.sql`DROP TABLE IF EXISTS cf_agents_state`;
|
|
424
562
|
this.sql`DROP TABLE IF EXISTS cf_agents_schedules`;
|
|
563
|
+
this.sql`DROP TABLE IF EXISTS cf_agents_mcp_servers`;
|
|
425
564
|
await this.ctx.storage.deleteAlarm();
|
|
426
565
|
await this.ctx.storage.deleteAll();
|
|
566
|
+
this.ctx.abort("destroyed");
|
|
427
567
|
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
})
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
568
|
+
/**
|
|
569
|
+
* Get all methods marked as callable on this Agent
|
|
570
|
+
* @returns A map of method names to their metadata
|
|
571
|
+
*/
|
|
572
|
+
_isCallable(method) {
|
|
573
|
+
return callableMetadata.has(this[method]);
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Connect to a new MCP Server
|
|
577
|
+
*
|
|
578
|
+
* @param url MCP Server SSE URL
|
|
579
|
+
* @param callbackHost Base host for the agent, used for the redirect URI.
|
|
580
|
+
* @param agentsPrefix agents routing prefix if not using `agents`
|
|
581
|
+
* @param options MCP client and transport (header) options
|
|
582
|
+
* @returns authUrl
|
|
583
|
+
*/
|
|
584
|
+
async addMcpServer(serverName, url, callbackHost, agentsPrefix = "agents", options) {
|
|
585
|
+
const callbackUrl = `${callbackHost}/${agentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;
|
|
586
|
+
const result = await this._connectToMcpServerInternal(
|
|
587
|
+
serverName,
|
|
588
|
+
url,
|
|
589
|
+
callbackUrl,
|
|
590
|
+
options
|
|
591
|
+
);
|
|
592
|
+
this.broadcast(
|
|
593
|
+
JSON.stringify({
|
|
594
|
+
mcp: this.getMcpServers(),
|
|
595
|
+
type: "cf_agent_mcp_servers"
|
|
596
|
+
})
|
|
597
|
+
);
|
|
598
|
+
return result;
|
|
599
|
+
}
|
|
600
|
+
async _connectToMcpServerInternal(serverName, url, callbackUrl, options, reconnect) {
|
|
601
|
+
const authProvider = new DurableObjectOAuthClientProvider(
|
|
602
|
+
this.ctx.storage,
|
|
603
|
+
this.name,
|
|
604
|
+
callbackUrl
|
|
605
|
+
);
|
|
606
|
+
if (reconnect) {
|
|
607
|
+
authProvider.serverId = reconnect.id;
|
|
608
|
+
if (reconnect.oauthClientId) {
|
|
609
|
+
authProvider.clientId = reconnect.oauthClientId;
|
|
454
610
|
}
|
|
611
|
+
}
|
|
612
|
+
let headerTransportOpts = {};
|
|
613
|
+
if (options?.transport?.headers) {
|
|
614
|
+
headerTransportOpts = {
|
|
615
|
+
eventSourceInit: {
|
|
616
|
+
fetch: (url2, init) => fetch(url2, {
|
|
617
|
+
...init,
|
|
618
|
+
headers: options?.transport?.headers
|
|
619
|
+
})
|
|
620
|
+
},
|
|
621
|
+
requestInit: {
|
|
622
|
+
headers: options?.transport?.headers
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
const { id, authUrl, clientId } = await this.mcp.connect(url, {
|
|
627
|
+
client: options?.client,
|
|
628
|
+
reconnect,
|
|
629
|
+
transport: {
|
|
630
|
+
...headerTransportOpts,
|
|
631
|
+
authProvider
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
this.sql`
|
|
635
|
+
INSERT OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)
|
|
636
|
+
VALUES (
|
|
637
|
+
${id},
|
|
638
|
+
${serverName},
|
|
639
|
+
${url},
|
|
640
|
+
${clientId ?? null},
|
|
641
|
+
${authUrl ?? null},
|
|
642
|
+
${callbackUrl},
|
|
643
|
+
${options ? JSON.stringify(options) : null}
|
|
644
|
+
);
|
|
645
|
+
`;
|
|
646
|
+
return {
|
|
647
|
+
authUrl,
|
|
648
|
+
id
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
async removeMcpServer(id) {
|
|
652
|
+
this.mcp.closeConnection(id);
|
|
653
|
+
this.sql`
|
|
654
|
+
DELETE FROM cf_agents_mcp_servers WHERE id = ${id};
|
|
655
|
+
`;
|
|
656
|
+
this.broadcast(
|
|
657
|
+
JSON.stringify({
|
|
658
|
+
mcp: this.getMcpServers(),
|
|
659
|
+
type: "cf_agent_mcp_servers"
|
|
660
|
+
})
|
|
455
661
|
);
|
|
456
|
-
});
|
|
457
|
-
};
|
|
458
|
-
tryCatch_fn = async function(fn) {
|
|
459
|
-
try {
|
|
460
|
-
return await fn();
|
|
461
|
-
} catch (e) {
|
|
462
|
-
throw this.onError(e);
|
|
463
662
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
663
|
+
getMcpServers() {
|
|
664
|
+
const mcpState = {
|
|
665
|
+
prompts: this.mcp.listPrompts(),
|
|
666
|
+
resources: this.mcp.listResources(),
|
|
667
|
+
servers: {},
|
|
668
|
+
tools: this.mcp.listTools()
|
|
669
|
+
};
|
|
670
|
+
const servers = this.sql`
|
|
671
|
+
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
471
672
|
`;
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
673
|
+
for (const server of servers) {
|
|
674
|
+
const serverConn = this.mcp.mcpConnections[server.id];
|
|
675
|
+
mcpState.servers[server.id] = {
|
|
676
|
+
auth_url: server.auth_url,
|
|
677
|
+
capabilities: serverConn?.serverCapabilities ?? null,
|
|
678
|
+
instructions: serverConn?.instructions ?? null,
|
|
679
|
+
name: server.name,
|
|
680
|
+
server_url: server.server_url,
|
|
681
|
+
// mark as "authenticating" because the server isn't automatically connected, so it's pending authenticating
|
|
682
|
+
state: serverConn?.connectionState ?? "authenticating"
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
return mcpState;
|
|
476
686
|
}
|
|
477
687
|
};
|
|
478
|
-
/**
|
|
479
|
-
* Get all methods marked as callable on this Agent
|
|
480
|
-
* @returns A map of method names to their metadata
|
|
481
|
-
*/
|
|
482
|
-
isCallable_fn = function(method) {
|
|
483
|
-
return callableMetadata.has(this[method]);
|
|
484
|
-
};
|
|
485
688
|
/**
|
|
486
689
|
* Agent configuration options
|
|
487
690
|
*/
|
|
@@ -492,9 +695,9 @@ Agent.options = {
|
|
|
492
695
|
};
|
|
493
696
|
async function routeAgentRequest(request, env, options) {
|
|
494
697
|
const corsHeaders = options?.cors === true ? {
|
|
495
|
-
"Access-Control-Allow-Origin": "*",
|
|
496
|
-
"Access-Control-Allow-Methods": "GET, POST, HEAD, OPTIONS",
|
|
497
698
|
"Access-Control-Allow-Credentials": "true",
|
|
699
|
+
"Access-Control-Allow-Methods": "GET, POST, HEAD, OPTIONS",
|
|
700
|
+
"Access-Control-Allow-Origin": "*",
|
|
498
701
|
"Access-Control-Max-Age": "86400"
|
|
499
702
|
} : options?.cors;
|
|
500
703
|
if (request.method === "OPTIONS") {
|
|
@@ -525,67 +728,61 @@ async function routeAgentRequest(request, env, options) {
|
|
|
525
728
|
}
|
|
526
729
|
return response;
|
|
527
730
|
}
|
|
528
|
-
async function routeAgentEmail(
|
|
731
|
+
async function routeAgentEmail(_email, _env, _options) {
|
|
529
732
|
}
|
|
530
|
-
function getAgentByName(namespace, name, options) {
|
|
733
|
+
async function getAgentByName(namespace, name, options) {
|
|
531
734
|
return getServerByName(namespace, name, options);
|
|
532
735
|
}
|
|
533
|
-
var _connection, _id, _closed;
|
|
534
736
|
var StreamingResponse = class {
|
|
535
737
|
constructor(connection, id) {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
__privateSet(this, _connection, connection);
|
|
540
|
-
__privateSet(this, _id, id);
|
|
738
|
+
this._closed = false;
|
|
739
|
+
this._connection = connection;
|
|
740
|
+
this._id = id;
|
|
541
741
|
}
|
|
542
742
|
/**
|
|
543
743
|
* Send a chunk of data to the client
|
|
544
744
|
* @param chunk The data to send
|
|
545
745
|
*/
|
|
546
746
|
send(chunk) {
|
|
547
|
-
if (
|
|
747
|
+
if (this._closed) {
|
|
548
748
|
throw new Error("StreamingResponse is already closed");
|
|
549
749
|
}
|
|
550
750
|
const response = {
|
|
551
|
-
|
|
552
|
-
id:
|
|
553
|
-
success: true,
|
|
751
|
+
done: false,
|
|
752
|
+
id: this._id,
|
|
554
753
|
result: chunk,
|
|
555
|
-
|
|
754
|
+
success: true,
|
|
755
|
+
type: "rpc"
|
|
556
756
|
};
|
|
557
|
-
|
|
757
|
+
this._connection.send(JSON.stringify(response));
|
|
558
758
|
}
|
|
559
759
|
/**
|
|
560
760
|
* End the stream and send the final chunk (if any)
|
|
561
761
|
* @param finalChunk Optional final chunk of data to send
|
|
562
762
|
*/
|
|
563
763
|
end(finalChunk) {
|
|
564
|
-
if (
|
|
764
|
+
if (this._closed) {
|
|
565
765
|
throw new Error("StreamingResponse is already closed");
|
|
566
766
|
}
|
|
567
|
-
|
|
767
|
+
this._closed = true;
|
|
568
768
|
const response = {
|
|
569
|
-
|
|
570
|
-
id:
|
|
571
|
-
success: true,
|
|
769
|
+
done: true,
|
|
770
|
+
id: this._id,
|
|
572
771
|
result: finalChunk,
|
|
573
|
-
|
|
772
|
+
success: true,
|
|
773
|
+
type: "rpc"
|
|
574
774
|
};
|
|
575
|
-
|
|
775
|
+
this._connection.send(JSON.stringify(response));
|
|
576
776
|
}
|
|
577
777
|
};
|
|
578
|
-
_connection = new WeakMap();
|
|
579
|
-
_id = new WeakMap();
|
|
580
|
-
_closed = new WeakMap();
|
|
581
778
|
|
|
582
779
|
export {
|
|
583
780
|
unstable_callable,
|
|
584
|
-
|
|
781
|
+
getCurrentAgent,
|
|
585
782
|
Agent,
|
|
586
783
|
routeAgentRequest,
|
|
587
784
|
routeAgentEmail,
|
|
588
785
|
getAgentByName,
|
|
589
786
|
StreamingResponse
|
|
590
787
|
};
|
|
591
|
-
//# sourceMappingURL=chunk-
|
|
788
|
+
//# sourceMappingURL=chunk-ZRRXJUAA.js.map
|