agents 0.0.0-1cb6383 → 0.0.0-1dc8321
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 +129 -7
- package/dist/_esm-LV5FJ3HK.js +3922 -0
- package/dist/_esm-LV5FJ3HK.js.map +1 -0
- package/dist/ai-chat-agent.d.ts +11 -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 +66 -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-JXN5WZFQ.js → chunk-XGMKNUJA.js} +173 -117
- package/dist/chunk-XGMKNUJA.js.map +1 -0
- package/dist/{chunk-HY7ZLHJB.js → chunk-ZMMHNOMZ.js} +415 -71
- package/dist/chunk-ZMMHNOMZ.js.map +1 -0
- package/dist/{client-DgyzBU_8.d.ts → client-DVoPb3-C.d.ts} +555 -36
- 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 -32
- package/dist/index.js +8 -4
- package/dist/mcp/client.d.ts +2 -1
- 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 +50 -83
- package/dist/mcp/index.js +904 -760
- 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 -14
- package/dist/observability/index.js +6 -4
- package/dist/react.d.ts +13 -7
- package/dist/react.js +107 -7
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +79 -5
- 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 +34 -9
- package/src/index.ts +251 -137
- package/dist/chunk-HY7ZLHJB.js.map +0 -1
- package/dist/chunk-JXN5WZFQ.js.map +0 -1
- package/dist/chunk-KUH345EY.js.map +0 -1
- package/dist/chunk-PVQZBKN7.js.map +0 -1
- package/dist/index-BCJclX6q.d.ts +0 -615
package/src/index.ts
CHANGED
|
@@ -22,10 +22,13 @@ import {
|
|
|
22
22
|
routePartykitRequest
|
|
23
23
|
} from "partyserver";
|
|
24
24
|
import { camelCaseToKebabCase } from "./client";
|
|
25
|
-
import { MCPClientManager } from "./mcp/client";
|
|
26
|
-
|
|
25
|
+
import { MCPClientManager, type MCPClientOAuthResult } from "./mcp/client";
|
|
26
|
+
import type { MCPConnectionState } from "./mcp/client-connection";
|
|
27
27
|
import { DurableObjectOAuthClientProvider } from "./mcp/do-oauth-client-provider";
|
|
28
|
+
import type { TransportType } from "./mcp/types";
|
|
28
29
|
import { genericObservability, type Observability } from "./observability";
|
|
30
|
+
import { DisposableStore } from "./core/events";
|
|
31
|
+
import { MessageType } from "./ai-types";
|
|
29
32
|
|
|
30
33
|
export type { Connection, ConnectionContext, WSMessage } from "partyserver";
|
|
31
34
|
|
|
@@ -43,7 +46,7 @@ export type RPCRequest = {
|
|
|
43
46
|
* State update message from client
|
|
44
47
|
*/
|
|
45
48
|
export type StateUpdateMessage = {
|
|
46
|
-
type:
|
|
49
|
+
type: MessageType.CF_AGENT_STATE;
|
|
47
50
|
state: unknown;
|
|
48
51
|
};
|
|
49
52
|
|
|
@@ -51,7 +54,7 @@ export type StateUpdateMessage = {
|
|
|
51
54
|
* RPC response message to client
|
|
52
55
|
*/
|
|
53
56
|
export type RPCResponse = {
|
|
54
|
-
type:
|
|
57
|
+
type: MessageType.RPC;
|
|
55
58
|
id: string;
|
|
56
59
|
} & (
|
|
57
60
|
| {
|
|
@@ -78,7 +81,7 @@ function isRPCRequest(msg: unknown): msg is RPCRequest {
|
|
|
78
81
|
typeof msg === "object" &&
|
|
79
82
|
msg !== null &&
|
|
80
83
|
"type" in msg &&
|
|
81
|
-
msg.type ===
|
|
84
|
+
msg.type === MessageType.RPC &&
|
|
82
85
|
"id" in msg &&
|
|
83
86
|
typeof msg.id === "string" &&
|
|
84
87
|
"method" in msg &&
|
|
@@ -96,7 +99,7 @@ function isStateUpdateMessage(msg: unknown): msg is StateUpdateMessage {
|
|
|
96
99
|
typeof msg === "object" &&
|
|
97
100
|
msg !== null &&
|
|
98
101
|
"type" in msg &&
|
|
99
|
-
msg.type ===
|
|
102
|
+
msg.type === MessageType.CF_AGENT_STATE &&
|
|
100
103
|
"state" in msg
|
|
101
104
|
);
|
|
102
105
|
}
|
|
@@ -117,7 +120,7 @@ const callableMetadata = new Map<Function, CallableMetadata>();
|
|
|
117
120
|
* Decorator that marks a method as callable by clients
|
|
118
121
|
* @param metadata Optional metadata about the callable method
|
|
119
122
|
*/
|
|
120
|
-
export function
|
|
123
|
+
export function callable(metadata: CallableMetadata = {}) {
|
|
121
124
|
return function callableDecorator<This, Args extends unknown[], Return>(
|
|
122
125
|
target: (this: This, ...args: Args) => Return,
|
|
123
126
|
// biome-ignore lint/correctness/noUnusedFunctionParameters: later
|
|
@@ -131,6 +134,23 @@ export function unstable_callable(metadata: CallableMetadata = {}) {
|
|
|
131
134
|
};
|
|
132
135
|
}
|
|
133
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
|
+
|
|
134
154
|
export type QueueItem<T = string> = {
|
|
135
155
|
id: string;
|
|
136
156
|
payload: T;
|
|
@@ -179,11 +199,13 @@ function getNextCronTime(cron: string) {
|
|
|
179
199
|
return interval.getNextDate();
|
|
180
200
|
}
|
|
181
201
|
|
|
202
|
+
export type { TransportType } from "./mcp/types";
|
|
203
|
+
|
|
182
204
|
/**
|
|
183
205
|
* MCP Server state update message from server -> Client
|
|
184
206
|
*/
|
|
185
207
|
export type MCPServerMessage = {
|
|
186
|
-
type:
|
|
208
|
+
type: MessageType.CF_AGENT_MCP_SERVERS;
|
|
187
209
|
mcp: MCPServersState;
|
|
188
210
|
};
|
|
189
211
|
|
|
@@ -203,7 +225,7 @@ export type MCPServer = {
|
|
|
203
225
|
// This state is specifically about the temporary process of getting a token (if needed).
|
|
204
226
|
// Scope outside of that can't be relied upon because when the DO sleeps, there's no way
|
|
205
227
|
// to communicate a change to a non-ready state.
|
|
206
|
-
state:
|
|
228
|
+
state: MCPConnectionState;
|
|
207
229
|
instructions: string | null;
|
|
208
230
|
capabilities: ServerCapabilities | null;
|
|
209
231
|
};
|
|
@@ -272,7 +294,13 @@ function withAgentContext<T extends (...args: any[]) => any>(
|
|
|
272
294
|
method: T
|
|
273
295
|
): (this: Agent<unknown, unknown>, ...args: Parameters<T>) => ReturnType<T> {
|
|
274
296
|
return function (...args: Parameters<T>): ReturnType<T> {
|
|
275
|
-
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
|
|
276
304
|
return agentContext.run({ agent: this, connection, request, email }, () => {
|
|
277
305
|
return method.apply(this, args);
|
|
278
306
|
});
|
|
@@ -284,13 +312,21 @@ function withAgentContext<T extends (...args: any[]) => any>(
|
|
|
284
312
|
* @template Env Environment type containing bindings
|
|
285
313
|
* @template State State type to store within the Agent
|
|
286
314
|
*/
|
|
287
|
-
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> {
|
|
288
320
|
private _state = DEFAULT_STATE as State;
|
|
321
|
+
private _disposables = new DisposableStore();
|
|
289
322
|
|
|
290
323
|
private _ParentClass: typeof Agent<Env, State> =
|
|
291
324
|
Object.getPrototypeOf(this).constructor;
|
|
292
325
|
|
|
293
|
-
mcp: MCPClientManager = new MCPClientManager(
|
|
326
|
+
readonly mcp: MCPClientManager = new MCPClientManager(
|
|
327
|
+
this._ParentClass.name,
|
|
328
|
+
"0.0.1"
|
|
329
|
+
);
|
|
294
330
|
|
|
295
331
|
/**
|
|
296
332
|
* Initial state for the Agent
|
|
@@ -383,8 +419,25 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
383
419
|
constructor(ctx: AgentContext, env: Env) {
|
|
384
420
|
super(ctx, env);
|
|
385
421
|
|
|
386
|
-
|
|
387
|
-
|
|
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
|
+
);
|
|
388
441
|
|
|
389
442
|
this.sql`
|
|
390
443
|
CREATE TABLE IF NOT EXISTS cf_agents_state (
|
|
@@ -441,21 +494,24 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
441
494
|
{ agent: this, connection: undefined, request, email: undefined },
|
|
442
495
|
async () => {
|
|
443
496
|
if (this.mcp.isCallbackRequest(request)) {
|
|
444
|
-
await this.mcp.handleCallbackRequest(request);
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
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
|
+
}
|
|
453
512
|
|
|
454
|
-
//
|
|
455
|
-
return
|
|
456
|
-
headers: { "content-type": "text/html" },
|
|
457
|
-
status: 200
|
|
458
|
-
});
|
|
513
|
+
// Handle OAuth callback response using MCPClientManager configuration
|
|
514
|
+
return this.handleOAuthCallbackResponse(result, request);
|
|
459
515
|
}
|
|
460
516
|
|
|
461
517
|
return this._tryCatch(() => _onRequest(request));
|
|
@@ -516,10 +572,8 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
516
572
|
displayMessage: `RPC call to ${method}`,
|
|
517
573
|
id: nanoid(),
|
|
518
574
|
payload: {
|
|
519
|
-
args,
|
|
520
575
|
method,
|
|
521
|
-
streaming: metadata?.streaming
|
|
522
|
-
success: true
|
|
576
|
+
streaming: metadata?.streaming
|
|
523
577
|
},
|
|
524
578
|
timestamp: Date.now(),
|
|
525
579
|
type: "rpc"
|
|
@@ -532,7 +586,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
532
586
|
id,
|
|
533
587
|
result,
|
|
534
588
|
success: true,
|
|
535
|
-
type:
|
|
589
|
+
type: MessageType.RPC
|
|
536
590
|
};
|
|
537
591
|
connection.send(JSON.stringify(response));
|
|
538
592
|
} catch (e) {
|
|
@@ -542,7 +596,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
542
596
|
e instanceof Error ? e.message : "Unknown error occurred",
|
|
543
597
|
id: parsed.id,
|
|
544
598
|
success: false,
|
|
545
|
-
type:
|
|
599
|
+
type: MessageType.RPC
|
|
546
600
|
};
|
|
547
601
|
connection.send(JSON.stringify(response));
|
|
548
602
|
console.error("RPC error:", e);
|
|
@@ -561,44 +615,42 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
561
615
|
// must fix this
|
|
562
616
|
return agentContext.run(
|
|
563
617
|
{ agent: this, connection, request: ctx.request, email: undefined },
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
if (this.state) {
|
|
567
|
-
connection.send(
|
|
568
|
-
JSON.stringify({
|
|
569
|
-
state: this.state,
|
|
570
|
-
type: "cf_agent_state"
|
|
571
|
-
})
|
|
572
|
-
);
|
|
573
|
-
}
|
|
574
|
-
|
|
618
|
+
() => {
|
|
619
|
+
if (this.state) {
|
|
575
620
|
connection.send(
|
|
576
621
|
JSON.stringify({
|
|
577
|
-
|
|
578
|
-
type:
|
|
622
|
+
state: this.state,
|
|
623
|
+
type: MessageType.CF_AGENT_STATE
|
|
579
624
|
})
|
|
580
625
|
);
|
|
626
|
+
}
|
|
581
627
|
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
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
|
|
591
641
|
},
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
642
|
+
timestamp: Date.now(),
|
|
643
|
+
type: "connect"
|
|
644
|
+
},
|
|
645
|
+
this.ctx
|
|
646
|
+
);
|
|
647
|
+
return this._tryCatch(() => _onConnect(connection, ctx));
|
|
596
648
|
}
|
|
597
649
|
);
|
|
598
650
|
};
|
|
599
651
|
|
|
600
652
|
const _onStart = this.onStart.bind(this);
|
|
601
|
-
this.onStart = async () => {
|
|
653
|
+
this.onStart = async (props?: Props) => {
|
|
602
654
|
return agentContext.run(
|
|
603
655
|
{
|
|
604
656
|
agent: this,
|
|
@@ -612,15 +664,20 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
612
664
|
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
613
665
|
`;
|
|
614
666
|
|
|
615
|
-
this.
|
|
616
|
-
JSON.stringify({
|
|
617
|
-
mcp: this.getMcpServers(),
|
|
618
|
-
type: "cf_agent_mcp_servers"
|
|
619
|
-
})
|
|
620
|
-
);
|
|
667
|
+
this.broadcastMcpServers();
|
|
621
668
|
|
|
622
669
|
// from DO storage, reconnect to all servers not currently in the oauth flow using our saved auth information
|
|
623
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
|
+
|
|
624
681
|
servers.forEach((server) => {
|
|
625
682
|
this._connectToMcpServerInternal(
|
|
626
683
|
server.name,
|
|
@@ -636,12 +693,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
636
693
|
)
|
|
637
694
|
.then(() => {
|
|
638
695
|
// Broadcast updated MCP servers state after each server connects
|
|
639
|
-
this.
|
|
640
|
-
JSON.stringify({
|
|
641
|
-
mcp: this.getMcpServers(),
|
|
642
|
-
type: "cf_agent_mcp_servers"
|
|
643
|
-
})
|
|
644
|
-
);
|
|
696
|
+
this.broadcastMcpServers();
|
|
645
697
|
})
|
|
646
698
|
.catch((error) => {
|
|
647
699
|
console.error(
|
|
@@ -649,16 +701,11 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
649
701
|
error
|
|
650
702
|
);
|
|
651
703
|
// Still broadcast even if connection fails, so clients know about the failure
|
|
652
|
-
this.
|
|
653
|
-
JSON.stringify({
|
|
654
|
-
mcp: this.getMcpServers(),
|
|
655
|
-
type: "cf_agent_mcp_servers"
|
|
656
|
-
})
|
|
657
|
-
);
|
|
704
|
+
this.broadcastMcpServers();
|
|
658
705
|
});
|
|
659
706
|
});
|
|
660
707
|
}
|
|
661
|
-
return _onStart();
|
|
708
|
+
return _onStart(props);
|
|
662
709
|
});
|
|
663
710
|
}
|
|
664
711
|
);
|
|
@@ -669,7 +716,6 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
669
716
|
state: State,
|
|
670
717
|
source: Connection | "server" = "server"
|
|
671
718
|
) {
|
|
672
|
-
const previousState = this._state;
|
|
673
719
|
this._state = state;
|
|
674
720
|
this.sql`
|
|
675
721
|
INSERT OR REPLACE INTO cf_agents_state (id, state)
|
|
@@ -682,7 +728,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
682
728
|
this.broadcast(
|
|
683
729
|
JSON.stringify({
|
|
684
730
|
state: state,
|
|
685
|
-
type:
|
|
731
|
+
type: MessageType.CF_AGENT_STATE
|
|
686
732
|
}),
|
|
687
733
|
source !== "server" ? [source.id] : []
|
|
688
734
|
);
|
|
@@ -695,10 +741,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
695
741
|
{
|
|
696
742
|
displayMessage: "State updated",
|
|
697
743
|
id: nanoid(),
|
|
698
|
-
payload: {
|
|
699
|
-
previousState,
|
|
700
|
-
state
|
|
701
|
-
},
|
|
744
|
+
payload: {},
|
|
702
745
|
timestamp: Date.now(),
|
|
703
746
|
type: "state:update"
|
|
704
747
|
},
|
|
@@ -838,41 +881,37 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
838
881
|
while (proto && proto !== Object.prototype && depth < 10) {
|
|
839
882
|
const methodNames = Object.getOwnPropertyNames(proto);
|
|
840
883
|
for (const methodName of methodNames) {
|
|
841
|
-
|
|
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,
|
|
842
887
|
if (
|
|
843
888
|
baseMethods.has(methodName) ||
|
|
844
889
|
methodName.startsWith("_") ||
|
|
845
|
-
|
|
890
|
+
!descriptor ||
|
|
891
|
+
!!descriptor.get ||
|
|
892
|
+
typeof descriptor.value !== "function"
|
|
846
893
|
) {
|
|
847
894
|
continue;
|
|
848
895
|
}
|
|
849
|
-
// If the method doesn't exist in base prototypes, it's a custom method
|
|
850
|
-
if (!baseMethods.has(methodName)) {
|
|
851
|
-
const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
|
|
852
|
-
if (descriptor && typeof descriptor.value === "function") {
|
|
853
|
-
// Wrap the custom method with context
|
|
854
|
-
|
|
855
|
-
const wrappedFunction = withAgentContext(
|
|
856
|
-
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
857
|
-
this[methodName as keyof this] as (...args: any[]) => any
|
|
858
|
-
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
859
|
-
) as any;
|
|
860
|
-
|
|
861
|
-
// if the method is callable, copy the metadata from the original method
|
|
862
|
-
if (this._isCallable(methodName)) {
|
|
863
|
-
callableMetadata.set(
|
|
864
|
-
wrappedFunction,
|
|
865
|
-
callableMetadata.get(
|
|
866
|
-
this[methodName as keyof this] as Function
|
|
867
|
-
)!
|
|
868
|
-
);
|
|
869
|
-
}
|
|
870
896
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
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
|
+
);
|
|
875
911
|
}
|
|
912
|
+
|
|
913
|
+
// set the wrapped function on the prototype
|
|
914
|
+
this.constructor.prototype[methodName as keyof this] = wrappedFunction;
|
|
876
915
|
}
|
|
877
916
|
|
|
878
917
|
proto = Object.getPrototypeOf(proto);
|
|
@@ -1059,7 +1098,10 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1059
1098
|
{
|
|
1060
1099
|
displayMessage: `Schedule ${schedule.id} created`,
|
|
1061
1100
|
id: nanoid(),
|
|
1062
|
-
payload:
|
|
1101
|
+
payload: {
|
|
1102
|
+
callback: callback as string,
|
|
1103
|
+
id: id
|
|
1104
|
+
},
|
|
1063
1105
|
timestamp: Date.now(),
|
|
1064
1106
|
type: "schedule:create"
|
|
1065
1107
|
},
|
|
@@ -1229,7 +1271,10 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1229
1271
|
{
|
|
1230
1272
|
displayMessage: `Schedule ${id} cancelled`,
|
|
1231
1273
|
id: nanoid(),
|
|
1232
|
-
payload:
|
|
1274
|
+
payload: {
|
|
1275
|
+
callback: schedule.callback,
|
|
1276
|
+
id: schedule.id
|
|
1277
|
+
},
|
|
1233
1278
|
timestamp: Date.now(),
|
|
1234
1279
|
type: "schedule:cancel"
|
|
1235
1280
|
},
|
|
@@ -1294,7 +1339,10 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1294
1339
|
{
|
|
1295
1340
|
displayMessage: `Schedule ${row.id} executed`,
|
|
1296
1341
|
id: nanoid(),
|
|
1297
|
-
payload:
|
|
1342
|
+
payload: {
|
|
1343
|
+
callback: row.callback,
|
|
1344
|
+
id: row.id
|
|
1345
|
+
},
|
|
1298
1346
|
timestamp: Date.now(),
|
|
1299
1347
|
type: "schedule:execute"
|
|
1300
1348
|
},
|
|
@@ -1346,6 +1394,8 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1346
1394
|
// delete all alarms
|
|
1347
1395
|
await this.ctx.storage.deleteAlarm();
|
|
1348
1396
|
await this.ctx.storage.deleteAll();
|
|
1397
|
+
this._disposables.dispose();
|
|
1398
|
+
await this.mcp.dispose?.();
|
|
1349
1399
|
this.ctx.abort("destroyed"); // enforce that the agent is evicted
|
|
1350
1400
|
|
|
1351
1401
|
this.observability?.emit(
|
|
@@ -1371,25 +1421,42 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1371
1421
|
/**
|
|
1372
1422
|
* Connect to a new MCP Server
|
|
1373
1423
|
*
|
|
1424
|
+
* @param serverName Name of the MCP server
|
|
1374
1425
|
* @param url MCP Server SSE URL
|
|
1375
|
-
* @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.
|
|
1376
1427
|
* @param agentsPrefix agents routing prefix if not using `agents`
|
|
1377
|
-
* @param options MCP client and transport
|
|
1428
|
+
* @param options MCP client and transport options
|
|
1378
1429
|
* @returns authUrl
|
|
1379
1430
|
*/
|
|
1380
1431
|
async addMcpServer(
|
|
1381
1432
|
serverName: string,
|
|
1382
1433
|
url: string,
|
|
1383
|
-
callbackHost
|
|
1434
|
+
callbackHost?: string,
|
|
1384
1435
|
agentsPrefix = "agents",
|
|
1385
1436
|
options?: {
|
|
1386
1437
|
client?: ConstructorParameters<typeof Client>[1];
|
|
1387
1438
|
transport?: {
|
|
1388
|
-
headers
|
|
1439
|
+
headers?: HeadersInit;
|
|
1440
|
+
type?: TransportType;
|
|
1389
1441
|
};
|
|
1390
1442
|
}
|
|
1391
1443
|
): Promise<{ id: string; authUrl: string | undefined }> {
|
|
1392
|
-
|
|
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`;
|
|
1393
1460
|
|
|
1394
1461
|
const result = await this._connectToMcpServerInternal(
|
|
1395
1462
|
serverName,
|
|
@@ -1397,6 +1464,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1397
1464
|
callbackUrl,
|
|
1398
1465
|
options
|
|
1399
1466
|
);
|
|
1467
|
+
|
|
1400
1468
|
this.sql`
|
|
1401
1469
|
INSERT
|
|
1402
1470
|
OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)
|
|
@@ -1411,17 +1479,12 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1411
1479
|
);
|
|
1412
1480
|
`;
|
|
1413
1481
|
|
|
1414
|
-
this.
|
|
1415
|
-
JSON.stringify({
|
|
1416
|
-
mcp: this.getMcpServers(),
|
|
1417
|
-
type: "cf_agent_mcp_servers"
|
|
1418
|
-
})
|
|
1419
|
-
);
|
|
1482
|
+
this.broadcastMcpServers();
|
|
1420
1483
|
|
|
1421
1484
|
return result;
|
|
1422
1485
|
}
|
|
1423
1486
|
|
|
1424
|
-
async _connectToMcpServerInternal(
|
|
1487
|
+
private async _connectToMcpServerInternal(
|
|
1425
1488
|
_serverName: string,
|
|
1426
1489
|
url: string,
|
|
1427
1490
|
callbackUrl: string,
|
|
@@ -1437,6 +1500,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1437
1500
|
*/
|
|
1438
1501
|
transport?: {
|
|
1439
1502
|
headers?: HeadersInit;
|
|
1503
|
+
type?: TransportType;
|
|
1440
1504
|
};
|
|
1441
1505
|
},
|
|
1442
1506
|
reconnect?: {
|
|
@@ -1461,6 +1525,9 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1461
1525
|
}
|
|
1462
1526
|
}
|
|
1463
1527
|
|
|
1528
|
+
// Use the transport type specified in options, or default to "auto"
|
|
1529
|
+
const transportType: TransportType = options?.transport?.type ?? "auto";
|
|
1530
|
+
|
|
1464
1531
|
// allows passing through transport headers if necessary
|
|
1465
1532
|
// this handles some non-standard bearer auth setups (i.e. MCP server behind CF access instead of OAuth)
|
|
1466
1533
|
let headerTransportOpts: SSEClientTransportOptions = {};
|
|
@@ -1484,7 +1551,8 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1484
1551
|
reconnect,
|
|
1485
1552
|
transport: {
|
|
1486
1553
|
...headerTransportOpts,
|
|
1487
|
-
authProvider
|
|
1554
|
+
authProvider,
|
|
1555
|
+
type: transportType
|
|
1488
1556
|
}
|
|
1489
1557
|
});
|
|
1490
1558
|
|
|
@@ -1497,15 +1565,11 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1497
1565
|
|
|
1498
1566
|
async removeMcpServer(id: string) {
|
|
1499
1567
|
this.mcp.closeConnection(id);
|
|
1568
|
+
this.mcp.unregisterCallbackUrl(id);
|
|
1500
1569
|
this.sql`
|
|
1501
1570
|
DELETE FROM cf_agents_mcp_servers WHERE id = ${id};
|
|
1502
1571
|
`;
|
|
1503
|
-
this.
|
|
1504
|
-
JSON.stringify({
|
|
1505
|
-
mcp: this.getMcpServers(),
|
|
1506
|
-
type: "cf_agent_mcp_servers"
|
|
1507
|
-
})
|
|
1508
|
-
);
|
|
1572
|
+
this.broadcastMcpServers();
|
|
1509
1573
|
}
|
|
1510
1574
|
|
|
1511
1575
|
getMcpServers(): MCPServersState {
|
|
@@ -1537,8 +1601,53 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1537
1601
|
|
|
1538
1602
|
return mcpState;
|
|
1539
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
|
+
}
|
|
1540
1646
|
}
|
|
1541
1647
|
|
|
1648
|
+
// A set of classes that have been wrapped with agent context
|
|
1649
|
+
const wrappedClasses = new Set<typeof Agent.prototype.constructor>();
|
|
1650
|
+
|
|
1542
1651
|
/**
|
|
1543
1652
|
* Namespace for creating Agent instances
|
|
1544
1653
|
* @template Agentic Type of the Agent class
|
|
@@ -1854,12 +1963,17 @@ export type EmailSendOptions = {
|
|
|
1854
1963
|
* @param options Options for Agent creation
|
|
1855
1964
|
* @returns Promise resolving to an Agent instance stub
|
|
1856
1965
|
*/
|
|
1857
|
-
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
|
+
>(
|
|
1858
1971
|
namespace: AgentNamespace<T>,
|
|
1859
1972
|
name: string,
|
|
1860
1973
|
options?: {
|
|
1861
1974
|
jurisdiction?: DurableObjectJurisdiction;
|
|
1862
1975
|
locationHint?: DurableObjectLocationHint;
|
|
1976
|
+
props?: Props;
|
|
1863
1977
|
}
|
|
1864
1978
|
) {
|
|
1865
1979
|
return getServerByName<Env, T>(namespace, name, options);
|
|
@@ -1891,7 +2005,7 @@ export class StreamingResponse {
|
|
|
1891
2005
|
id: this._id,
|
|
1892
2006
|
result: chunk,
|
|
1893
2007
|
success: true,
|
|
1894
|
-
type:
|
|
2008
|
+
type: MessageType.RPC
|
|
1895
2009
|
};
|
|
1896
2010
|
this._connection.send(JSON.stringify(response));
|
|
1897
2011
|
}
|
|
@@ -1910,7 +2024,7 @@ export class StreamingResponse {
|
|
|
1910
2024
|
id: this._id,
|
|
1911
2025
|
result: finalChunk,
|
|
1912
2026
|
success: true,
|
|
1913
|
-
type:
|
|
2027
|
+
type: MessageType.RPC
|
|
1914
2028
|
};
|
|
1915
2029
|
this._connection.send(JSON.stringify(response));
|
|
1916
2030
|
}
|