agents 0.0.0-25aeaf2 → 0.0.0-2662748
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-chat-agent.d.ts +28 -2
- package/dist/ai-chat-agent.js +99 -105
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-react.d.ts +2 -1
- package/dist/ai-react.js +0 -2
- package/dist/ai-react.js.map +1 -1
- package/dist/{chunk-D6UOOELW.js → chunk-BZXOAZUX.js} +11 -11
- package/dist/chunk-BZXOAZUX.js.map +1 -0
- package/dist/{chunk-25YDMV4H.js → chunk-OYJXQRRH.js} +13 -12
- package/dist/chunk-OYJXQRRH.js.map +1 -0
- package/dist/{chunk-YFPCCSZO.js → chunk-P3RZJ72N.js} +183 -187
- package/dist/chunk-P3RZJ72N.js.map +1 -0
- package/dist/{chunk-RN4SNE73.js → chunk-VCSB47AK.js} +10 -27
- package/dist/chunk-VCSB47AK.js.map +1 -0
- package/dist/client.d.ts +8 -1
- package/dist/client.js +1 -2
- package/dist/index.d.ts +47 -3
- package/dist/index.js +4 -5
- package/dist/mcp/client.d.ts +6 -6
- package/dist/mcp/client.js +1 -2
- package/dist/mcp/do-oauth-client-provider.d.ts +3 -3
- package/dist/mcp/do-oauth-client-provider.js +1 -2
- package/dist/mcp/index.d.ts +10 -1
- package/dist/mcp/index.js +90 -126
- package/dist/mcp/index.js.map +1 -1
- package/dist/react.d.ts +73 -7
- package/dist/react.js +10 -2
- package/dist/react.js.map +1 -1
- package/dist/schedule.js +0 -2
- package/dist/schedule.js.map +1 -1
- package/dist/serializable.d.ts +32 -0
- package/dist/serializable.js +1 -0
- package/package.json +8 -8
- package/src/index.ts +86 -78
- package/dist/chunk-25YDMV4H.js.map +0 -1
- package/dist/chunk-D6UOOELW.js.map +0 -1
- package/dist/chunk-HMLY7DHA.js +0 -16
- package/dist/chunk-RN4SNE73.js.map +0 -1
- package/dist/chunk-YFPCCSZO.js.map +0 -1
- /package/dist/{chunk-HMLY7DHA.js.map → serializable.js.map} +0 -0
package/src/index.ts
CHANGED
|
@@ -1,34 +1,32 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Server,
|
|
3
|
-
routePartykitRequest,
|
|
4
|
-
type PartyServerOptions,
|
|
5
3
|
getServerByName,
|
|
4
|
+
routePartykitRequest,
|
|
6
5
|
type Connection,
|
|
7
6
|
type ConnectionContext,
|
|
7
|
+
type PartyServerOptions,
|
|
8
8
|
type WSMessage,
|
|
9
9
|
} from "partyserver";
|
|
10
10
|
|
|
11
11
|
import { parseCronExpression } from "cron-schedule";
|
|
12
12
|
import { nanoid } from "nanoid";
|
|
13
13
|
|
|
14
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
15
|
-
import { MCPClientManager } from "./mcp/client";
|
|
16
|
-
import {
|
|
17
|
-
DurableObjectOAuthClientProvider,
|
|
18
|
-
type AgentsOAuthProvider,
|
|
19
|
-
} from "./mcp/do-oauth-client-provider";
|
|
20
14
|
import type {
|
|
21
|
-
Tool,
|
|
22
|
-
Resource,
|
|
23
15
|
Prompt,
|
|
16
|
+
Resource,
|
|
17
|
+
ServerCapabilities,
|
|
18
|
+
Tool,
|
|
24
19
|
} from "@modelcontextprotocol/sdk/types.js";
|
|
20
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
21
|
+
import { MCPClientManager } from "./mcp/client";
|
|
22
|
+
import { DurableObjectOAuthClientProvider } from "./mcp/do-oauth-client-provider";
|
|
25
23
|
|
|
26
24
|
import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
27
25
|
import type { SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
28
26
|
|
|
29
27
|
import { camelCaseToKebabCase } from "./client";
|
|
30
28
|
|
|
31
|
-
export type { Connection,
|
|
29
|
+
export type { Connection, ConnectionContext, WSMessage } from "partyserver";
|
|
32
30
|
|
|
33
31
|
/**
|
|
34
32
|
* RPC request message from client
|
|
@@ -112,7 +110,6 @@ export type CallableMetadata = {
|
|
|
112
110
|
streaming?: boolean;
|
|
113
111
|
};
|
|
114
112
|
|
|
115
|
-
// biome-ignore lint/complexity/noBannedTypes: <explanation>
|
|
116
113
|
const callableMetadata = new Map<Function, CallableMetadata>();
|
|
117
114
|
|
|
118
115
|
/**
|
|
@@ -194,7 +191,12 @@ export type MCPServer = {
|
|
|
194
191
|
name: string;
|
|
195
192
|
server_url: string;
|
|
196
193
|
auth_url: string | null;
|
|
194
|
+
// This state is specifically about the temporary process of getting a token (if needed).
|
|
195
|
+
// Scope outside of that can't be relied upon because when the DO sleeps, there's no way
|
|
196
|
+
// to communicate a change to a non-ready state.
|
|
197
197
|
state: "authenticating" | "connecting" | "ready" | "discovering" | "failed";
|
|
198
|
+
instructions: string | null;
|
|
199
|
+
capabilities: ServerCapabilities | null;
|
|
198
200
|
};
|
|
199
201
|
|
|
200
202
|
/**
|
|
@@ -251,12 +253,12 @@ export function getCurrentAgent<
|
|
|
251
253
|
* @template State State type to store within the Agent
|
|
252
254
|
*/
|
|
253
255
|
export class Agent<Env, State = unknown> extends Server<Env> {
|
|
254
|
-
|
|
256
|
+
private _state = DEFAULT_STATE as State;
|
|
255
257
|
|
|
256
|
-
|
|
258
|
+
private _ParentClass: typeof Agent<Env, State> =
|
|
257
259
|
Object.getPrototypeOf(this).constructor;
|
|
258
260
|
|
|
259
|
-
mcp: MCPClientManager = new MCPClientManager(this
|
|
261
|
+
mcp: MCPClientManager = new MCPClientManager(this._ParentClass.name, "0.0.1");
|
|
260
262
|
|
|
261
263
|
/**
|
|
262
264
|
* Initial state for the Agent
|
|
@@ -268,9 +270,9 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
268
270
|
* Current state of the Agent
|
|
269
271
|
*/
|
|
270
272
|
get state(): State {
|
|
271
|
-
if (this
|
|
273
|
+
if (this._state !== DEFAULT_STATE) {
|
|
272
274
|
// state was previously set, and populated internal state
|
|
273
|
-
return this
|
|
275
|
+
return this._state;
|
|
274
276
|
}
|
|
275
277
|
// looks like this is the first time the state is being accessed
|
|
276
278
|
// check if the state was set in a previous life
|
|
@@ -290,8 +292,8 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
290
292
|
) {
|
|
291
293
|
const state = result[0]?.state as string; // could be null?
|
|
292
294
|
|
|
293
|
-
this
|
|
294
|
-
return this
|
|
295
|
+
this._state = JSON.parse(state);
|
|
296
|
+
return this._state;
|
|
295
297
|
}
|
|
296
298
|
|
|
297
299
|
// ok, this is the first time the state is being accessed
|
|
@@ -352,7 +354,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
352
354
|
`;
|
|
353
355
|
|
|
354
356
|
void this.ctx.blockConcurrencyWhile(async () => {
|
|
355
|
-
return this
|
|
357
|
+
return this._tryCatch(async () => {
|
|
356
358
|
// Create alarms table if it doesn't exist
|
|
357
359
|
this.sql`
|
|
358
360
|
CREATE TABLE IF NOT EXISTS cf_agents_schedules (
|
|
@@ -396,7 +398,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
396
398
|
this.broadcast(
|
|
397
399
|
JSON.stringify({
|
|
398
400
|
type: "cf_agent_mcp_servers",
|
|
399
|
-
mcp: this
|
|
401
|
+
mcp: this.getMcpServers(),
|
|
400
402
|
})
|
|
401
403
|
);
|
|
402
404
|
|
|
@@ -407,7 +409,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
407
409
|
});
|
|
408
410
|
}
|
|
409
411
|
|
|
410
|
-
return this
|
|
412
|
+
return this._tryCatch(() => _onRequest(request));
|
|
411
413
|
}
|
|
412
414
|
);
|
|
413
415
|
};
|
|
@@ -418,7 +420,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
418
420
|
{ agent: this, connection, request: undefined },
|
|
419
421
|
async () => {
|
|
420
422
|
if (typeof message !== "string") {
|
|
421
|
-
return this
|
|
423
|
+
return this._tryCatch(() => _onMessage(connection, message));
|
|
422
424
|
}
|
|
423
425
|
|
|
424
426
|
let parsed: unknown;
|
|
@@ -426,11 +428,11 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
426
428
|
parsed = JSON.parse(message);
|
|
427
429
|
} catch (e) {
|
|
428
430
|
// silently fail and let the onMessage handler handle it
|
|
429
|
-
return this
|
|
431
|
+
return this._tryCatch(() => _onMessage(connection, message));
|
|
430
432
|
}
|
|
431
433
|
|
|
432
434
|
if (isStateUpdateMessage(parsed)) {
|
|
433
|
-
this
|
|
435
|
+
this._setStateInternal(parsed.state as State, connection);
|
|
434
436
|
return;
|
|
435
437
|
}
|
|
436
438
|
|
|
@@ -444,11 +446,10 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
444
446
|
throw new Error(`Method ${method} does not exist`);
|
|
445
447
|
}
|
|
446
448
|
|
|
447
|
-
if (!this
|
|
449
|
+
if (!this._isCallable(method)) {
|
|
448
450
|
throw new Error(`Method ${method} is not callable`);
|
|
449
451
|
}
|
|
450
452
|
|
|
451
|
-
// biome-ignore lint/complexity/noBannedTypes: <explanation>
|
|
452
453
|
const metadata = callableMetadata.get(methodFn as Function);
|
|
453
454
|
|
|
454
455
|
// For streaming methods, pass a StreamingResponse object
|
|
@@ -483,7 +484,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
483
484
|
return;
|
|
484
485
|
}
|
|
485
486
|
|
|
486
|
-
return this
|
|
487
|
+
return this._tryCatch(() => _onMessage(connection, message));
|
|
487
488
|
}
|
|
488
489
|
);
|
|
489
490
|
};
|
|
@@ -508,11 +509,11 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
508
509
|
connection.send(
|
|
509
510
|
JSON.stringify({
|
|
510
511
|
type: "cf_agent_mcp_servers",
|
|
511
|
-
mcp: this
|
|
512
|
+
mcp: this.getMcpServers(),
|
|
512
513
|
})
|
|
513
514
|
);
|
|
514
515
|
|
|
515
|
-
return this
|
|
516
|
+
return this._tryCatch(() => _onConnect(connection, ctx));
|
|
516
517
|
}, 20);
|
|
517
518
|
}
|
|
518
519
|
);
|
|
@@ -527,39 +528,44 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
527
528
|
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
528
529
|
`;
|
|
529
530
|
|
|
530
|
-
// from DO storage, reconnect to all servers using our saved auth information
|
|
531
|
+
// from DO storage, reconnect to all servers not currently in the oauth flow using our saved auth information
|
|
531
532
|
await Promise.allSettled(
|
|
532
|
-
servers
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
533
|
+
servers
|
|
534
|
+
.filter((server) => server.auth_url === null)
|
|
535
|
+
.map((server) => {
|
|
536
|
+
return this._connectToMcpServerInternal(
|
|
537
|
+
server.name,
|
|
538
|
+
server.server_url,
|
|
539
|
+
server.callback_url,
|
|
540
|
+
server.server_options
|
|
541
|
+
? JSON.parse(server.server_options)
|
|
542
|
+
: undefined,
|
|
543
|
+
{
|
|
544
|
+
id: server.id,
|
|
545
|
+
oauthClientId: server.client_id ?? undefined,
|
|
546
|
+
}
|
|
547
|
+
);
|
|
548
|
+
})
|
|
546
549
|
);
|
|
547
550
|
|
|
548
551
|
this.broadcast(
|
|
549
552
|
JSON.stringify({
|
|
550
553
|
type: "cf_agent_mcp_servers",
|
|
551
|
-
mcp: this
|
|
554
|
+
mcp: this.getMcpServers(),
|
|
552
555
|
})
|
|
553
556
|
);
|
|
554
557
|
|
|
555
|
-
await this
|
|
558
|
+
await this._tryCatch(() => _onStart());
|
|
556
559
|
}
|
|
557
560
|
);
|
|
558
561
|
};
|
|
559
562
|
}
|
|
560
563
|
|
|
561
|
-
|
|
562
|
-
|
|
564
|
+
private _setStateInternal(
|
|
565
|
+
state: State,
|
|
566
|
+
source: Connection | "server" = "server"
|
|
567
|
+
) {
|
|
568
|
+
this._state = state;
|
|
563
569
|
this.sql`
|
|
564
570
|
INSERT OR REPLACE INTO cf_agents_state (id, state)
|
|
565
571
|
VALUES (${STATE_ROW_ID}, ${JSON.stringify(state)})
|
|
@@ -575,7 +581,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
575
581
|
}),
|
|
576
582
|
source !== "server" ? [source.id] : []
|
|
577
583
|
);
|
|
578
|
-
return this
|
|
584
|
+
return this._tryCatch(() => {
|
|
579
585
|
const { connection, request } = agentContext.getStore() || {};
|
|
580
586
|
return agentContext.run(
|
|
581
587
|
{ agent: this, connection, request },
|
|
@@ -591,7 +597,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
591
597
|
* @param state New state to set
|
|
592
598
|
*/
|
|
593
599
|
setState(state: State) {
|
|
594
|
-
this
|
|
600
|
+
this._setStateInternal(state, "server");
|
|
595
601
|
}
|
|
596
602
|
|
|
597
603
|
/**
|
|
@@ -616,7 +622,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
616
622
|
);
|
|
617
623
|
}
|
|
618
624
|
|
|
619
|
-
async
|
|
625
|
+
private async _tryCatch<T>(fn: () => T | Promise<T>) {
|
|
620
626
|
try {
|
|
621
627
|
return await fn();
|
|
622
628
|
} catch (e) {
|
|
@@ -690,7 +696,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
690
696
|
)}, 'scheduled', ${timestamp})
|
|
691
697
|
`;
|
|
692
698
|
|
|
693
|
-
await this
|
|
699
|
+
await this._scheduleNextAlarm();
|
|
694
700
|
|
|
695
701
|
return {
|
|
696
702
|
id,
|
|
@@ -711,7 +717,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
711
717
|
)}, 'delayed', ${when}, ${timestamp})
|
|
712
718
|
`;
|
|
713
719
|
|
|
714
|
-
await this
|
|
720
|
+
await this._scheduleNextAlarm();
|
|
715
721
|
|
|
716
722
|
return {
|
|
717
723
|
id,
|
|
@@ -733,7 +739,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
733
739
|
)}, 'cron', ${when}, ${timestamp})
|
|
734
740
|
`;
|
|
735
741
|
|
|
736
|
-
await this
|
|
742
|
+
await this._scheduleNextAlarm();
|
|
737
743
|
|
|
738
744
|
return {
|
|
739
745
|
id,
|
|
@@ -820,11 +826,11 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
820
826
|
async cancelSchedule(id: string): Promise<boolean> {
|
|
821
827
|
this.sql`DELETE FROM cf_agents_schedules WHERE id = ${id}`;
|
|
822
828
|
|
|
823
|
-
await this
|
|
829
|
+
await this._scheduleNextAlarm();
|
|
824
830
|
return true;
|
|
825
831
|
}
|
|
826
832
|
|
|
827
|
-
async
|
|
833
|
+
private async _scheduleNextAlarm() {
|
|
828
834
|
// Find the next schedule that needs to be executed
|
|
829
835
|
const result = this.sql`
|
|
830
836
|
SELECT time FROM cf_agents_schedules
|
|
@@ -894,7 +900,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
894
900
|
}
|
|
895
901
|
|
|
896
902
|
// Schedule the next alarm
|
|
897
|
-
await this
|
|
903
|
+
await this._scheduleNextAlarm();
|
|
898
904
|
};
|
|
899
905
|
|
|
900
906
|
/**
|
|
@@ -915,8 +921,7 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
915
921
|
* Get all methods marked as callable on this Agent
|
|
916
922
|
* @returns A map of method names to their metadata
|
|
917
923
|
*/
|
|
918
|
-
|
|
919
|
-
// biome-ignore lint/complexity/noBannedTypes: <explanation>
|
|
924
|
+
private _isCallable(method: string): boolean {
|
|
920
925
|
return callableMetadata.has(this[method as keyof this] as Function);
|
|
921
926
|
}
|
|
922
927
|
|
|
@@ -941,9 +946,9 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
941
946
|
};
|
|
942
947
|
}
|
|
943
948
|
): Promise<{ id: string; authUrl: string | undefined }> {
|
|
944
|
-
const callbackUrl = `${callbackHost}/${agentsPrefix}/${camelCaseToKebabCase(this
|
|
949
|
+
const callbackUrl = `${callbackHost}/${agentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;
|
|
945
950
|
|
|
946
|
-
const result = await this
|
|
951
|
+
const result = await this._connectToMcpServerInternal(
|
|
947
952
|
serverName,
|
|
948
953
|
url,
|
|
949
954
|
callbackUrl,
|
|
@@ -953,14 +958,14 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
953
958
|
this.broadcast(
|
|
954
959
|
JSON.stringify({
|
|
955
960
|
type: "cf_agent_mcp_servers",
|
|
956
|
-
mcp: this
|
|
961
|
+
mcp: this.getMcpServers(),
|
|
957
962
|
})
|
|
958
963
|
);
|
|
959
964
|
|
|
960
965
|
return result;
|
|
961
966
|
}
|
|
962
967
|
|
|
963
|
-
async
|
|
968
|
+
async _connectToMcpServerInternal(
|
|
964
969
|
serverName: string,
|
|
965
970
|
url: string,
|
|
966
971
|
callbackUrl: string,
|
|
@@ -1050,12 +1055,12 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1050
1055
|
this.broadcast(
|
|
1051
1056
|
JSON.stringify({
|
|
1052
1057
|
type: "cf_agent_mcp_servers",
|
|
1053
|
-
mcp: this
|
|
1058
|
+
mcp: this.getMcpServers(),
|
|
1054
1059
|
})
|
|
1055
1060
|
);
|
|
1056
1061
|
}
|
|
1057
1062
|
|
|
1058
|
-
|
|
1063
|
+
getMcpServers(): MCPServersState {
|
|
1059
1064
|
const mcpState: MCPServersState = {
|
|
1060
1065
|
servers: {},
|
|
1061
1066
|
tools: this.mcp.listTools(),
|
|
@@ -1073,6 +1078,9 @@ export class Agent<Env, State = unknown> extends Server<Env> {
|
|
|
1073
1078
|
server_url: server.server_url,
|
|
1074
1079
|
auth_url: server.auth_url,
|
|
1075
1080
|
state: this.mcp.mcpConnections[server.id].connectionState,
|
|
1081
|
+
instructions: this.mcp.mcpConnections[server.id].instructions ?? null,
|
|
1082
|
+
capabilities:
|
|
1083
|
+
this.mcp.mcpConnections[server.id].serverCapabilities ?? null,
|
|
1076
1084
|
};
|
|
1077
1085
|
}
|
|
1078
1086
|
|
|
@@ -1196,13 +1204,13 @@ export async function getAgentByName<Env, T extends Agent<Env>>(
|
|
|
1196
1204
|
* A wrapper for streaming responses in callable methods
|
|
1197
1205
|
*/
|
|
1198
1206
|
export class StreamingResponse {
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1207
|
+
private _connection: Connection;
|
|
1208
|
+
private _id: string;
|
|
1209
|
+
private _closed = false;
|
|
1202
1210
|
|
|
1203
1211
|
constructor(connection: Connection, id: string) {
|
|
1204
|
-
this
|
|
1205
|
-
this
|
|
1212
|
+
this._connection = connection;
|
|
1213
|
+
this._id = id;
|
|
1206
1214
|
}
|
|
1207
1215
|
|
|
1208
1216
|
/**
|
|
@@ -1210,17 +1218,17 @@ export class StreamingResponse {
|
|
|
1210
1218
|
* @param chunk The data to send
|
|
1211
1219
|
*/
|
|
1212
1220
|
send(chunk: unknown) {
|
|
1213
|
-
if (this
|
|
1221
|
+
if (this._closed) {
|
|
1214
1222
|
throw new Error("StreamingResponse is already closed");
|
|
1215
1223
|
}
|
|
1216
1224
|
const response: RPCResponse = {
|
|
1217
1225
|
type: "rpc",
|
|
1218
|
-
id: this
|
|
1226
|
+
id: this._id,
|
|
1219
1227
|
success: true,
|
|
1220
1228
|
result: chunk,
|
|
1221
1229
|
done: false,
|
|
1222
1230
|
};
|
|
1223
|
-
this
|
|
1231
|
+
this._connection.send(JSON.stringify(response));
|
|
1224
1232
|
}
|
|
1225
1233
|
|
|
1226
1234
|
/**
|
|
@@ -1228,17 +1236,17 @@ export class StreamingResponse {
|
|
|
1228
1236
|
* @param finalChunk Optional final chunk of data to send
|
|
1229
1237
|
*/
|
|
1230
1238
|
end(finalChunk?: unknown) {
|
|
1231
|
-
if (this
|
|
1239
|
+
if (this._closed) {
|
|
1232
1240
|
throw new Error("StreamingResponse is already closed");
|
|
1233
1241
|
}
|
|
1234
|
-
this
|
|
1242
|
+
this._closed = true;
|
|
1235
1243
|
const response: RPCResponse = {
|
|
1236
1244
|
type: "rpc",
|
|
1237
|
-
id: this
|
|
1245
|
+
id: this._id,
|
|
1238
1246
|
success: true,
|
|
1239
1247
|
result: finalChunk,
|
|
1240
1248
|
done: true,
|
|
1241
1249
|
};
|
|
1242
|
-
this
|
|
1250
|
+
this._connection.send(JSON.stringify(response));
|
|
1243
1251
|
}
|
|
1244
1252
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/sse-edge.ts","../src/mcp/client-connection.ts","../src/mcp/client.ts"],"sourcesContent":["import {\n SSEClientTransport,\n type SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\n\nexport class SSEEdgeClientTransport extends SSEClientTransport {\n private authProvider: OAuthClientProvider | undefined;\n /**\n * Creates a new EdgeSSEClientTransport, which overrides fetch to be compatible with the CF workers environment\n */\n constructor(url: URL, options: SSEClientTransportOptions) {\n const fetchOverride: typeof fetch = async (\n fetchUrl: RequestInfo | URL,\n fetchInit: RequestInit = {}\n ) => {\n // add auth headers\n const headers = await this.authHeaders();\n const workerOptions = {\n ...fetchInit,\n headers: {\n ...options.requestInit?.headers,\n ...fetchInit?.headers,\n ...headers,\n },\n };\n\n // Remove unsupported properties\n // biome-ignore lint/performance/noDelete: workaround for workers environment\n delete workerOptions.mode;\n\n // Call the original fetch with fixed options\n return (\n (options.eventSourceInit?.fetch?.(\n fetchUrl as URL | string,\n // @ts-expect-error Expects FetchLikeInit from EventSource but is compatible with RequestInit\n workerOptions\n ) as Promise<Response>) || fetch(fetchUrl, workerOptions)\n );\n };\n\n super(url, {\n ...options,\n eventSourceInit: {\n ...options.eventSourceInit,\n fetch: fetchOverride,\n },\n });\n this.authProvider = options.authProvider;\n }\n\n async authHeaders() {\n if (this.authProvider) {\n const tokens = await this.authProvider.tokens();\n if (tokens) {\n return {\n Authorization: `Bearer ${tokens.access_token}`,\n };\n }\n }\n }\n}\n","import { SSEEdgeClientTransport } from \"./sse-edge\";\n\nimport {\n ToolListChangedNotificationSchema,\n type ClientCapabilities,\n type Resource,\n type Tool,\n type Prompt,\n ResourceListChangedNotificationSchema,\n PromptListChangedNotificationSchema,\n type ListToolsResult,\n type ListResourcesResult,\n type ListPromptsResult,\n type ServerCapabilities,\n type ResourceTemplate,\n type ListResourceTemplatesResult,\n type Notification,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { AgentsOAuthProvider } from \"./do-oauth-client-provider\";\n\nexport class MCPClientConnection {\n client: Client;\n connectionState:\n | \"authenticating\"\n | \"connecting\"\n | \"ready\"\n | \"discovering\"\n | \"failed\" = \"connecting\";\n instructions?: string;\n tools: Tool[] = [];\n prompts: Prompt[] = [];\n resources: Resource[] = [];\n resourceTemplates: ResourceTemplate[] = [];\n serverCapabilities: ServerCapabilities | undefined;\n\n constructor(\n public url: URL,\n info: ConstructorParameters<typeof Client>[0],\n public options: {\n transport: SSEClientTransportOptions & {\n authProvider?: AgentsOAuthProvider;\n };\n client: ConstructorParameters<typeof Client>[1];\n } = { transport: {}, client: {} }\n ) {\n this.client = new Client(info, options.client);\n }\n\n /**\n * Initialize a client connection\n *\n * @param code Optional OAuth code to initialize the connection with if auth hasn't been initialized\n * @returns\n */\n async init(code?: string) {\n try {\n const transport = new SSEEdgeClientTransport(\n this.url,\n this.options.transport\n );\n\n if (code) {\n await transport.finishAuth(code);\n }\n\n await this.client.connect(transport);\n // biome-ignore lint/suspicious/noExplicitAny: allow for the error check here\n } catch (e: any) {\n if (e.toString().includes(\"Unauthorized\")) {\n // unauthorized, we should wait for the user to authenticate\n this.connectionState = \"authenticating\";\n return;\n }\n this.connectionState = \"failed\";\n throw e;\n }\n\n this.connectionState = \"discovering\";\n\n this.serverCapabilities = await this.client.getServerCapabilities();\n if (!this.serverCapabilities) {\n throw new Error(\"The MCP Server failed to return server capabilities\");\n }\n\n const [instructions, tools, resources, prompts, resourceTemplates] =\n await Promise.all([\n this.client.getInstructions(),\n this.registerTools(),\n this.registerResources(),\n this.registerPrompts(),\n this.registerResourceTemplates(),\n ]);\n\n this.instructions = instructions;\n this.tools = tools;\n this.resources = resources;\n this.prompts = prompts;\n this.resourceTemplates = resourceTemplates;\n\n this.connectionState = \"ready\";\n }\n\n /**\n * Notification handler registration\n */\n async registerTools(): Promise<Tool[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.tools) {\n return [];\n }\n\n if (this.serverCapabilities.tools.listChanged) {\n this.client.setNotificationHandler(\n ToolListChangedNotificationSchema,\n async (_notification) => {\n this.tools = await this.fetchTools();\n }\n );\n }\n\n return this.fetchTools();\n }\n\n async registerResources(): Promise<Resource[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.resources) {\n return [];\n }\n\n if (this.serverCapabilities.resources.listChanged) {\n this.client.setNotificationHandler(\n ResourceListChangedNotificationSchema,\n async (_notification) => {\n this.resources = await this.fetchResources();\n }\n );\n }\n\n return this.fetchResources();\n }\n\n async registerPrompts(): Promise<Prompt[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.prompts) {\n return [];\n }\n\n if (this.serverCapabilities.prompts.listChanged) {\n this.client.setNotificationHandler(\n PromptListChangedNotificationSchema,\n async (_notification) => {\n this.prompts = await this.fetchPrompts();\n }\n );\n }\n\n return this.fetchPrompts();\n }\n\n async registerResourceTemplates(): Promise<ResourceTemplate[]> {\n if (!this.serverCapabilities || !this.serverCapabilities.resources) {\n return [];\n }\n\n return this.fetchResourceTemplates();\n }\n\n async fetchTools() {\n let toolsAgg: Tool[] = [];\n let toolsResult: ListToolsResult = { tools: [] };\n do {\n toolsResult = await this.client\n .listTools({\n cursor: toolsResult.nextCursor,\n })\n .catch(capabilityErrorHandler({ tools: [] }, \"tools/list\"));\n toolsAgg = toolsAgg.concat(toolsResult.tools);\n } while (toolsResult.nextCursor);\n return toolsAgg;\n }\n\n async fetchResources() {\n let resourcesAgg: Resource[] = [];\n let resourcesResult: ListResourcesResult = { resources: [] };\n do {\n resourcesResult = await this.client\n .listResources({\n cursor: resourcesResult.nextCursor,\n })\n .catch(capabilityErrorHandler({ resources: [] }, \"resources/list\"));\n resourcesAgg = resourcesAgg.concat(resourcesResult.resources);\n } while (resourcesResult.nextCursor);\n return resourcesAgg;\n }\n\n async fetchPrompts() {\n let promptsAgg: Prompt[] = [];\n let promptsResult: ListPromptsResult = { prompts: [] };\n do {\n promptsResult = await this.client\n .listPrompts({\n cursor: promptsResult.nextCursor,\n })\n .catch(capabilityErrorHandler({ prompts: [] }, \"prompts/list\"));\n promptsAgg = promptsAgg.concat(promptsResult.prompts);\n } while (promptsResult.nextCursor);\n return promptsAgg;\n }\n\n async fetchResourceTemplates() {\n let templatesAgg: ResourceTemplate[] = [];\n let templatesResult: ListResourceTemplatesResult = {\n resourceTemplates: [],\n };\n do {\n templatesResult = await this.client\n .listResourceTemplates({\n cursor: templatesResult.nextCursor,\n })\n .catch(\n capabilityErrorHandler(\n { resourceTemplates: [] },\n \"resources/templates/list\"\n )\n );\n templatesAgg = templatesAgg.concat(templatesResult.resourceTemplates);\n } while (templatesResult.nextCursor);\n return templatesAgg;\n }\n}\n\nfunction capabilityErrorHandler<T>(empty: T, method: string) {\n return (e: { code: number }) => {\n // server is badly behaved and returning invalid capabilities. This commonly occurs for resource templates\n if (e.code === -32601) {\n console.error(\n `The server advertised support for the capability ${method.split(\"/\")[0]}, but returned \"Method not found\" for '${method}'.`\n );\n return empty;\n }\n throw e;\n };\n}\n","import { MCPClientConnection } from \"./client-connection\";\n\nimport type {\n CallToolRequest,\n CallToolResultSchema,\n CompatibilityCallToolResultSchema,\n ReadResourceRequest,\n GetPromptRequest,\n Tool,\n Resource,\n Prompt,\n ResourceTemplate,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport type { SSEClientTransportOptions } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport type { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport type { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport type { AgentsOAuthProvider } from \"./do-oauth-client-provider\";\nimport { jsonSchema, type ToolSet } from \"ai\";\nimport { nanoid } from \"nanoid\";\n\n/**\n * Utility class that aggregates multiple MCP clients into one\n */\nexport class MCPClientManager {\n public mcpConnections: Record<string, MCPClientConnection> = {};\n private callbackUrls: string[] = [];\n\n /**\n * @param name Name of the MCP client\n * @param version Version of the MCP Client\n * @param auth Auth paramters if being used to create a DurableObjectOAuthClientProvider\n */\n constructor(\n private name: string,\n private version: string\n ) {}\n\n /**\n * Connect to and register an MCP server\n *\n * @param transportConfig Transport config\n * @param clientConfig Client config\n * @param capabilities Client capabilities (i.e. if the client supports roots/sampling)\n */\n async connect(\n url: string,\n options: {\n // Allows you to reconnect to a server (in the case of a auth reconnect)\n reconnect?: {\n id: string;\n oauthClientId?: string;\n oauthCode?: string;\n };\n // we're overriding authProvider here because we want to be able to access the auth URL\n transport?: SSEClientTransportOptions & {\n authProvider?: AgentsOAuthProvider;\n };\n client?: ConstructorParameters<typeof Client>[1];\n } = {}\n ): Promise<{\n id: string;\n authUrl?: string;\n clientId?: string;\n }> {\n const id = options.reconnect?.id ?? nanoid(8);\n\n if (!options.transport?.authProvider) {\n console.warn(\n \"No authProvider provided in the transport options. This client will only support unauthenticated remote MCP Servers\"\n );\n } else {\n // reconnect with auth\n options.transport.authProvider.serverId = id;\n if (options.reconnect?.oauthClientId) {\n options.transport.authProvider.clientId =\n options.reconnect?.oauthClientId;\n }\n }\n\n this.mcpConnections[id] = new MCPClientConnection(\n new URL(url),\n {\n name: this.name,\n version: this.version,\n },\n {\n transport: options.transport ?? {},\n client: options.client ?? {},\n }\n );\n\n await this.mcpConnections[id].init(options.reconnect?.oauthCode);\n\n const authUrl = options.transport?.authProvider?.authUrl;\n if (authUrl && options.transport?.authProvider?.redirectUrl) {\n this.callbackUrls.push(\n options.transport.authProvider.redirectUrl.toString()\n );\n return {\n id,\n authUrl,\n clientId: options.transport?.authProvider?.clientId,\n };\n }\n\n return {\n id,\n };\n }\n\n isCallbackRequest(req: Request): boolean {\n return (\n req.method === \"GET\" &&\n !!this.callbackUrls.find((url) => {\n return req.url.startsWith(url);\n })\n );\n }\n\n async handleCallbackRequest(req: Request) {\n const url = new URL(req.url);\n const urlMatch = this.callbackUrls.find((url) => {\n return req.url.startsWith(url);\n });\n if (!urlMatch) {\n throw new Error(\n `No callback URI match found for the request url: ${req.url}. Was the request matched with \\`isCallbackRequest()\\`?`\n );\n }\n const code = url.searchParams.get(\"code\");\n const clientId = url.searchParams.get(\"state\");\n const urlParams = urlMatch.split(\"/\");\n const serverId = urlParams[urlParams.length - 1];\n if (!code) {\n throw new Error(\"Unauthorized: no code provided\");\n }\n if (!clientId) {\n throw new Error(\"Unauthorized: no state provided\");\n }\n\n if (this.mcpConnections[serverId] === undefined) {\n throw new Error(`Could not find serverId: ${serverId}`);\n }\n\n if (this.mcpConnections[serverId].connectionState !== \"authenticating\") {\n throw new Error(\n \"Failed to authenticate: the client isn't in the `authenticating` state\"\n );\n }\n\n const conn = this.mcpConnections[serverId];\n if (!conn.options.transport.authProvider) {\n throw new Error(\n \"Trying to finalize authentication for a server connection without an authProvider\"\n );\n }\n\n conn.options.transport.authProvider.clientId = clientId;\n conn.options.transport.authProvider.serverId = serverId;\n\n // reconnect to server with authorization\n const serverUrl = conn.url.toString();\n await this.connect(serverUrl, {\n reconnect: {\n id: serverId,\n oauthClientId: clientId,\n oauthCode: code,\n },\n ...conn.options,\n });\n\n if (this.mcpConnections[serverId].connectionState === \"authenticating\") {\n throw new Error(\"Failed to authenticate: client failed to initialize\");\n }\n\n return { serverId };\n }\n\n /**\n * @returns namespaced list of tools\n */\n listTools(): NamespacedData[\"tools\"] {\n return getNamespacedData(this.mcpConnections, \"tools\");\n }\n\n /**\n * @returns a set of tools that you can use with the AI SDK\n */\n unstable_getAITools(): ToolSet {\n return Object.fromEntries(\n getNamespacedData(this.mcpConnections, \"tools\").map((tool) => {\n return [\n `${tool.serverId}_${tool.name}`,\n {\n parameters: jsonSchema(tool.inputSchema),\n description: tool.description,\n execute: async (args) => {\n const result = await this.callTool({\n name: tool.name,\n arguments: args,\n serverId: tool.serverId,\n });\n if (result.isError) {\n // @ts-expect-error TODO we should fix this\n throw new Error(result.content[0].text);\n }\n return result;\n },\n },\n ];\n })\n );\n }\n\n /**\n * Closes all connections to MCP servers\n */\n async closeAllConnections() {\n return Promise.all(\n Object.values(this.mcpConnections).map(async (connection) => {\n await connection.client.close();\n })\n );\n }\n\n /**\n * Closes a connection to an MCP server\n * @param id The id of the connection to close\n */\n async closeConnection(id: string) {\n if (!this.mcpConnections[id]) {\n throw new Error(`Connection with id \"${id}\" does not exist.`);\n }\n await this.mcpConnections[id].client.close();\n }\n\n /**\n * @returns namespaced list of prompts\n */\n listPrompts(): NamespacedData[\"prompts\"] {\n return getNamespacedData(this.mcpConnections, \"prompts\");\n }\n\n /**\n * @returns namespaced list of tools\n */\n listResources(): NamespacedData[\"resources\"] {\n return getNamespacedData(this.mcpConnections, \"resources\");\n }\n\n /**\n * @returns namespaced list of resource templates\n */\n listResourceTemplates(): NamespacedData[\"resourceTemplates\"] {\n return getNamespacedData(this.mcpConnections, \"resourceTemplates\");\n }\n\n /**\n * Namespaced version of callTool\n */\n callTool(\n params: CallToolRequest[\"params\"] & { serverId: string },\n resultSchema?:\n | typeof CallToolResultSchema\n | typeof CompatibilityCallToolResultSchema,\n options?: RequestOptions\n ) {\n const unqualifiedName = params.name.replace(`${params.serverId}.`, \"\");\n return this.mcpConnections[params.serverId].client.callTool(\n {\n ...params,\n name: unqualifiedName,\n },\n resultSchema,\n options\n );\n }\n\n /**\n * Namespaced version of readResource\n */\n readResource(\n params: ReadResourceRequest[\"params\"] & { serverId: string },\n options: RequestOptions\n ) {\n return this.mcpConnections[params.serverId].client.readResource(\n params,\n options\n );\n }\n\n /**\n * Namespaced version of getPrompt\n */\n getPrompt(\n params: GetPromptRequest[\"params\"] & { serverId: string },\n options: RequestOptions\n ) {\n return this.mcpConnections[params.serverId].client.getPrompt(\n params,\n options\n );\n }\n}\n\ntype NamespacedData = {\n tools: (Tool & { serverId: string })[];\n prompts: (Prompt & { serverId: string })[];\n resources: (Resource & { serverId: string })[];\n resourceTemplates: (ResourceTemplate & { serverId: string })[];\n};\n\nexport function getNamespacedData<T extends keyof NamespacedData>(\n mcpClients: Record<string, MCPClientConnection>,\n type: T\n): NamespacedData[T] {\n const sets = Object.entries(mcpClients).map(([name, conn]) => {\n return { name, data: conn[type] };\n });\n\n const namespacedData = sets.flatMap(({ name: serverId, data }) => {\n return data.map((item) => {\n return {\n ...item,\n // we add a serverId so we can easily pull it out and send the tool call to the right server\n serverId,\n };\n });\n });\n\n return namespacedData as NamespacedData[T]; // Type assertion needed due to TS limitations with conditional return types\n}\n"],"mappings":"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","names":["url"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/do-oauth-client-provider.ts"],"sourcesContent":["import type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type {\n OAuthTokens,\n OAuthClientMetadata,\n OAuthClientInformation,\n OAuthClientInformationFull,\n} from \"@modelcontextprotocol/sdk/shared/auth.js\";\n\n// A slight extension to the standard OAuthClientProvider interface because `redirectToAuthorization` doesn't give us the interface we need\n// This allows us to track authentication for a specific server and associated dynamic client registration\nexport interface AgentsOAuthProvider extends OAuthClientProvider {\n authUrl: string | undefined;\n clientId: string | undefined;\n serverId: string | undefined;\n}\n\nexport class DurableObjectOAuthClientProvider implements AgentsOAuthProvider {\n private authUrl_: string | undefined;\n private serverId_: string | undefined;\n private clientId_: string | undefined;\n\n constructor(\n public storage: DurableObjectStorage,\n public clientName: string,\n public baseRedirectUrl: string\n ) {}\n\n get clientMetadata(): OAuthClientMetadata {\n return {\n redirect_uris: [this.redirectUrl],\n token_endpoint_auth_method: \"none\",\n grant_types: [\"authorization_code\", \"refresh_token\"],\n response_types: [\"code\"],\n client_name: this.clientName,\n client_uri: \"example.com\",\n };\n }\n\n get redirectUrl() {\n return `${this.baseRedirectUrl}/${this.serverId}`;\n }\n\n get clientId() {\n if (!this.clientId_) {\n throw new Error(\"Trying to access clientId before it was set\");\n }\n return this.clientId_;\n }\n\n set clientId(clientId_: string) {\n this.clientId_ = clientId_;\n }\n\n get serverId() {\n if (!this.serverId_) {\n throw new Error(\"Trying to access serverId before it was set\");\n }\n return this.serverId_;\n }\n\n set serverId(serverId_: string) {\n this.serverId_ = serverId_;\n }\n\n keyPrefix(clientId: string) {\n return `/${this.clientName}/${this.serverId}/${clientId}`;\n }\n\n clientInfoKey(clientId: string) {\n return `${this.keyPrefix(clientId)}/client_info/`;\n }\n\n async clientInformation(): Promise<OAuthClientInformation | undefined> {\n if (!this.clientId_) {\n return undefined;\n }\n return (\n (await this.storage.get<OAuthClientInformation>(\n this.clientInfoKey(this.clientId)\n )) ?? undefined\n );\n }\n\n async saveClientInformation(\n clientInformation: OAuthClientInformationFull\n ): Promise<void> {\n await this.storage.put(\n this.clientInfoKey(clientInformation.client_id),\n clientInformation\n );\n this.clientId = clientInformation.client_id;\n }\n\n tokenKey(clientId: string) {\n return `${this.keyPrefix(clientId)}/token`;\n }\n\n async tokens(): Promise<OAuthTokens | undefined> {\n if (!this.clientId_) {\n return undefined;\n }\n return (\n (await this.storage.get<OAuthTokens>(this.tokenKey(this.clientId))) ??\n undefined\n );\n }\n\n async saveTokens(tokens: OAuthTokens): Promise<void> {\n await this.storage.put(this.tokenKey(this.clientId), tokens);\n }\n\n get authUrl() {\n return this.authUrl_;\n }\n\n /**\n * Because this operates on the server side (but we need browser auth), we send this url back to the user\n * and require user interact to initiate the redirect flow\n */\n async redirectToAuthorization(authUrl: URL): Promise<void> {\n // We want to track the client ID in state here because the typescript SSE client sometimes does\n // a dynamic client registration AFTER generating this redirect URL.\n const client_id = authUrl.searchParams.get(\"client_id\");\n if (client_id) {\n authUrl.searchParams.append(\"state\", client_id);\n }\n this.authUrl_ = authUrl.toString();\n }\n\n codeVerifierKey(clientId: string) {\n return `${this.keyPrefix(clientId)}/code_verifier`;\n }\n\n async saveCodeVerifier(verifier: string): Promise<void> {\n await this.storage.put(this.codeVerifierKey(this.clientId), verifier);\n }\n\n async codeVerifier(): Promise<string> {\n const codeVerifier = await this.storage.get<string>(\n this.codeVerifierKey(this.clientId)\n );\n if (!codeVerifier) {\n throw new Error(\"No code verifier found\");\n }\n return codeVerifier;\n }\n}\n"],"mappings":";AAgBO,IAAM,mCAAN,MAAsE;AAAA,EAK3E,YACS,SACA,YACA,iBACP;AAHO;AACA;AACA;AAAA,EACN;AAAA,EAEH,IAAI,iBAAsC;AACxC,WAAO;AAAA,MACL,eAAe,CAAC,KAAK,WAAW;AAAA,MAChC,4BAA4B;AAAA,MAC5B,aAAa,CAAC,sBAAsB,eAAe;AAAA,MACnD,gBAAgB,CAAC,MAAM;AAAA,MACvB,aAAa,KAAK;AAAA,MAClB,YAAY;AAAA,IACd;AAAA,EACF;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,GAAG,KAAK,eAAe,IAAI,KAAK,QAAQ;AAAA,EACjD;AAAA,EAEA,IAAI,WAAW;AACb,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAS,WAAmB;AAC9B,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,IAAI,WAAW;AACb,QAAI,CAAC,KAAK,WAAW;AACnB,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAS,WAAmB;AAC9B,SAAK,YAAY;AAAA,EACnB;AAAA,EAEA,UAAU,UAAkB;AAC1B,WAAO,IAAI,KAAK,UAAU,IAAI,KAAK,QAAQ,IAAI,QAAQ;AAAA,EACzD;AAAA,EAEA,cAAc,UAAkB;AAC9B,WAAO,GAAG,KAAK,UAAU,QAAQ,CAAC;AAAA,EACpC;AAAA,EAEA,MAAM,oBAAiE;AACrE,QAAI,CAAC,KAAK,WAAW;AACnB,aAAO;AAAA,IACT;AACA,WACG,MAAM,KAAK,QAAQ;AAAA,MAClB,KAAK,cAAc,KAAK,QAAQ;AAAA,IAClC,KAAM;AAAA,EAEV;AAAA,EAEA,MAAM,sBACJ,mBACe;AACf,UAAM,KAAK,QAAQ;AAAA,MACjB,KAAK,cAAc,kBAAkB,SAAS;AAAA,MAC9C;AAAA,IACF;AACA,SAAK,WAAW,kBAAkB;AAAA,EACpC;AAAA,EAEA,SAAS,UAAkB;AACzB,WAAO,GAAG,KAAK,UAAU,QAAQ,CAAC;AAAA,EACpC;AAAA,EAEA,MAAM,SAA2C;AAC/C,QAAI,CAAC,KAAK,WAAW;AACnB,aAAO;AAAA,IACT;AACA,WACG,MAAM,KAAK,QAAQ,IAAiB,KAAK,SAAS,KAAK,QAAQ,CAAC,KACjE;AAAA,EAEJ;AAAA,EAEA,MAAM,WAAW,QAAoC;AACnD,UAAM,KAAK,QAAQ,IAAI,KAAK,SAAS,KAAK,QAAQ,GAAG,MAAM;AAAA,EAC7D;AAAA,EAEA,IAAI,UAAU;AACZ,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,wBAAwB,SAA6B;AAGzD,UAAM,YAAY,QAAQ,aAAa,IAAI,WAAW;AACtD,QAAI,WAAW;AACb,cAAQ,aAAa,OAAO,SAAS,SAAS;AAAA,IAChD;AACA,SAAK,WAAW,QAAQ,SAAS;AAAA,EACnC;AAAA,EAEA,gBAAgB,UAAkB;AAChC,WAAO,GAAG,KAAK,UAAU,QAAQ,CAAC;AAAA,EACpC;AAAA,EAEA,MAAM,iBAAiB,UAAiC;AACtD,UAAM,KAAK,QAAQ,IAAI,KAAK,gBAAgB,KAAK,QAAQ,GAAG,QAAQ;AAAA,EACtE;AAAA,EAEA,MAAM,eAAgC;AACpC,UAAM,eAAe,MAAM,KAAK,QAAQ;AAAA,MACtC,KAAK,gBAAgB,KAAK,QAAQ;AAAA,IACpC;AACA,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AACA,WAAO;AAAA,EACT;AACF;","names":[]}
|
package/dist/chunk-HMLY7DHA.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
var __typeError = (msg) => {
|
|
2
|
-
throw TypeError(msg);
|
|
3
|
-
};
|
|
4
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
-
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
-
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
|
-
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
9
|
-
|
|
10
|
-
export {
|
|
11
|
-
__privateGet,
|
|
12
|
-
__privateAdd,
|
|
13
|
-
__privateSet,
|
|
14
|
-
__privateMethod
|
|
15
|
-
};
|
|
16
|
-
//# sourceMappingURL=chunk-HMLY7DHA.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["import {\n PartySocket,\n type PartySocketOptions,\n type PartyFetchOptions,\n} from \"partysocket\";\nimport type { RPCRequest, RPCResponse } from \"./\";\n\n/**\n * Options for creating an AgentClient\n */\nexport type AgentClientOptions<State = unknown> = Omit<\n PartySocketOptions,\n \"party\" | \"room\"\n> & {\n /** Name of the agent to connect to */\n agent: string;\n /** Name of the specific Agent instance */\n name?: string;\n /** Called when the Agent's state is updated */\n onStateUpdate?: (state: State, source: \"server\" | \"client\") => void;\n};\n\n/**\n * Options for streaming RPC calls\n */\nexport type StreamOptions = {\n /** Called when a chunk of data is received */\n onChunk?: (chunk: unknown) => void;\n /** Called when the stream ends */\n onDone?: (finalChunk: unknown) => void;\n /** Called when an error occurs */\n onError?: (error: string) => void;\n};\n\n/**\n * Options for the agentFetch function\n */\nexport type AgentClientFetchOptions = Omit<\n PartyFetchOptions,\n \"party\" | \"room\"\n> & {\n /** Name of the agent to connect to */\n agent: string;\n /** Name of the specific Agent instance */\n name?: string;\n};\n\n/**\n * Convert a camelCase string to a kebab-case string\n * @param str The string to convert\n * @returns The kebab-case string\n */\nexport function camelCaseToKebabCase(str: string): string {\n // If string is all uppercase, convert to lowercase\n if (str === str.toUpperCase() && str !== str.toLowerCase()) {\n return str.toLowerCase().replace(/_/g, \"-\");\n }\n\n // Otherwise handle camelCase to kebab-case\n let kebabified = str.replace(\n /[A-Z]/g,\n (letter) => `-${letter.toLowerCase()}`\n );\n kebabified = kebabified.startsWith(\"-\") ? kebabified.slice(1) : kebabified;\n // Convert any remaining underscores to hyphens and remove trailing -'s\n return kebabified.replace(/_/g, \"-\").replace(/-$/, \"\");\n}\n\n/**\n * WebSocket client for connecting to an Agent\n */\nexport class AgentClient<State = unknown> extends PartySocket {\n /**\n * @deprecated Use agentFetch instead\n */\n static fetch(_opts: PartyFetchOptions): Promise<Response> {\n throw new Error(\n \"AgentClient.fetch is not implemented, use agentFetch instead\"\n );\n }\n agent: string;\n name: string;\n #options: AgentClientOptions<State>;\n #pendingCalls = new Map<\n string,\n {\n resolve: (value: unknown) => void;\n reject: (error: Error) => void;\n stream?: StreamOptions;\n type?: unknown;\n }\n >();\n\n constructor(options: AgentClientOptions<State>) {\n const agentNamespace = camelCaseToKebabCase(options.agent);\n super({\n prefix: \"agents\",\n party: agentNamespace,\n room: options.name || \"default\",\n ...options,\n });\n this.agent = agentNamespace;\n this.name = options.name || \"default\";\n this.#options = options;\n\n this.addEventListener(\"message\", (event) => {\n if (typeof event.data === \"string\") {\n let parsedMessage: Record<string, unknown>;\n try {\n parsedMessage = JSON.parse(event.data);\n } catch (error) {\n // silently ignore invalid messages for now\n // TODO: log errors with log levels\n return;\n }\n if (parsedMessage.type === \"cf_agent_state\") {\n this.#options.onStateUpdate?.(parsedMessage.state as State, \"server\");\n return;\n }\n if (parsedMessage.type === \"rpc\") {\n const response = parsedMessage as RPCResponse;\n const pending = this.#pendingCalls.get(response.id);\n if (!pending) return;\n\n if (!response.success) {\n pending.reject(new Error(response.error));\n this.#pendingCalls.delete(response.id);\n pending.stream?.onError?.(response.error);\n return;\n }\n\n // Handle streaming responses\n if (\"done\" in response) {\n if (response.done) {\n pending.resolve(response.result);\n this.#pendingCalls.delete(response.id);\n pending.stream?.onDone?.(response.result);\n } else {\n pending.stream?.onChunk?.(response.result);\n }\n } else {\n // Non-streaming response\n pending.resolve(response.result);\n this.#pendingCalls.delete(response.id);\n }\n }\n }\n });\n }\n\n setState(state: State) {\n this.send(JSON.stringify({ type: \"cf_agent_state\", state }));\n this.#options.onStateUpdate?.(state, \"client\");\n }\n\n /**\n * Call a method on the Agent\n * @param method Name of the method to call\n * @param args Arguments to pass to the method\n * @param streamOptions Options for handling streaming responses\n * @returns Promise that resolves with the method's return value\n */\n async call<T = unknown>(\n method: string,\n args: unknown[] = [],\n streamOptions?: StreamOptions\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const id = Math.random().toString(36).slice(2);\n this.#pendingCalls.set(id, {\n resolve: (value: unknown) => resolve(value as T),\n reject,\n stream: streamOptions,\n type: null as T,\n });\n\n const request: RPCRequest = {\n type: \"rpc\",\n id,\n method,\n args,\n };\n\n this.send(JSON.stringify(request));\n });\n }\n}\n\n/**\n * Make an HTTP request to an Agent\n * @param opts Connection options\n * @param init Request initialization options\n * @returns Promise resolving to a Response\n */\nexport function agentFetch(opts: AgentClientFetchOptions, init?: RequestInit) {\n const agentNamespace = camelCaseToKebabCase(opts.agent);\n\n return PartySocket.fetch(\n {\n prefix: \"agents\",\n party: agentNamespace,\n room: opts.name || \"default\",\n ...opts,\n },\n init\n );\n}\n"],"mappings":"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","names":[]}
|