agents 0.0.0-2a6e66e → 0.0.0-2bea91f
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 +8 -6
- package/dist/ai-chat-agent.js +442 -48
- 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 +64 -69
- package/dist/ai-react.js +252 -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-CV3L6FQZ.js → chunk-254F4GDT.js} +159 -106
- package/dist/chunk-254F4GDT.js.map +1 -0
- package/dist/{chunk-HY7ZLHJB.js → chunk-3OT2NNEW.js} +412 -69
- package/dist/chunk-3OT2NNEW.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-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-PVQZBKN7.js → chunk-Z44WASMA.js} +11 -3
- package/dist/chunk-Z44WASMA.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 +5112 -0
- package/dist/codemode/ai.js.map +1 -0
- package/dist/index.d.ts +48 -38
- 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 +12 -24
- package/dist/observability/index.js +6 -4
- package/dist/react.d.ts +11 -6
- package/dist/react.js +107 -7
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +76 -2
- 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 +27 -7
- package/src/index.ts +237 -126
- package/dist/chunk-CV3L6FQZ.js.map +0 -1
- package/dist/chunk-HY7ZLHJB.js.map +0 -1
- package/dist/chunk-KUH345EY.js.map +0 -1
- package/dist/chunk-PVQZBKN7.js.map +0 -1
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));
|
|
@@ -530,7 +586,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
530
586
|
id,
|
|
531
587
|
result,
|
|
532
588
|
success: true,
|
|
533
|
-
type:
|
|
589
|
+
type: MessageType.RPC
|
|
534
590
|
};
|
|
535
591
|
connection.send(JSON.stringify(response));
|
|
536
592
|
} catch (e) {
|
|
@@ -540,7 +596,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
540
596
|
e instanceof Error ? e.message : "Unknown error occurred",
|
|
541
597
|
id: parsed.id,
|
|
542
598
|
success: false,
|
|
543
|
-
type:
|
|
599
|
+
type: MessageType.RPC
|
|
544
600
|
};
|
|
545
601
|
connection.send(JSON.stringify(response));
|
|
546
602
|
console.error("RPC error:", e);
|
|
@@ -559,44 +615,42 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
559
615
|
// must fix this
|
|
560
616
|
return agentContext.run(
|
|
561
617
|
{ agent: this, connection, request: ctx.request, email: undefined },
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
if (this.state) {
|
|
565
|
-
connection.send(
|
|
566
|
-
JSON.stringify({
|
|
567
|
-
state: this.state,
|
|
568
|
-
type: "cf_agent_state"
|
|
569
|
-
})
|
|
570
|
-
);
|
|
571
|
-
}
|
|
572
|
-
|
|
618
|
+
() => {
|
|
619
|
+
if (this.state) {
|
|
573
620
|
connection.send(
|
|
574
621
|
JSON.stringify({
|
|
575
|
-
|
|
576
|
-
type:
|
|
622
|
+
state: this.state,
|
|
623
|
+
type: MessageType.CF_AGENT_STATE
|
|
577
624
|
})
|
|
578
625
|
);
|
|
626
|
+
}
|
|
579
627
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
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
|
|
589
641
|
},
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
642
|
+
timestamp: Date.now(),
|
|
643
|
+
type: "connect"
|
|
644
|
+
},
|
|
645
|
+
this.ctx
|
|
646
|
+
);
|
|
647
|
+
return this._tryCatch(() => _onConnect(connection, ctx));
|
|
594
648
|
}
|
|
595
649
|
);
|
|
596
650
|
};
|
|
597
651
|
|
|
598
652
|
const _onStart = this.onStart.bind(this);
|
|
599
|
-
this.onStart = async () => {
|
|
653
|
+
this.onStart = async (props?: Props) => {
|
|
600
654
|
return agentContext.run(
|
|
601
655
|
{
|
|
602
656
|
agent: this,
|
|
@@ -610,15 +664,20 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
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
|
-
this.
|
|
614
|
-
JSON.stringify({
|
|
615
|
-
mcp: this.getMcpServers(),
|
|
616
|
-
type: "cf_agent_mcp_servers"
|
|
617
|
-
})
|
|
618
|
-
);
|
|
667
|
+
this.broadcastMcpServers();
|
|
619
668
|
|
|
620
669
|
// from DO storage, reconnect to all servers not currently in the oauth flow using our saved auth information
|
|
621
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
|
+
|
|
622
681
|
servers.forEach((server) => {
|
|
623
682
|
this._connectToMcpServerInternal(
|
|
624
683
|
server.name,
|
|
@@ -634,12 +693,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
634
693
|
)
|
|
635
694
|
.then(() => {
|
|
636
695
|
// Broadcast updated MCP servers state after each server connects
|
|
637
|
-
this.
|
|
638
|
-
JSON.stringify({
|
|
639
|
-
mcp: this.getMcpServers(),
|
|
640
|
-
type: "cf_agent_mcp_servers"
|
|
641
|
-
})
|
|
642
|
-
);
|
|
696
|
+
this.broadcastMcpServers();
|
|
643
697
|
})
|
|
644
698
|
.catch((error) => {
|
|
645
699
|
console.error(
|
|
@@ -647,16 +701,11 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
647
701
|
error
|
|
648
702
|
);
|
|
649
703
|
// Still broadcast even if connection fails, so clients know about the failure
|
|
650
|
-
this.
|
|
651
|
-
JSON.stringify({
|
|
652
|
-
mcp: this.getMcpServers(),
|
|
653
|
-
type: "cf_agent_mcp_servers"
|
|
654
|
-
})
|
|
655
|
-
);
|
|
704
|
+
this.broadcastMcpServers();
|
|
656
705
|
});
|
|
657
706
|
});
|
|
658
707
|
}
|
|
659
|
-
return _onStart();
|
|
708
|
+
return _onStart(props);
|
|
660
709
|
});
|
|
661
710
|
}
|
|
662
711
|
);
|
|
@@ -679,7 +728,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
679
728
|
this.broadcast(
|
|
680
729
|
JSON.stringify({
|
|
681
730
|
state: state,
|
|
682
|
-
type:
|
|
731
|
+
type: MessageType.CF_AGENT_STATE
|
|
683
732
|
}),
|
|
684
733
|
source !== "server" ? [source.id] : []
|
|
685
734
|
);
|
|
@@ -832,41 +881,37 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
832
881
|
while (proto && proto !== Object.prototype && depth < 10) {
|
|
833
882
|
const methodNames = Object.getOwnPropertyNames(proto);
|
|
834
883
|
for (const methodName of methodNames) {
|
|
835
|
-
|
|
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,
|
|
836
887
|
if (
|
|
837
888
|
baseMethods.has(methodName) ||
|
|
838
889
|
methodName.startsWith("_") ||
|
|
839
|
-
|
|
890
|
+
!descriptor ||
|
|
891
|
+
!!descriptor.get ||
|
|
892
|
+
typeof descriptor.value !== "function"
|
|
840
893
|
) {
|
|
841
894
|
continue;
|
|
842
895
|
}
|
|
843
|
-
// If the method doesn't exist in base prototypes, it's a custom method
|
|
844
|
-
if (!baseMethods.has(methodName)) {
|
|
845
|
-
const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
|
|
846
|
-
if (descriptor && typeof descriptor.value === "function") {
|
|
847
|
-
// Wrap the custom method with context
|
|
848
|
-
|
|
849
|
-
const wrappedFunction = withAgentContext(
|
|
850
|
-
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
851
|
-
this[methodName as keyof this] as (...args: any[]) => any
|
|
852
|
-
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
853
|
-
) as any;
|
|
854
|
-
|
|
855
|
-
// if the method is callable, copy the metadata from the original method
|
|
856
|
-
if (this._isCallable(methodName)) {
|
|
857
|
-
callableMetadata.set(
|
|
858
|
-
wrappedFunction,
|
|
859
|
-
callableMetadata.get(
|
|
860
|
-
this[methodName as keyof this] as Function
|
|
861
|
-
)!
|
|
862
|
-
);
|
|
863
|
-
}
|
|
864
896
|
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
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
|
+
);
|
|
869
911
|
}
|
|
912
|
+
|
|
913
|
+
// set the wrapped function on the prototype
|
|
914
|
+
this.constructor.prototype[methodName as keyof this] = wrappedFunction;
|
|
870
915
|
}
|
|
871
916
|
|
|
872
917
|
proto = Object.getPrototypeOf(proto);
|
|
@@ -1349,6 +1394,8 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1349
1394
|
// delete all alarms
|
|
1350
1395
|
await this.ctx.storage.deleteAlarm();
|
|
1351
1396
|
await this.ctx.storage.deleteAll();
|
|
1397
|
+
this._disposables.dispose();
|
|
1398
|
+
await this.mcp.dispose?.();
|
|
1352
1399
|
this.ctx.abort("destroyed"); // enforce that the agent is evicted
|
|
1353
1400
|
|
|
1354
1401
|
this.observability?.emit(
|
|
@@ -1374,25 +1421,42 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1374
1421
|
/**
|
|
1375
1422
|
* Connect to a new MCP Server
|
|
1376
1423
|
*
|
|
1424
|
+
* @param serverName Name of the MCP server
|
|
1377
1425
|
* @param url MCP Server SSE URL
|
|
1378
|
-
* @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.
|
|
1379
1427
|
* @param agentsPrefix agents routing prefix if not using `agents`
|
|
1380
|
-
* @param options MCP client and transport
|
|
1428
|
+
* @param options MCP client and transport options
|
|
1381
1429
|
* @returns authUrl
|
|
1382
1430
|
*/
|
|
1383
1431
|
async addMcpServer(
|
|
1384
1432
|
serverName: string,
|
|
1385
1433
|
url: string,
|
|
1386
|
-
callbackHost
|
|
1434
|
+
callbackHost?: string,
|
|
1387
1435
|
agentsPrefix = "agents",
|
|
1388
1436
|
options?: {
|
|
1389
1437
|
client?: ConstructorParameters<typeof Client>[1];
|
|
1390
1438
|
transport?: {
|
|
1391
|
-
headers
|
|
1439
|
+
headers?: HeadersInit;
|
|
1440
|
+
type?: TransportType;
|
|
1392
1441
|
};
|
|
1393
1442
|
}
|
|
1394
1443
|
): Promise<{ id: string; authUrl: string | undefined }> {
|
|
1395
|
-
|
|
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`;
|
|
1396
1460
|
|
|
1397
1461
|
const result = await this._connectToMcpServerInternal(
|
|
1398
1462
|
serverName,
|
|
@@ -1400,6 +1464,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1400
1464
|
callbackUrl,
|
|
1401
1465
|
options
|
|
1402
1466
|
);
|
|
1467
|
+
|
|
1403
1468
|
this.sql`
|
|
1404
1469
|
INSERT
|
|
1405
1470
|
OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)
|
|
@@ -1414,17 +1479,12 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1414
1479
|
);
|
|
1415
1480
|
`;
|
|
1416
1481
|
|
|
1417
|
-
this.
|
|
1418
|
-
JSON.stringify({
|
|
1419
|
-
mcp: this.getMcpServers(),
|
|
1420
|
-
type: "cf_agent_mcp_servers"
|
|
1421
|
-
})
|
|
1422
|
-
);
|
|
1482
|
+
this.broadcastMcpServers();
|
|
1423
1483
|
|
|
1424
1484
|
return result;
|
|
1425
1485
|
}
|
|
1426
1486
|
|
|
1427
|
-
async _connectToMcpServerInternal(
|
|
1487
|
+
private async _connectToMcpServerInternal(
|
|
1428
1488
|
_serverName: string,
|
|
1429
1489
|
url: string,
|
|
1430
1490
|
callbackUrl: string,
|
|
@@ -1440,6 +1500,7 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1440
1500
|
*/
|
|
1441
1501
|
transport?: {
|
|
1442
1502
|
headers?: HeadersInit;
|
|
1503
|
+
type?: TransportType;
|
|
1443
1504
|
};
|
|
1444
1505
|
},
|
|
1445
1506
|
reconnect?: {
|
|
@@ -1464,6 +1525,9 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1464
1525
|
}
|
|
1465
1526
|
}
|
|
1466
1527
|
|
|
1528
|
+
// Use the transport type specified in options, or default to "auto"
|
|
1529
|
+
const transportType: TransportType = options?.transport?.type ?? "auto";
|
|
1530
|
+
|
|
1467
1531
|
// allows passing through transport headers if necessary
|
|
1468
1532
|
// this handles some non-standard bearer auth setups (i.e. MCP server behind CF access instead of OAuth)
|
|
1469
1533
|
let headerTransportOpts: SSEClientTransportOptions = {};
|
|
@@ -1487,7 +1551,8 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1487
1551
|
reconnect,
|
|
1488
1552
|
transport: {
|
|
1489
1553
|
...headerTransportOpts,
|
|
1490
|
-
authProvider
|
|
1554
|
+
authProvider,
|
|
1555
|
+
type: transportType
|
|
1491
1556
|
}
|
|
1492
1557
|
});
|
|
1493
1558
|
|
|
@@ -1500,15 +1565,11 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1500
1565
|
|
|
1501
1566
|
async removeMcpServer(id: string) {
|
|
1502
1567
|
this.mcp.closeConnection(id);
|
|
1568
|
+
this.mcp.unregisterCallbackUrl(id);
|
|
1503
1569
|
this.sql`
|
|
1504
1570
|
DELETE FROM cf_agents_mcp_servers WHERE id = ${id};
|
|
1505
1571
|
`;
|
|
1506
|
-
this.
|
|
1507
|
-
JSON.stringify({
|
|
1508
|
-
mcp: this.getMcpServers(),
|
|
1509
|
-
type: "cf_agent_mcp_servers"
|
|
1510
|
-
})
|
|
1511
|
-
);
|
|
1572
|
+
this.broadcastMcpServers();
|
|
1512
1573
|
}
|
|
1513
1574
|
|
|
1514
1575
|
getMcpServers(): MCPServersState {
|
|
@@ -1540,8 +1601,53 @@ export class Agent<Env = typeof env, State = unknown> extends Server<Env> {
|
|
|
1540
1601
|
|
|
1541
1602
|
return mcpState;
|
|
1542
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
|
+
}
|
|
1543
1646
|
}
|
|
1544
1647
|
|
|
1648
|
+
// A set of classes that have been wrapped with agent context
|
|
1649
|
+
const wrappedClasses = new Set<typeof Agent.prototype.constructor>();
|
|
1650
|
+
|
|
1545
1651
|
/**
|
|
1546
1652
|
* Namespace for creating Agent instances
|
|
1547
1653
|
* @template Agentic Type of the Agent class
|
|
@@ -1857,12 +1963,17 @@ export type EmailSendOptions = {
|
|
|
1857
1963
|
* @param options Options for Agent creation
|
|
1858
1964
|
* @returns Promise resolving to an Agent instance stub
|
|
1859
1965
|
*/
|
|
1860
|
-
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
|
+
>(
|
|
1861
1971
|
namespace: AgentNamespace<T>,
|
|
1862
1972
|
name: string,
|
|
1863
1973
|
options?: {
|
|
1864
1974
|
jurisdiction?: DurableObjectJurisdiction;
|
|
1865
1975
|
locationHint?: DurableObjectLocationHint;
|
|
1976
|
+
props?: Props;
|
|
1866
1977
|
}
|
|
1867
1978
|
) {
|
|
1868
1979
|
return getServerByName<Env, T>(namespace, name, options);
|
|
@@ -1894,7 +2005,7 @@ export class StreamingResponse {
|
|
|
1894
2005
|
id: this._id,
|
|
1895
2006
|
result: chunk,
|
|
1896
2007
|
success: true,
|
|
1897
|
-
type:
|
|
2008
|
+
type: MessageType.RPC
|
|
1898
2009
|
};
|
|
1899
2010
|
this._connection.send(JSON.stringify(response));
|
|
1900
2011
|
}
|
|
@@ -1913,7 +2024,7 @@ export class StreamingResponse {
|
|
|
1913
2024
|
id: this._id,
|
|
1914
2025
|
result: finalChunk,
|
|
1915
2026
|
success: true,
|
|
1916
|
-
type:
|
|
2027
|
+
type: MessageType.RPC
|
|
1917
2028
|
};
|
|
1918
2029
|
this._connection.send(JSON.stringify(response));
|
|
1919
2030
|
}
|