agents 0.0.0-77368ff → 0.0.0-789141e
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 +130 -7
- package/dist/_esm-LV5FJ3HK.js +3922 -0
- package/dist/_esm-LV5FJ3HK.js.map +1 -0
- package/dist/ai-chat-agent.d.ts +12 -8
- package/dist/ai-chat-agent.js +466 -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 +67 -70
- 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-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-PVQZBKN7.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-KUH345EY.js → chunk-QEVM4BVL.js} +5 -5
- package/dist/chunk-QEVM4BVL.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/{chunk-Z2OUUKK4.js → chunk-XGMKNUJA.js} +188 -115
- package/dist/chunk-XGMKNUJA.js.map +1 -0
- package/dist/chunk-ZMMHNOMZ.js +942 -0
- package/dist/chunk-ZMMHNOMZ.js.map +1 -0
- package/dist/client-DVoPb3-C.d.ts +5120 -0
- 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 +548 -31
- package/dist/index.js +8 -4
- package/dist/mcp/client.d.ts +10 -1052
- 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 +59 -87
- package/dist/mcp/index.js +948 -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 -13
- package/dist/observability/index.js +6 -4
- package/dist/react.d.ts +14 -7
- 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 +38 -10
- package/src/index.ts +273 -136
- package/dist/chunk-KUH345EY.js.map +0 -1
- package/dist/chunk-PVQZBKN7.js.map +0 -1
- package/dist/chunk-UNG3FXYX.js +0 -525
- package/dist/chunk-UNG3FXYX.js.map +0 -1
- package/dist/chunk-Z2OUUKK4.js.map +0 -1
- package/dist/index-BIJvkfYt.d.ts +0 -614
package/src/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { env } from "cloudflare:workers";
|
|
1
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
3
|
import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
4
|
import type { SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
@@ -21,10 +22,13 @@ import {
|
|
|
21
22
|
routePartykitRequest
|
|
22
23
|
} from "partyserver";
|
|
23
24
|
import { camelCaseToKebabCase } from "./client";
|
|
24
|
-
import { MCPClientManager } from "./mcp/client";
|
|
25
|
-
|
|
25
|
+
import { MCPClientManager, type MCPClientOAuthResult } from "./mcp/client";
|
|
26
|
+
import type { MCPConnectionState } from "./mcp/client-connection";
|
|
26
27
|
import { DurableObjectOAuthClientProvider } from "./mcp/do-oauth-client-provider";
|
|
28
|
+
import type { TransportType } from "./mcp/types";
|
|
27
29
|
import { genericObservability, type Observability } from "./observability";
|
|
30
|
+
import { DisposableStore } from "./core/events";
|
|
31
|
+
import { MessageType } from "./ai-types";
|
|
28
32
|
|
|
29
33
|
export type { Connection, ConnectionContext, WSMessage } from "partyserver";
|
|
30
34
|
|
|
@@ -42,7 +46,7 @@ export type RPCRequest = {
|
|
|
42
46
|
* State update message from client
|
|
43
47
|
*/
|
|
44
48
|
export type StateUpdateMessage = {
|
|
45
|
-
type:
|
|
49
|
+
type: MessageType.CF_AGENT_STATE;
|
|
46
50
|
state: unknown;
|
|
47
51
|
};
|
|
48
52
|
|
|
@@ -50,7 +54,7 @@ export type StateUpdateMessage = {
|
|
|
50
54
|
* RPC response message to client
|
|
51
55
|
*/
|
|
52
56
|
export type RPCResponse = {
|
|
53
|
-
type:
|
|
57
|
+
type: MessageType.RPC;
|
|
54
58
|
id: string;
|
|
55
59
|
} & (
|
|
56
60
|
| {
|
|
@@ -77,7 +81,7 @@ function isRPCRequest(msg: unknown): msg is RPCRequest {
|
|
|
77
81
|
typeof msg === "object" &&
|
|
78
82
|
msg !== null &&
|
|
79
83
|
"type" in msg &&
|
|
80
|
-
msg.type ===
|
|
84
|
+
msg.type === MessageType.RPC &&
|
|
81
85
|
"id" in msg &&
|
|
82
86
|
typeof msg.id === "string" &&
|
|
83
87
|
"method" in msg &&
|
|
@@ -95,7 +99,7 @@ function isStateUpdateMessage(msg: unknown): msg is StateUpdateMessage {
|
|
|
95
99
|
typeof msg === "object" &&
|
|
96
100
|
msg !== null &&
|
|
97
101
|
"type" in msg &&
|
|
98
|
-
msg.type ===
|
|
102
|
+
msg.type === MessageType.CF_AGENT_STATE &&
|
|
99
103
|
"state" in msg
|
|
100
104
|
);
|
|
101
105
|
}
|
|
@@ -116,7 +120,7 @@ const callableMetadata = new Map<Function, CallableMetadata>();
|
|
|
116
120
|
* Decorator that marks a method as callable by clients
|
|
117
121
|
* @param metadata Optional metadata about the callable method
|
|
118
122
|
*/
|
|
119
|
-
export function
|
|
123
|
+
export function callable(metadata: CallableMetadata = {}) {
|
|
120
124
|
return function callableDecorator<This, Args extends unknown[], Return>(
|
|
121
125
|
target: (this: This, ...args: Args) => Return,
|
|
122
126
|
// biome-ignore lint/correctness/noUnusedFunctionParameters: later
|
|
@@ -130,6 +134,23 @@ export function unstable_callable(metadata: CallableMetadata = {}) {
|
|
|
130
134
|
};
|
|
131
135
|
}
|
|
132
136
|
|
|
137
|
+
let didWarnAboutUnstableCallable = false;
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Decorator that marks a method as callable by clients
|
|
141
|
+
* @deprecated this has been renamed to callable, and unstable_callable will be removed in the next major version
|
|
142
|
+
* @param metadata Optional metadata about the callable method
|
|
143
|
+
*/
|
|
144
|
+
export const unstable_callable = (metadata: CallableMetadata = {}) => {
|
|
145
|
+
if (!didWarnAboutUnstableCallable) {
|
|
146
|
+
didWarnAboutUnstableCallable = true;
|
|
147
|
+
console.warn(
|
|
148
|
+
"unstable_callable is deprecated, use callable instead. unstable_callable will be removed in the next major version."
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
callable(metadata);
|
|
152
|
+
};
|
|
153
|
+
|
|
133
154
|
export type QueueItem<T = string> = {
|
|
134
155
|
id: string;
|
|
135
156
|
payload: T;
|
|
@@ -178,11 +199,13 @@ function getNextCronTime(cron: string) {
|
|
|
178
199
|
return interval.getNextDate();
|
|
179
200
|
}
|
|
180
201
|
|
|
202
|
+
export type { TransportType } from "./mcp/types";
|
|
203
|
+
|
|
181
204
|
/**
|
|
182
205
|
* MCP Server state update message from server -> Client
|
|
183
206
|
*/
|
|
184
207
|
export type MCPServerMessage = {
|
|
185
|
-
type:
|
|
208
|
+
type: MessageType.CF_AGENT_MCP_SERVERS;
|
|
186
209
|
mcp: MCPServersState;
|
|
187
210
|
};
|
|
188
211
|
|
|
@@ -202,7 +225,7 @@ export type MCPServer = {
|
|
|
202
225
|
// This state is specifically about the temporary process of getting a token (if needed).
|
|
203
226
|
// Scope outside of that can't be relied upon because when the DO sleeps, there's no way
|
|
204
227
|
// to communicate a change to a non-ready state.
|
|
205
|
-
state:
|
|
228
|
+
state: MCPConnectionState;
|
|
206
229
|
instructions: string | null;
|
|
207
230
|
capabilities: ServerCapabilities | null;
|
|
208
231
|
};
|
|
@@ -271,7 +294,13 @@ function withAgentContext<T extends (...args: any[]) => any>(
|
|
|
271
294
|
method: T
|
|
272
295
|
): (this: Agent<unknown, unknown>, ...args: Parameters<T>) => ReturnType<T> {
|
|
273
296
|
return function (...args: Parameters<T>): ReturnType<T> {
|
|
274
|
-
const { connection, request, email } = getCurrentAgent();
|
|
297
|
+
const { connection, request, email, agent } = getCurrentAgent();
|
|
298
|
+
|
|
299
|
+
if (agent === this) {
|
|
300
|
+
// already wrapped, so we can just call the method
|
|
301
|
+
return method.apply(this, args);
|
|
302
|
+
}
|
|
303
|
+
// not wrapped, so we need to wrap it
|
|
275
304
|
return agentContext.run({ agent: this, connection, request, email }, () => {
|
|
276
305
|
return method.apply(this, args);
|
|
277
306
|
});
|
|
@@ -283,13 +312,21 @@ function withAgentContext<T extends (...args: any[]) => any>(
|
|
|
283
312
|
* @template Env Environment type containing bindings
|
|
284
313
|
* @template State State type to store within the Agent
|
|
285
314
|
*/
|
|
286
|
-
export class Agent<
|
|
315
|
+
export class Agent<
|
|
316
|
+
Env = typeof env,
|
|
317
|
+
State = unknown,
|
|
318
|
+
Props extends Record<string, unknown> = Record<string, unknown>
|
|
319
|
+
> extends Server<Env, Props> {
|
|
287
320
|
private _state = DEFAULT_STATE as State;
|
|
321
|
+
private _disposables = new DisposableStore();
|
|
288
322
|
|
|
289
323
|
private _ParentClass: typeof Agent<Env, State> =
|
|
290
324
|
Object.getPrototypeOf(this).constructor;
|
|
291
325
|
|
|
292
|
-
mcp: MCPClientManager = new MCPClientManager(
|
|
326
|
+
readonly mcp: MCPClientManager = new MCPClientManager(
|
|
327
|
+
this._ParentClass.name,
|
|
328
|
+
"0.0.1"
|
|
329
|
+
);
|
|
293
330
|
|
|
294
331
|
/**
|
|
295
332
|
* Initial state for the Agent
|
|
@@ -382,8 +419,25 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
382
419
|
constructor(ctx: AgentContext, env: Env) {
|
|
383
420
|
super(ctx, env);
|
|
384
421
|
|
|
385
|
-
|
|
386
|
-
|
|
422
|
+
if (!wrappedClasses.has(this.constructor)) {
|
|
423
|
+
// Auto-wrap custom methods with agent context
|
|
424
|
+
this._autoWrapCustomMethods();
|
|
425
|
+
wrappedClasses.add(this.constructor);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// Broadcast server state after background connects (for OAuth servers)
|
|
429
|
+
this._disposables.add(
|
|
430
|
+
this.mcp.onConnected(async () => {
|
|
431
|
+
this.broadcastMcpServers();
|
|
432
|
+
})
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
// Emit MCP observability events
|
|
436
|
+
this._disposables.add(
|
|
437
|
+
this.mcp.onObservabilityEvent((event) => {
|
|
438
|
+
this.observability?.emit(event);
|
|
439
|
+
})
|
|
440
|
+
);
|
|
387
441
|
|
|
388
442
|
this.sql`
|
|
389
443
|
CREATE TABLE IF NOT EXISTS cf_agents_state (
|
|
@@ -440,21 +494,24 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
440
494
|
{ agent: this, connection: undefined, request, email: undefined },
|
|
441
495
|
async () => {
|
|
442
496
|
if (this.mcp.isCallbackRequest(request)) {
|
|
443
|
-
await this.mcp.handleCallbackRequest(request);
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
497
|
+
const result = await this.mcp.handleCallbackRequest(request);
|
|
498
|
+
this.broadcastMcpServers();
|
|
499
|
+
|
|
500
|
+
if (result.authSuccess) {
|
|
501
|
+
// Start background connection if auth was successful
|
|
502
|
+
this.mcp
|
|
503
|
+
.establishConnection(result.serverId)
|
|
504
|
+
.catch((error) => {
|
|
505
|
+
console.error("Background connection failed:", error);
|
|
506
|
+
})
|
|
507
|
+
.finally(() => {
|
|
508
|
+
// Broadcast after background connection resolves (success/failure)
|
|
509
|
+
this.broadcastMcpServers();
|
|
510
|
+
});
|
|
511
|
+
}
|
|
452
512
|
|
|
453
|
-
//
|
|
454
|
-
return
|
|
455
|
-
headers: { "content-type": "text/html" },
|
|
456
|
-
status: 200
|
|
457
|
-
});
|
|
513
|
+
// Handle OAuth callback response using MCPClientManager configuration
|
|
514
|
+
return this.handleOAuthCallbackResponse(result, request);
|
|
458
515
|
}
|
|
459
516
|
|
|
460
517
|
return this._tryCatch(() => _onRequest(request));
|
|
@@ -515,10 +572,8 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
515
572
|
displayMessage: `RPC call to ${method}`,
|
|
516
573
|
id: nanoid(),
|
|
517
574
|
payload: {
|
|
518
|
-
args,
|
|
519
575
|
method,
|
|
520
|
-
streaming: metadata?.streaming
|
|
521
|
-
success: true
|
|
576
|
+
streaming: metadata?.streaming
|
|
522
577
|
},
|
|
523
578
|
timestamp: Date.now(),
|
|
524
579
|
type: "rpc"
|
|
@@ -531,7 +586,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
531
586
|
id,
|
|
532
587
|
result,
|
|
533
588
|
success: true,
|
|
534
|
-
type:
|
|
589
|
+
type: MessageType.RPC
|
|
535
590
|
};
|
|
536
591
|
connection.send(JSON.stringify(response));
|
|
537
592
|
} catch (e) {
|
|
@@ -541,7 +596,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
541
596
|
e instanceof Error ? e.message : "Unknown error occurred",
|
|
542
597
|
id: parsed.id,
|
|
543
598
|
success: false,
|
|
544
|
-
type:
|
|
599
|
+
type: MessageType.RPC
|
|
545
600
|
};
|
|
546
601
|
connection.send(JSON.stringify(response));
|
|
547
602
|
console.error("RPC error:", e);
|
|
@@ -560,44 +615,42 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
560
615
|
// must fix this
|
|
561
616
|
return agentContext.run(
|
|
562
617
|
{ agent: this, connection, request: ctx.request, email: undefined },
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
if (this.state) {
|
|
566
|
-
connection.send(
|
|
567
|
-
JSON.stringify({
|
|
568
|
-
state: this.state,
|
|
569
|
-
type: "cf_agent_state"
|
|
570
|
-
})
|
|
571
|
-
);
|
|
572
|
-
}
|
|
573
|
-
|
|
618
|
+
() => {
|
|
619
|
+
if (this.state) {
|
|
574
620
|
connection.send(
|
|
575
621
|
JSON.stringify({
|
|
576
|
-
|
|
577
|
-
type:
|
|
622
|
+
state: this.state,
|
|
623
|
+
type: MessageType.CF_AGENT_STATE
|
|
578
624
|
})
|
|
579
625
|
);
|
|
626
|
+
}
|
|
580
627
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
628
|
+
connection.send(
|
|
629
|
+
JSON.stringify({
|
|
630
|
+
mcp: this.getMcpServers(),
|
|
631
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
632
|
+
})
|
|
633
|
+
);
|
|
634
|
+
|
|
635
|
+
this.observability?.emit(
|
|
636
|
+
{
|
|
637
|
+
displayMessage: "Connection established",
|
|
638
|
+
id: nanoid(),
|
|
639
|
+
payload: {
|
|
640
|
+
connectionId: connection.id
|
|
590
641
|
},
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
642
|
+
timestamp: Date.now(),
|
|
643
|
+
type: "connect"
|
|
644
|
+
},
|
|
645
|
+
this.ctx
|
|
646
|
+
);
|
|
647
|
+
return this._tryCatch(() => _onConnect(connection, ctx));
|
|
595
648
|
}
|
|
596
649
|
);
|
|
597
650
|
};
|
|
598
651
|
|
|
599
652
|
const _onStart = this.onStart.bind(this);
|
|
600
|
-
this.onStart = async () => {
|
|
653
|
+
this.onStart = async (props?: Props) => {
|
|
601
654
|
return agentContext.run(
|
|
602
655
|
{
|
|
603
656
|
agent: this,
|
|
@@ -606,15 +659,27 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
606
659
|
email: undefined
|
|
607
660
|
},
|
|
608
661
|
async () => {
|
|
609
|
-
|
|
662
|
+
await this._tryCatch(() => {
|
|
663
|
+
const servers = this.sql<MCPServerRow>`
|
|
610
664
|
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
611
665
|
`;
|
|
612
666
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
667
|
+
this.broadcastMcpServers();
|
|
668
|
+
|
|
669
|
+
// from DO storage, reconnect to all servers not currently in the oauth flow using our saved auth information
|
|
670
|
+
if (servers && Array.isArray(servers) && servers.length > 0) {
|
|
671
|
+
// Restore callback URLs for OAuth-enabled servers
|
|
672
|
+
servers.forEach((server) => {
|
|
673
|
+
if (server.callback_url) {
|
|
674
|
+
// Register the full redirect URL including serverId to avoid ambiguous matches
|
|
675
|
+
this.mcp.registerCallbackUrl(
|
|
676
|
+
`${server.callback_url}/${server.id}`
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
servers.forEach((server) => {
|
|
682
|
+
this._connectToMcpServerInternal(
|
|
618
683
|
server.name,
|
|
619
684
|
server.server_url,
|
|
620
685
|
server.callback_url,
|
|
@@ -625,18 +690,23 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
625
690
|
id: server.id,
|
|
626
691
|
oauthClientId: server.client_id ?? undefined
|
|
627
692
|
}
|
|
628
|
-
)
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
693
|
+
)
|
|
694
|
+
.then(() => {
|
|
695
|
+
// Broadcast updated MCP servers state after each server connects
|
|
696
|
+
this.broadcastMcpServers();
|
|
697
|
+
})
|
|
698
|
+
.catch((error) => {
|
|
699
|
+
console.error(
|
|
700
|
+
`Error connecting to MCP server: ${server.name} (${server.server_url})`,
|
|
701
|
+
error
|
|
702
|
+
);
|
|
703
|
+
// Still broadcast even if connection fails, so clients know about the failure
|
|
704
|
+
this.broadcastMcpServers();
|
|
705
|
+
});
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
return _onStart(props);
|
|
709
|
+
});
|
|
640
710
|
}
|
|
641
711
|
);
|
|
642
712
|
};
|
|
@@ -646,7 +716,6 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
646
716
|
state: State,
|
|
647
717
|
source: Connection | "server" = "server"
|
|
648
718
|
) {
|
|
649
|
-
const previousState = this._state;
|
|
650
719
|
this._state = state;
|
|
651
720
|
this.sql`
|
|
652
721
|
INSERT OR REPLACE INTO cf_agents_state (id, state)
|
|
@@ -659,7 +728,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
659
728
|
this.broadcast(
|
|
660
729
|
JSON.stringify({
|
|
661
730
|
state: state,
|
|
662
|
-
type:
|
|
731
|
+
type: MessageType.CF_AGENT_STATE
|
|
663
732
|
}),
|
|
664
733
|
source !== "server" ? [source.id] : []
|
|
665
734
|
);
|
|
@@ -672,10 +741,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
672
741
|
{
|
|
673
742
|
displayMessage: "State updated",
|
|
674
743
|
id: nanoid(),
|
|
675
|
-
payload: {
|
|
676
|
-
previousState,
|
|
677
|
-
state
|
|
678
|
-
},
|
|
744
|
+
payload: {},
|
|
679
745
|
timestamp: Date.now(),
|
|
680
746
|
type: "state:update"
|
|
681
747
|
},
|
|
@@ -815,41 +881,37 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
815
881
|
while (proto && proto !== Object.prototype && depth < 10) {
|
|
816
882
|
const methodNames = Object.getOwnPropertyNames(proto);
|
|
817
883
|
for (const methodName of methodNames) {
|
|
818
|
-
|
|
884
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
|
|
885
|
+
|
|
886
|
+
// Skip if it's a private method, a base method, a getter, or not a function,
|
|
819
887
|
if (
|
|
820
888
|
baseMethods.has(methodName) ||
|
|
821
889
|
methodName.startsWith("_") ||
|
|
822
|
-
|
|
890
|
+
!descriptor ||
|
|
891
|
+
!!descriptor.get ||
|
|
892
|
+
typeof descriptor.value !== "function"
|
|
823
893
|
) {
|
|
824
894
|
continue;
|
|
825
895
|
}
|
|
826
|
-
// If the method doesn't exist in base prototypes, it's a custom method
|
|
827
|
-
if (!baseMethods.has(methodName)) {
|
|
828
|
-
const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
|
|
829
|
-
if (descriptor && typeof descriptor.value === "function") {
|
|
830
|
-
// Wrap the custom method with context
|
|
831
|
-
|
|
832
|
-
const wrappedFunction = withAgentContext(
|
|
833
|
-
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
834
|
-
this[methodName as keyof this] as (...args: any[]) => any
|
|
835
|
-
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
836
|
-
) as any;
|
|
837
|
-
|
|
838
|
-
// if the method is callable, copy the metadata from the original method
|
|
839
|
-
if (this._isCallable(methodName)) {
|
|
840
|
-
callableMetadata.set(
|
|
841
|
-
wrappedFunction,
|
|
842
|
-
callableMetadata.get(
|
|
843
|
-
this[methodName as keyof this] as Function
|
|
844
|
-
)!
|
|
845
|
-
);
|
|
846
|
-
}
|
|
847
896
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
897
|
+
// Now, methodName is confirmed to be a custom method/function
|
|
898
|
+
// Wrap the custom method with context
|
|
899
|
+
const wrappedFunction = withAgentContext(
|
|
900
|
+
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
901
|
+
this[methodName as keyof this] as (...args: any[]) => any
|
|
902
|
+
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
903
|
+
) as any;
|
|
904
|
+
|
|
905
|
+
// if the method is callable, copy the metadata from the original method
|
|
906
|
+
if (this._isCallable(methodName)) {
|
|
907
|
+
callableMetadata.set(
|
|
908
|
+
wrappedFunction,
|
|
909
|
+
callableMetadata.get(this[methodName as keyof this] as Function)!
|
|
910
|
+
);
|
|
852
911
|
}
|
|
912
|
+
|
|
913
|
+
// set the wrapped function on the prototype
|
|
914
|
+
this.constructor.prototype[methodName as keyof this] = wrappedFunction;
|
|
853
915
|
}
|
|
854
916
|
|
|
855
917
|
proto = Object.getPrototypeOf(proto);
|
|
@@ -1036,7 +1098,10 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1036
1098
|
{
|
|
1037
1099
|
displayMessage: `Schedule ${schedule.id} created`,
|
|
1038
1100
|
id: nanoid(),
|
|
1039
|
-
payload:
|
|
1101
|
+
payload: {
|
|
1102
|
+
callback: callback as string,
|
|
1103
|
+
id: id
|
|
1104
|
+
},
|
|
1040
1105
|
timestamp: Date.now(),
|
|
1041
1106
|
type: "schedule:create"
|
|
1042
1107
|
},
|
|
@@ -1206,7 +1271,10 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1206
1271
|
{
|
|
1207
1272
|
displayMessage: `Schedule ${id} cancelled`,
|
|
1208
1273
|
id: nanoid(),
|
|
1209
|
-
payload:
|
|
1274
|
+
payload: {
|
|
1275
|
+
callback: schedule.callback,
|
|
1276
|
+
id: schedule.id
|
|
1277
|
+
},
|
|
1210
1278
|
timestamp: Date.now(),
|
|
1211
1279
|
type: "schedule:cancel"
|
|
1212
1280
|
},
|
|
@@ -1271,7 +1339,10 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1271
1339
|
{
|
|
1272
1340
|
displayMessage: `Schedule ${row.id} executed`,
|
|
1273
1341
|
id: nanoid(),
|
|
1274
|
-
payload:
|
|
1342
|
+
payload: {
|
|
1343
|
+
callback: row.callback,
|
|
1344
|
+
id: row.id
|
|
1345
|
+
},
|
|
1275
1346
|
timestamp: Date.now(),
|
|
1276
1347
|
type: "schedule:execute"
|
|
1277
1348
|
},
|
|
@@ -1323,6 +1394,8 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1323
1394
|
// delete all alarms
|
|
1324
1395
|
await this.ctx.storage.deleteAlarm();
|
|
1325
1396
|
await this.ctx.storage.deleteAll();
|
|
1397
|
+
this._disposables.dispose();
|
|
1398
|
+
await this.mcp.dispose?.();
|
|
1326
1399
|
this.ctx.abort("destroyed"); // enforce that the agent is evicted
|
|
1327
1400
|
|
|
1328
1401
|
this.observability?.emit(
|
|
@@ -1348,25 +1421,42 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1348
1421
|
/**
|
|
1349
1422
|
* Connect to a new MCP Server
|
|
1350
1423
|
*
|
|
1424
|
+
* @param serverName Name of the MCP server
|
|
1351
1425
|
* @param url MCP Server SSE URL
|
|
1352
|
-
* @param callbackHost Base host for the agent, used for the redirect URI.
|
|
1426
|
+
* @param callbackHost Base host for the agent, used for the redirect URI. If not provided, will be derived from the current request.
|
|
1353
1427
|
* @param agentsPrefix agents routing prefix if not using `agents`
|
|
1354
|
-
* @param options MCP client and transport
|
|
1428
|
+
* @param options MCP client and transport options
|
|
1355
1429
|
* @returns authUrl
|
|
1356
1430
|
*/
|
|
1357
1431
|
async addMcpServer(
|
|
1358
1432
|
serverName: string,
|
|
1359
1433
|
url: string,
|
|
1360
|
-
callbackHost
|
|
1434
|
+
callbackHost?: string,
|
|
1361
1435
|
agentsPrefix = "agents",
|
|
1362
1436
|
options?: {
|
|
1363
1437
|
client?: ConstructorParameters<typeof Client>[1];
|
|
1364
1438
|
transport?: {
|
|
1365
|
-
headers
|
|
1439
|
+
headers?: HeadersInit;
|
|
1440
|
+
type?: TransportType;
|
|
1366
1441
|
};
|
|
1367
1442
|
}
|
|
1368
1443
|
): Promise<{ id: string; authUrl: string | undefined }> {
|
|
1369
|
-
|
|
1444
|
+
// If callbackHost is not provided, derive it from the current request
|
|
1445
|
+
let resolvedCallbackHost = callbackHost;
|
|
1446
|
+
if (!resolvedCallbackHost) {
|
|
1447
|
+
const { request } = getCurrentAgent();
|
|
1448
|
+
if (!request) {
|
|
1449
|
+
throw new Error(
|
|
1450
|
+
"callbackHost is required when not called within a request context"
|
|
1451
|
+
);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
// Extract the origin from the request
|
|
1455
|
+
const requestUrl = new URL(request.url);
|
|
1456
|
+
resolvedCallbackHost = `${requestUrl.protocol}//${requestUrl.host}`;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
const callbackUrl = `${resolvedCallbackHost}/${agentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;
|
|
1370
1460
|
|
|
1371
1461
|
const result = await this._connectToMcpServerInternal(
|
|
1372
1462
|
serverName,
|
|
@@ -1374,6 +1464,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1374
1464
|
callbackUrl,
|
|
1375
1465
|
options
|
|
1376
1466
|
);
|
|
1467
|
+
|
|
1377
1468
|
this.sql`
|
|
1378
1469
|
INSERT
|
|
1379
1470
|
OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)
|
|
@@ -1388,17 +1479,12 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1388
1479
|
);
|
|
1389
1480
|
`;
|
|
1390
1481
|
|
|
1391
|
-
this.
|
|
1392
|
-
JSON.stringify({
|
|
1393
|
-
mcp: this.getMcpServers(),
|
|
1394
|
-
type: "cf_agent_mcp_servers"
|
|
1395
|
-
})
|
|
1396
|
-
);
|
|
1482
|
+
this.broadcastMcpServers();
|
|
1397
1483
|
|
|
1398
1484
|
return result;
|
|
1399
1485
|
}
|
|
1400
1486
|
|
|
1401
|
-
async _connectToMcpServerInternal(
|
|
1487
|
+
private async _connectToMcpServerInternal(
|
|
1402
1488
|
_serverName: string,
|
|
1403
1489
|
url: string,
|
|
1404
1490
|
callbackUrl: string,
|
|
@@ -1414,6 +1500,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1414
1500
|
*/
|
|
1415
1501
|
transport?: {
|
|
1416
1502
|
headers?: HeadersInit;
|
|
1503
|
+
type?: TransportType;
|
|
1417
1504
|
};
|
|
1418
1505
|
},
|
|
1419
1506
|
reconnect?: {
|
|
@@ -1438,6 +1525,9 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1438
1525
|
}
|
|
1439
1526
|
}
|
|
1440
1527
|
|
|
1528
|
+
// Use the transport type specified in options, or default to "auto"
|
|
1529
|
+
const transportType: TransportType = options?.transport?.type ?? "auto";
|
|
1530
|
+
|
|
1441
1531
|
// allows passing through transport headers if necessary
|
|
1442
1532
|
// this handles some non-standard bearer auth setups (i.e. MCP server behind CF access instead of OAuth)
|
|
1443
1533
|
let headerTransportOpts: SSEClientTransportOptions = {};
|
|
@@ -1461,7 +1551,8 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1461
1551
|
reconnect,
|
|
1462
1552
|
transport: {
|
|
1463
1553
|
...headerTransportOpts,
|
|
1464
|
-
authProvider
|
|
1554
|
+
authProvider,
|
|
1555
|
+
type: transportType
|
|
1465
1556
|
}
|
|
1466
1557
|
});
|
|
1467
1558
|
|
|
@@ -1474,15 +1565,11 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1474
1565
|
|
|
1475
1566
|
async removeMcpServer(id: string) {
|
|
1476
1567
|
this.mcp.closeConnection(id);
|
|
1568
|
+
this.mcp.unregisterCallbackUrl(id);
|
|
1477
1569
|
this.sql`
|
|
1478
1570
|
DELETE FROM cf_agents_mcp_servers WHERE id = ${id};
|
|
1479
1571
|
`;
|
|
1480
|
-
this.
|
|
1481
|
-
JSON.stringify({
|
|
1482
|
-
mcp: this.getMcpServers(),
|
|
1483
|
-
type: "cf_agent_mcp_servers"
|
|
1484
|
-
})
|
|
1485
|
-
);
|
|
1572
|
+
this.broadcastMcpServers();
|
|
1486
1573
|
}
|
|
1487
1574
|
|
|
1488
1575
|
getMcpServers(): MCPServersState {
|
|
@@ -1514,8 +1601,53 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1514
1601
|
|
|
1515
1602
|
return mcpState;
|
|
1516
1603
|
}
|
|
1604
|
+
|
|
1605
|
+
private broadcastMcpServers() {
|
|
1606
|
+
this.broadcast(
|
|
1607
|
+
JSON.stringify({
|
|
1608
|
+
mcp: this.getMcpServers(),
|
|
1609
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
1610
|
+
})
|
|
1611
|
+
);
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
/**
|
|
1615
|
+
* Handle OAuth callback response using MCPClientManager configuration
|
|
1616
|
+
* @param result OAuth callback result
|
|
1617
|
+
* @param request The original request (needed for base URL)
|
|
1618
|
+
* @returns Response for the OAuth callback
|
|
1619
|
+
*/
|
|
1620
|
+
private handleOAuthCallbackResponse(
|
|
1621
|
+
result: MCPClientOAuthResult,
|
|
1622
|
+
request: Request
|
|
1623
|
+
): Response {
|
|
1624
|
+
const config = this.mcp.getOAuthCallbackConfig();
|
|
1625
|
+
|
|
1626
|
+
// Use custom handler if configured
|
|
1627
|
+
if (config?.customHandler) {
|
|
1628
|
+
return config.customHandler(result);
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
// Use redirect URLs if configured
|
|
1632
|
+
if (config?.successRedirect && result.authSuccess) {
|
|
1633
|
+
return Response.redirect(config.successRedirect);
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
if (config?.errorRedirect && !result.authSuccess) {
|
|
1637
|
+
return Response.redirect(
|
|
1638
|
+
`${config.errorRedirect}?error=${encodeURIComponent(result.authError || "Unknown error")}`
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
|
|
1642
|
+
// Default behavior - redirect to base URL
|
|
1643
|
+
const baseUrl = new URL(request.url).origin;
|
|
1644
|
+
return Response.redirect(baseUrl);
|
|
1645
|
+
}
|
|
1517
1646
|
}
|
|
1518
1647
|
|
|
1648
|
+
// A set of classes that have been wrapped with agent context
|
|
1649
|
+
const wrappedClasses = new Set<typeof Agent.prototype.constructor>();
|
|
1650
|
+
|
|
1519
1651
|
/**
|
|
1520
1652
|
* Namespace for creating Agent instances
|
|
1521
1653
|
* @template Agentic Type of the Agent class
|
|
@@ -1831,12 +1963,17 @@ export type EmailSendOptions = {
|
|
|
1831
1963
|
* @param options Options for Agent creation
|
|
1832
1964
|
* @returns Promise resolving to an Agent instance stub
|
|
1833
1965
|
*/
|
|
1834
|
-
export async function getAgentByName<
|
|
1966
|
+
export async function getAgentByName<
|
|
1967
|
+
Env,
|
|
1968
|
+
T extends Agent<Env>,
|
|
1969
|
+
Props extends Record<string, unknown> = Record<string, unknown>
|
|
1970
|
+
>(
|
|
1835
1971
|
namespace: AgentNamespace<T>,
|
|
1836
1972
|
name: string,
|
|
1837
1973
|
options?: {
|
|
1838
1974
|
jurisdiction?: DurableObjectJurisdiction;
|
|
1839
1975
|
locationHint?: DurableObjectLocationHint;
|
|
1976
|
+
props?: Props;
|
|
1840
1977
|
}
|
|
1841
1978
|
) {
|
|
1842
1979
|
return getServerByName<Env, T>(namespace, name, options);
|
|
@@ -1868,7 +2005,7 @@ export class StreamingResponse {
|
|
|
1868
2005
|
id: this._id,
|
|
1869
2006
|
result: chunk,
|
|
1870
2007
|
success: true,
|
|
1871
|
-
type:
|
|
2008
|
+
type: MessageType.RPC
|
|
1872
2009
|
};
|
|
1873
2010
|
this._connection.send(JSON.stringify(response));
|
|
1874
2011
|
}
|
|
@@ -1887,7 +2024,7 @@ export class StreamingResponse {
|
|
|
1887
2024
|
id: this._id,
|
|
1888
2025
|
result: finalChunk,
|
|
1889
2026
|
success: true,
|
|
1890
|
-
type:
|
|
2027
|
+
type: MessageType.RPC
|
|
1891
2028
|
};
|
|
1892
2029
|
this._connection.send(JSON.stringify(response));
|
|
1893
2030
|
}
|