agents 0.0.0-e48e5f9 → 0.0.0-e777fdd
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 +234 -6
- package/dist/_esm-LV5FJ3HK.js +3922 -0
- package/dist/_esm-LV5FJ3HK.js.map +1 -0
- package/dist/ai-chat-agent.d.ts +12 -9
- package/dist/ai-chat-agent.js +151 -59
- 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 +68 -71
- 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-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-MW5BQ2FW.js → chunk-QEPGNUG6.js} +213 -32
- package/dist/chunk-QEPGNUG6.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-5YIRLLUX.js → chunk-RS5OCNEQ.js} +169 -110
- package/dist/chunk-RS5OCNEQ.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-XFS5ERG3.js} +24 -3
- package/dist/chunk-XFS5ERG3.js.map +1 -0
- package/dist/client-BohGLma8.d.ts +5041 -0
- package/dist/client.js +3 -1
- package/dist/index.d.ts +564 -32
- package/dist/index.js +8 -4
- package/dist/mcp/client.d.ts +9 -1053
- package/dist/mcp/client.js +2 -1
- package/dist/mcp/do-oauth-client-provider.d.ts +9 -0
- package/dist/mcp/do-oauth-client-provider.js +2 -1
- package/dist/mcp/index.d.ts +57 -63
- package/dist/mcp/index.js +954 -638
- 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/observability/index.d.ts +46 -12
- package/dist/observability/index.js +6 -4
- package/dist/react.d.ts +7 -3
- package/dist/react.js +8 -5
- 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 +25 -9
- package/src/index.ts +240 -131
- package/dist/chunk-5YIRLLUX.js.map +0 -1
- package/dist/chunk-KUH345EY.js.map +0 -1
- package/dist/chunk-MW5BQ2FW.js.map +0 -1
- package/dist/chunk-PVQZBKN7.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";
|
|
@@ -22,9 +23,10 @@ import {
|
|
|
22
23
|
} from "partyserver";
|
|
23
24
|
import { camelCaseToKebabCase } from "./client";
|
|
24
25
|
import { MCPClientManager } from "./mcp/client";
|
|
25
|
-
// import type { MCPClientConnection } from "./mcp/client-connection";
|
|
26
26
|
import { DurableObjectOAuthClientProvider } from "./mcp/do-oauth-client-provider";
|
|
27
|
+
import type { TransportType } from "./mcp/types";
|
|
27
28
|
import { genericObservability, type Observability } from "./observability";
|
|
29
|
+
import { MessageType } from "./ai-types";
|
|
28
30
|
|
|
29
31
|
export type { Connection, ConnectionContext, WSMessage } from "partyserver";
|
|
30
32
|
|
|
@@ -42,7 +44,7 @@ export type RPCRequest = {
|
|
|
42
44
|
* State update message from client
|
|
43
45
|
*/
|
|
44
46
|
export type StateUpdateMessage = {
|
|
45
|
-
type:
|
|
47
|
+
type: MessageType.CF_AGENT_STATE;
|
|
46
48
|
state: unknown;
|
|
47
49
|
};
|
|
48
50
|
|
|
@@ -50,7 +52,7 @@ export type StateUpdateMessage = {
|
|
|
50
52
|
* RPC response message to client
|
|
51
53
|
*/
|
|
52
54
|
export type RPCResponse = {
|
|
53
|
-
type:
|
|
55
|
+
type: MessageType.RPC;
|
|
54
56
|
id: string;
|
|
55
57
|
} & (
|
|
56
58
|
| {
|
|
@@ -77,7 +79,7 @@ function isRPCRequest(msg: unknown): msg is RPCRequest {
|
|
|
77
79
|
typeof msg === "object" &&
|
|
78
80
|
msg !== null &&
|
|
79
81
|
"type" in msg &&
|
|
80
|
-
msg.type ===
|
|
82
|
+
msg.type === MessageType.RPC &&
|
|
81
83
|
"id" in msg &&
|
|
82
84
|
typeof msg.id === "string" &&
|
|
83
85
|
"method" in msg &&
|
|
@@ -95,7 +97,7 @@ function isStateUpdateMessage(msg: unknown): msg is StateUpdateMessage {
|
|
|
95
97
|
typeof msg === "object" &&
|
|
96
98
|
msg !== null &&
|
|
97
99
|
"type" in msg &&
|
|
98
|
-
msg.type ===
|
|
100
|
+
msg.type === MessageType.CF_AGENT_STATE &&
|
|
99
101
|
"state" in msg
|
|
100
102
|
);
|
|
101
103
|
}
|
|
@@ -116,7 +118,7 @@ const callableMetadata = new Map<Function, CallableMetadata>();
|
|
|
116
118
|
* Decorator that marks a method as callable by clients
|
|
117
119
|
* @param metadata Optional metadata about the callable method
|
|
118
120
|
*/
|
|
119
|
-
export function
|
|
121
|
+
export function callable(metadata: CallableMetadata = {}) {
|
|
120
122
|
return function callableDecorator<This, Args extends unknown[], Return>(
|
|
121
123
|
target: (this: This, ...args: Args) => Return,
|
|
122
124
|
// biome-ignore lint/correctness/noUnusedFunctionParameters: later
|
|
@@ -130,6 +132,23 @@ export function unstable_callable(metadata: CallableMetadata = {}) {
|
|
|
130
132
|
};
|
|
131
133
|
}
|
|
132
134
|
|
|
135
|
+
let didWarnAboutUnstableCallable = false;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Decorator that marks a method as callable by clients
|
|
139
|
+
* @deprecated this has been renamed to callable, and unstable_callable will be removed in the next major version
|
|
140
|
+
* @param metadata Optional metadata about the callable method
|
|
141
|
+
*/
|
|
142
|
+
export const unstable_callable = (metadata: CallableMetadata = {}) => {
|
|
143
|
+
if (!didWarnAboutUnstableCallable) {
|
|
144
|
+
didWarnAboutUnstableCallable = true;
|
|
145
|
+
console.warn(
|
|
146
|
+
"unstable_callable is deprecated, use callable instead. unstable_callable will be removed in the next major version."
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
callable(metadata);
|
|
150
|
+
};
|
|
151
|
+
|
|
133
152
|
export type QueueItem<T = string> = {
|
|
134
153
|
id: string;
|
|
135
154
|
payload: T;
|
|
@@ -178,11 +197,13 @@ function getNextCronTime(cron: string) {
|
|
|
178
197
|
return interval.getNextDate();
|
|
179
198
|
}
|
|
180
199
|
|
|
200
|
+
export type { TransportType } from "./mcp/types";
|
|
201
|
+
|
|
181
202
|
/**
|
|
182
203
|
* MCP Server state update message from server -> Client
|
|
183
204
|
*/
|
|
184
205
|
export type MCPServerMessage = {
|
|
185
|
-
type:
|
|
206
|
+
type: MessageType.CF_AGENT_MCP_SERVERS;
|
|
186
207
|
mcp: MCPServersState;
|
|
187
208
|
};
|
|
188
209
|
|
|
@@ -271,7 +292,13 @@ function withAgentContext<T extends (...args: any[]) => any>(
|
|
|
271
292
|
method: T
|
|
272
293
|
): (this: Agent<unknown, unknown>, ...args: Parameters<T>) => ReturnType<T> {
|
|
273
294
|
return function (...args: Parameters<T>): ReturnType<T> {
|
|
274
|
-
const { connection, request, email } = getCurrentAgent();
|
|
295
|
+
const { connection, request, email, agent } = getCurrentAgent();
|
|
296
|
+
|
|
297
|
+
if (agent === this) {
|
|
298
|
+
// already wrapped, so we can just call the method
|
|
299
|
+
return method.apply(this, args);
|
|
300
|
+
}
|
|
301
|
+
// not wrapped, so we need to wrap it
|
|
275
302
|
return agentContext.run({ agent: this, connection, request, email }, () => {
|
|
276
303
|
return method.apply(this, args);
|
|
277
304
|
});
|
|
@@ -283,13 +310,20 @@ function withAgentContext<T extends (...args: any[]) => any>(
|
|
|
283
310
|
* @template Env Environment type containing bindings
|
|
284
311
|
* @template State State type to store within the Agent
|
|
285
312
|
*/
|
|
286
|
-
export class Agent<
|
|
313
|
+
export class Agent<
|
|
314
|
+
Env = typeof env,
|
|
315
|
+
State = unknown,
|
|
316
|
+
Props extends Record<string, unknown> = Record<string, unknown>
|
|
317
|
+
> extends Server<Env, Props> {
|
|
287
318
|
private _state = DEFAULT_STATE as State;
|
|
288
319
|
|
|
289
320
|
private _ParentClass: typeof Agent<Env, State> =
|
|
290
321
|
Object.getPrototypeOf(this).constructor;
|
|
291
322
|
|
|
292
|
-
mcp: MCPClientManager = new MCPClientManager(
|
|
323
|
+
readonly mcp: MCPClientManager = new MCPClientManager(
|
|
324
|
+
this._ParentClass.name,
|
|
325
|
+
"0.0.1"
|
|
326
|
+
);
|
|
293
327
|
|
|
294
328
|
/**
|
|
295
329
|
* Initial state for the Agent
|
|
@@ -382,8 +416,11 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
382
416
|
constructor(ctx: AgentContext, env: Env) {
|
|
383
417
|
super(ctx, env);
|
|
384
418
|
|
|
385
|
-
|
|
386
|
-
|
|
419
|
+
if (!wrappedClasses.has(this.constructor)) {
|
|
420
|
+
// Auto-wrap custom methods with agent context
|
|
421
|
+
this._autoWrapCustomMethods();
|
|
422
|
+
wrappedClasses.add(this.constructor);
|
|
423
|
+
}
|
|
387
424
|
|
|
388
425
|
this.sql`
|
|
389
426
|
CREATE TABLE IF NOT EXISTS cf_agents_state (
|
|
@@ -446,7 +483,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
446
483
|
this.broadcast(
|
|
447
484
|
JSON.stringify({
|
|
448
485
|
mcp: this.getMcpServers(),
|
|
449
|
-
type:
|
|
486
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
450
487
|
})
|
|
451
488
|
);
|
|
452
489
|
|
|
@@ -515,10 +552,8 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
515
552
|
displayMessage: `RPC call to ${method}`,
|
|
516
553
|
id: nanoid(),
|
|
517
554
|
payload: {
|
|
518
|
-
args,
|
|
519
555
|
method,
|
|
520
|
-
streaming: metadata?.streaming
|
|
521
|
-
success: true
|
|
556
|
+
streaming: metadata?.streaming
|
|
522
557
|
},
|
|
523
558
|
timestamp: Date.now(),
|
|
524
559
|
type: "rpc"
|
|
@@ -531,7 +566,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
531
566
|
id,
|
|
532
567
|
result,
|
|
533
568
|
success: true,
|
|
534
|
-
type:
|
|
569
|
+
type: MessageType.RPC
|
|
535
570
|
};
|
|
536
571
|
connection.send(JSON.stringify(response));
|
|
537
572
|
} catch (e) {
|
|
@@ -541,7 +576,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
541
576
|
e instanceof Error ? e.message : "Unknown error occurred",
|
|
542
577
|
id: parsed.id,
|
|
543
578
|
success: false,
|
|
544
|
-
type:
|
|
579
|
+
type: MessageType.RPC
|
|
545
580
|
};
|
|
546
581
|
connection.send(JSON.stringify(response));
|
|
547
582
|
console.error("RPC error:", e);
|
|
@@ -560,44 +595,42 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
560
595
|
// must fix this
|
|
561
596
|
return agentContext.run(
|
|
562
597
|
{ 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
|
-
|
|
598
|
+
() => {
|
|
599
|
+
if (this.state) {
|
|
574
600
|
connection.send(
|
|
575
601
|
JSON.stringify({
|
|
576
|
-
|
|
577
|
-
type:
|
|
602
|
+
state: this.state,
|
|
603
|
+
type: MessageType.CF_AGENT_STATE
|
|
578
604
|
})
|
|
579
605
|
);
|
|
606
|
+
}
|
|
580
607
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
608
|
+
connection.send(
|
|
609
|
+
JSON.stringify({
|
|
610
|
+
mcp: this.getMcpServers(),
|
|
611
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
612
|
+
})
|
|
613
|
+
);
|
|
614
|
+
|
|
615
|
+
this.observability?.emit(
|
|
616
|
+
{
|
|
617
|
+
displayMessage: "Connection established",
|
|
618
|
+
id: nanoid(),
|
|
619
|
+
payload: {
|
|
620
|
+
connectionId: connection.id
|
|
590
621
|
},
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
622
|
+
timestamp: Date.now(),
|
|
623
|
+
type: "connect"
|
|
624
|
+
},
|
|
625
|
+
this.ctx
|
|
626
|
+
);
|
|
627
|
+
return this._tryCatch(() => _onConnect(connection, ctx));
|
|
595
628
|
}
|
|
596
629
|
);
|
|
597
630
|
};
|
|
598
631
|
|
|
599
632
|
const _onStart = this.onStart.bind(this);
|
|
600
|
-
this.onStart = async () => {
|
|
633
|
+
this.onStart = async (props?: Props) => {
|
|
601
634
|
return agentContext.run(
|
|
602
635
|
{
|
|
603
636
|
agent: this,
|
|
@@ -606,15 +639,29 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
606
639
|
email: undefined
|
|
607
640
|
},
|
|
608
641
|
async () => {
|
|
609
|
-
|
|
642
|
+
await this._tryCatch(() => {
|
|
643
|
+
const servers = this.sql<MCPServerRow>`
|
|
610
644
|
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
611
645
|
`;
|
|
612
646
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
647
|
+
this.broadcast(
|
|
648
|
+
JSON.stringify({
|
|
649
|
+
mcp: this.getMcpServers(),
|
|
650
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
651
|
+
})
|
|
652
|
+
);
|
|
653
|
+
|
|
654
|
+
// from DO storage, reconnect to all servers not currently in the oauth flow using our saved auth information
|
|
655
|
+
if (servers && Array.isArray(servers) && servers.length > 0) {
|
|
656
|
+
// Restore callback URLs for OAuth-enabled servers
|
|
657
|
+
servers.forEach((server) => {
|
|
658
|
+
if (server.callback_url) {
|
|
659
|
+
this.mcp.registerCallbackUrl(server.callback_url);
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
servers.forEach((server) => {
|
|
664
|
+
this._connectToMcpServerInternal(
|
|
618
665
|
server.name,
|
|
619
666
|
server.server_url,
|
|
620
667
|
server.callback_url,
|
|
@@ -625,18 +672,33 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
625
672
|
id: server.id,
|
|
626
673
|
oauthClientId: server.client_id ?? undefined
|
|
627
674
|
}
|
|
628
|
-
)
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
675
|
+
)
|
|
676
|
+
.then(() => {
|
|
677
|
+
// Broadcast updated MCP servers state after each server connects
|
|
678
|
+
this.broadcast(
|
|
679
|
+
JSON.stringify({
|
|
680
|
+
mcp: this.getMcpServers(),
|
|
681
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
682
|
+
})
|
|
683
|
+
);
|
|
684
|
+
})
|
|
685
|
+
.catch((error) => {
|
|
686
|
+
console.error(
|
|
687
|
+
`Error connecting to MCP server: ${server.name} (${server.server_url})`,
|
|
688
|
+
error
|
|
689
|
+
);
|
|
690
|
+
// Still broadcast even if connection fails, so clients know about the failure
|
|
691
|
+
this.broadcast(
|
|
692
|
+
JSON.stringify({
|
|
693
|
+
mcp: this.getMcpServers(),
|
|
694
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
695
|
+
})
|
|
696
|
+
);
|
|
697
|
+
});
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
return _onStart(props);
|
|
701
|
+
});
|
|
640
702
|
}
|
|
641
703
|
);
|
|
642
704
|
};
|
|
@@ -646,7 +708,6 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
646
708
|
state: State,
|
|
647
709
|
source: Connection | "server" = "server"
|
|
648
710
|
) {
|
|
649
|
-
const previousState = this._state;
|
|
650
711
|
this._state = state;
|
|
651
712
|
this.sql`
|
|
652
713
|
INSERT OR REPLACE INTO cf_agents_state (id, state)
|
|
@@ -659,7 +720,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
659
720
|
this.broadcast(
|
|
660
721
|
JSON.stringify({
|
|
661
722
|
state: state,
|
|
662
|
-
type:
|
|
723
|
+
type: MessageType.CF_AGENT_STATE
|
|
663
724
|
}),
|
|
664
725
|
source !== "server" ? [source.id] : []
|
|
665
726
|
);
|
|
@@ -672,10 +733,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
672
733
|
{
|
|
673
734
|
displayMessage: "State updated",
|
|
674
735
|
id: nanoid(),
|
|
675
|
-
payload: {
|
|
676
|
-
previousState,
|
|
677
|
-
state
|
|
678
|
-
},
|
|
736
|
+
payload: {},
|
|
679
737
|
timestamp: Date.now(),
|
|
680
738
|
type: "state:update"
|
|
681
739
|
},
|
|
@@ -815,41 +873,37 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
815
873
|
while (proto && proto !== Object.prototype && depth < 10) {
|
|
816
874
|
const methodNames = Object.getOwnPropertyNames(proto);
|
|
817
875
|
for (const methodName of methodNames) {
|
|
818
|
-
|
|
876
|
+
const descriptor = Object.getOwnPropertyDescriptor(proto, methodName);
|
|
877
|
+
|
|
878
|
+
// Skip if it's a private method, a base method, a getter, or not a function,
|
|
819
879
|
if (
|
|
820
880
|
baseMethods.has(methodName) ||
|
|
821
881
|
methodName.startsWith("_") ||
|
|
822
|
-
|
|
882
|
+
!descriptor ||
|
|
883
|
+
!!descriptor.get ||
|
|
884
|
+
typeof descriptor.value !== "function"
|
|
823
885
|
) {
|
|
824
886
|
continue;
|
|
825
887
|
}
|
|
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
888
|
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
889
|
+
// Now, methodName is confirmed to be a custom method/function
|
|
890
|
+
// Wrap the custom method with context
|
|
891
|
+
const wrappedFunction = withAgentContext(
|
|
892
|
+
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
893
|
+
this[methodName as keyof this] as (...args: any[]) => any
|
|
894
|
+
// biome-ignore lint/suspicious/noExplicitAny: I can't typescript
|
|
895
|
+
) as any;
|
|
896
|
+
|
|
897
|
+
// if the method is callable, copy the metadata from the original method
|
|
898
|
+
if (this._isCallable(methodName)) {
|
|
899
|
+
callableMetadata.set(
|
|
900
|
+
wrappedFunction,
|
|
901
|
+
callableMetadata.get(this[methodName as keyof this] as Function)!
|
|
902
|
+
);
|
|
852
903
|
}
|
|
904
|
+
|
|
905
|
+
// set the wrapped function on the prototype
|
|
906
|
+
this.constructor.prototype[methodName as keyof this] = wrappedFunction;
|
|
853
907
|
}
|
|
854
908
|
|
|
855
909
|
proto = Object.getPrototypeOf(proto);
|
|
@@ -927,7 +981,6 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
927
981
|
}
|
|
928
982
|
this._flushingQueue = true;
|
|
929
983
|
while (true) {
|
|
930
|
-
const executed: string[] = [];
|
|
931
984
|
const result = this.sql<QueueItem<string>>`
|
|
932
985
|
SELECT * FROM cf_agents_queues
|
|
933
986
|
ORDER BY created_at ASC
|
|
@@ -959,13 +1012,10 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
959
1012
|
queueItem: QueueItem<string>
|
|
960
1013
|
) => Promise<void>
|
|
961
1014
|
).bind(this)(JSON.parse(row.payload as string), row);
|
|
962
|
-
|
|
1015
|
+
await this.dequeue(row.id);
|
|
963
1016
|
}
|
|
964
1017
|
);
|
|
965
1018
|
}
|
|
966
|
-
for (const id of executed) {
|
|
967
|
-
await this.dequeue(id);
|
|
968
|
-
}
|
|
969
1019
|
}
|
|
970
1020
|
this._flushingQueue = false;
|
|
971
1021
|
}
|
|
@@ -1040,7 +1090,10 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1040
1090
|
{
|
|
1041
1091
|
displayMessage: `Schedule ${schedule.id} created`,
|
|
1042
1092
|
id: nanoid(),
|
|
1043
|
-
payload:
|
|
1093
|
+
payload: {
|
|
1094
|
+
callback: callback as string,
|
|
1095
|
+
id: id
|
|
1096
|
+
},
|
|
1044
1097
|
timestamp: Date.now(),
|
|
1045
1098
|
type: "schedule:create"
|
|
1046
1099
|
},
|
|
@@ -1210,7 +1263,10 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1210
1263
|
{
|
|
1211
1264
|
displayMessage: `Schedule ${id} cancelled`,
|
|
1212
1265
|
id: nanoid(),
|
|
1213
|
-
payload:
|
|
1266
|
+
payload: {
|
|
1267
|
+
callback: schedule.callback,
|
|
1268
|
+
id: schedule.id
|
|
1269
|
+
},
|
|
1214
1270
|
timestamp: Date.now(),
|
|
1215
1271
|
type: "schedule:cancel"
|
|
1216
1272
|
},
|
|
@@ -1226,9 +1282,9 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1226
1282
|
private async _scheduleNextAlarm() {
|
|
1227
1283
|
// Find the next schedule that needs to be executed
|
|
1228
1284
|
const result = this.sql`
|
|
1229
|
-
SELECT time FROM cf_agents_schedules
|
|
1285
|
+
SELECT time FROM cf_agents_schedules
|
|
1230
1286
|
WHERE time > ${Math.floor(Date.now() / 1000)}
|
|
1231
|
-
ORDER BY time ASC
|
|
1287
|
+
ORDER BY time ASC
|
|
1232
1288
|
LIMIT 1
|
|
1233
1289
|
`;
|
|
1234
1290
|
if (!result) return;
|
|
@@ -1275,7 +1331,10 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1275
1331
|
{
|
|
1276
1332
|
displayMessage: `Schedule ${row.id} executed`,
|
|
1277
1333
|
id: nanoid(),
|
|
1278
|
-
payload:
|
|
1334
|
+
payload: {
|
|
1335
|
+
callback: row.callback,
|
|
1336
|
+
id: row.id
|
|
1337
|
+
},
|
|
1279
1338
|
timestamp: Date.now(),
|
|
1280
1339
|
type: "schedule:execute"
|
|
1281
1340
|
},
|
|
@@ -1352,8 +1411,9 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1352
1411
|
/**
|
|
1353
1412
|
* Connect to a new MCP Server
|
|
1354
1413
|
*
|
|
1414
|
+
* @param serverName Name of the MCP server
|
|
1355
1415
|
* @param url MCP Server SSE URL
|
|
1356
|
-
* @param callbackHost Base host for the agent, used for the redirect URI.
|
|
1416
|
+
* @param callbackHost Base host for the agent, used for the redirect URI. If not provided, will be derived from the current request.
|
|
1357
1417
|
* @param agentsPrefix agents routing prefix if not using `agents`
|
|
1358
1418
|
* @param options MCP client and transport (header) options
|
|
1359
1419
|
* @returns authUrl
|
|
@@ -1361,7 +1421,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1361
1421
|
async addMcpServer(
|
|
1362
1422
|
serverName: string,
|
|
1363
1423
|
url: string,
|
|
1364
|
-
callbackHost
|
|
1424
|
+
callbackHost?: string,
|
|
1365
1425
|
agentsPrefix = "agents",
|
|
1366
1426
|
options?: {
|
|
1367
1427
|
client?: ConstructorParameters<typeof Client>[1];
|
|
@@ -1370,7 +1430,22 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1370
1430
|
};
|
|
1371
1431
|
}
|
|
1372
1432
|
): Promise<{ id: string; authUrl: string | undefined }> {
|
|
1373
|
-
|
|
1433
|
+
// If callbackHost is not provided, derive it from the current request
|
|
1434
|
+
let resolvedCallbackHost = callbackHost;
|
|
1435
|
+
if (!resolvedCallbackHost) {
|
|
1436
|
+
const { request } = getCurrentAgent();
|
|
1437
|
+
if (!request) {
|
|
1438
|
+
throw new Error(
|
|
1439
|
+
"callbackHost is required when not called within a request context"
|
|
1440
|
+
);
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
// Extract the origin from the request
|
|
1444
|
+
const requestUrl = new URL(request.url);
|
|
1445
|
+
resolvedCallbackHost = `${requestUrl.protocol}//${requestUrl.host}`;
|
|
1446
|
+
}
|
|
1447
|
+
|
|
1448
|
+
const callbackUrl = `${resolvedCallbackHost}/${agentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;
|
|
1374
1449
|
|
|
1375
1450
|
const result = await this._connectToMcpServerInternal(
|
|
1376
1451
|
serverName,
|
|
@@ -1395,7 +1470,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1395
1470
|
this.broadcast(
|
|
1396
1471
|
JSON.stringify({
|
|
1397
1472
|
mcp: this.getMcpServers(),
|
|
1398
|
-
type:
|
|
1473
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
1399
1474
|
})
|
|
1400
1475
|
);
|
|
1401
1476
|
|
|
@@ -1418,6 +1493,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1418
1493
|
*/
|
|
1419
1494
|
transport?: {
|
|
1420
1495
|
headers?: HeadersInit;
|
|
1496
|
+
type?: TransportType;
|
|
1421
1497
|
};
|
|
1422
1498
|
},
|
|
1423
1499
|
reconnect?: {
|
|
@@ -1460,12 +1536,16 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1460
1536
|
};
|
|
1461
1537
|
}
|
|
1462
1538
|
|
|
1539
|
+
// Use the transport type specified in options, or default to "auto"
|
|
1540
|
+
const transportType = options?.transport?.type || "auto";
|
|
1541
|
+
|
|
1463
1542
|
const { id, authUrl, clientId } = await this.mcp.connect(url, {
|
|
1464
1543
|
client: options?.client,
|
|
1465
1544
|
reconnect,
|
|
1466
1545
|
transport: {
|
|
1467
1546
|
...headerTransportOpts,
|
|
1468
|
-
authProvider
|
|
1547
|
+
authProvider,
|
|
1548
|
+
type: transportType
|
|
1469
1549
|
}
|
|
1470
1550
|
});
|
|
1471
1551
|
|
|
@@ -1478,13 +1558,14 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1478
1558
|
|
|
1479
1559
|
async removeMcpServer(id: string) {
|
|
1480
1560
|
this.mcp.closeConnection(id);
|
|
1561
|
+
this.mcp.unregisterCallbackUrl(id);
|
|
1481
1562
|
this.sql`
|
|
1482
1563
|
DELETE FROM cf_agents_mcp_servers WHERE id = ${id};
|
|
1483
1564
|
`;
|
|
1484
1565
|
this.broadcast(
|
|
1485
1566
|
JSON.stringify({
|
|
1486
1567
|
mcp: this.getMcpServers(),
|
|
1487
|
-
type:
|
|
1568
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
1488
1569
|
})
|
|
1489
1570
|
);
|
|
1490
1571
|
}
|
|
@@ -1520,6 +1601,9 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1520
1601
|
}
|
|
1521
1602
|
}
|
|
1522
1603
|
|
|
1604
|
+
// A set of classes that have been wrapped with agent context
|
|
1605
|
+
const wrappedClasses = new Set<typeof Agent.prototype.constructor>();
|
|
1606
|
+
|
|
1523
1607
|
/**
|
|
1524
1608
|
* Namespace for creating Agent instances
|
|
1525
1609
|
* @template Agentic Type of the Agent class
|
|
@@ -1696,6 +1780,13 @@ export type EmailRoutingOptions<Env> = AgentOptions<Env> & {
|
|
|
1696
1780
|
resolver: EmailResolver<Env>;
|
|
1697
1781
|
};
|
|
1698
1782
|
|
|
1783
|
+
// Cache the agent namespace map for email routing
|
|
1784
|
+
// This maps both kebab-case and original names to namespaces
|
|
1785
|
+
const agentMapCache = new WeakMap<
|
|
1786
|
+
Record<string, unknown>,
|
|
1787
|
+
Record<string, unknown>
|
|
1788
|
+
>();
|
|
1789
|
+
|
|
1699
1790
|
/**
|
|
1700
1791
|
* Route an email to the appropriate Agent
|
|
1701
1792
|
* @param email The email to route
|
|
@@ -1715,28 +1806,41 @@ export async function routeAgentEmail<Env>(
|
|
|
1715
1806
|
return;
|
|
1716
1807
|
}
|
|
1717
1808
|
|
|
1718
|
-
|
|
1719
|
-
if (!
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1809
|
+
// Build a map that includes both original names and kebab-case versions
|
|
1810
|
+
if (!agentMapCache.has(env as Record<string, unknown>)) {
|
|
1811
|
+
const map: Record<string, unknown> = {};
|
|
1812
|
+
for (const [key, value] of Object.entries(env as Record<string, unknown>)) {
|
|
1813
|
+
if (
|
|
1814
|
+
value &&
|
|
1815
|
+
typeof value === "object" &&
|
|
1816
|
+
"idFromName" in value &&
|
|
1817
|
+
typeof value.idFromName === "function"
|
|
1818
|
+
) {
|
|
1819
|
+
// Add both the original name and kebab-case version
|
|
1820
|
+
map[key] = value;
|
|
1821
|
+
map[camelCaseToKebabCase(key)] = value;
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
agentMapCache.set(env as Record<string, unknown>, map);
|
|
1723
1825
|
}
|
|
1724
1826
|
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1827
|
+
const agentMap = agentMapCache.get(env as Record<string, unknown>)!;
|
|
1828
|
+
const namespace = agentMap[routingInfo.agentName];
|
|
1829
|
+
|
|
1830
|
+
if (!namespace) {
|
|
1831
|
+
// Provide helpful error message listing available agents
|
|
1832
|
+
const availableAgents = Object.keys(agentMap)
|
|
1833
|
+
.filter((key) => !key.includes("-")) // Show only original names, not kebab-case duplicates
|
|
1834
|
+
.join(", ");
|
|
1731
1835
|
throw new Error(
|
|
1732
|
-
`
|
|
1836
|
+
`Agent namespace '${routingInfo.agentName}' not found in environment. Available agents: ${availableAgents}`
|
|
1733
1837
|
);
|
|
1734
1838
|
}
|
|
1735
1839
|
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1840
|
+
const agent = await getAgentByName(
|
|
1841
|
+
namespace as unknown as AgentNamespace<Agent<Env>>,
|
|
1842
|
+
routingInfo.agentId
|
|
1843
|
+
);
|
|
1740
1844
|
|
|
1741
1845
|
// let's make a serialisable version of the email
|
|
1742
1846
|
const serialisableEmail: AgentEmail = {
|
|
@@ -1815,12 +1919,17 @@ export type EmailSendOptions = {
|
|
|
1815
1919
|
* @param options Options for Agent creation
|
|
1816
1920
|
* @returns Promise resolving to an Agent instance stub
|
|
1817
1921
|
*/
|
|
1818
|
-
export async function getAgentByName<
|
|
1922
|
+
export async function getAgentByName<
|
|
1923
|
+
Env,
|
|
1924
|
+
T extends Agent<Env>,
|
|
1925
|
+
Props extends Record<string, unknown> = Record<string, unknown>
|
|
1926
|
+
>(
|
|
1819
1927
|
namespace: AgentNamespace<T>,
|
|
1820
1928
|
name: string,
|
|
1821
1929
|
options?: {
|
|
1822
1930
|
jurisdiction?: DurableObjectJurisdiction;
|
|
1823
1931
|
locationHint?: DurableObjectLocationHint;
|
|
1932
|
+
props?: Props;
|
|
1824
1933
|
}
|
|
1825
1934
|
) {
|
|
1826
1935
|
return getServerByName<Env, T>(namespace, name, options);
|
|
@@ -1852,7 +1961,7 @@ export class StreamingResponse {
|
|
|
1852
1961
|
id: this._id,
|
|
1853
1962
|
result: chunk,
|
|
1854
1963
|
success: true,
|
|
1855
|
-
type:
|
|
1964
|
+
type: MessageType.RPC
|
|
1856
1965
|
};
|
|
1857
1966
|
this._connection.send(JSON.stringify(response));
|
|
1858
1967
|
}
|
|
@@ -1871,7 +1980,7 @@ export class StreamingResponse {
|
|
|
1871
1980
|
id: this._id,
|
|
1872
1981
|
result: finalChunk,
|
|
1873
1982
|
success: true,
|
|
1874
|
-
type:
|
|
1983
|
+
type: MessageType.RPC
|
|
1875
1984
|
};
|
|
1876
1985
|
this._connection.send(JSON.stringify(response));
|
|
1877
1986
|
}
|