agents 0.0.0-7d9b939 → 0.0.0-7f4616c
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 +103 -5
- package/dist/ai-chat-agent.d.ts +16 -17
- package/dist/ai-chat-agent.js +532 -351
- package/dist/ai-chat-agent.js.map +1 -1
- package/dist/ai-chat-v5-migration-gdyLiTd8.js +155 -0
- package/dist/ai-chat-v5-migration-gdyLiTd8.js.map +1 -0
- package/dist/ai-chat-v5-migration.d.ts +7 -4
- package/dist/ai-chat-v5-migration.js +3 -19
- package/dist/ai-react.d.ts +20 -23
- package/dist/ai-react.js +259 -304
- package/dist/ai-react.js.map +1 -1
- package/dist/ai-types-BWW4umHY.d.ts +95 -0
- package/dist/ai-types-UZlfLOYP.js +20 -0
- package/dist/ai-types-UZlfLOYP.js.map +1 -0
- package/dist/ai-types.d.ts +6 -91
- package/dist/ai-types.js +3 -7
- package/dist/client-CZBVDDoO.js +786 -0
- package/dist/client-CZBVDDoO.js.map +1 -0
- package/dist/client-CmMi85Sj.d.ts +104 -0
- package/dist/client-CrWcaPgn.d.ts +5313 -0
- package/dist/client-DjR-lC16.js +117 -0
- package/dist/client-DjR-lC16.js.map +1 -0
- package/dist/client.d.ts +11 -92
- package/dist/client.js +4 -12
- package/dist/codemode/ai.d.ts +27 -0
- package/dist/codemode/ai.js +151 -0
- package/dist/codemode/ai.js.map +1 -0
- package/dist/do-oauth-client-provider-B2jr6UNq.js +93 -0
- package/dist/do-oauth-client-provider-B2jr6UNq.js.map +1 -0
- package/dist/do-oauth-client-provider-CCwGwnrA.d.ts +55 -0
- package/dist/index-DpH9o0ao.d.ts +568 -0
- package/dist/index-W4JUkafc.d.ts +54 -0
- package/dist/index.d.ts +56 -550
- package/dist/index.js +7 -31
- package/dist/mcp/client.d.ts +4 -11
- package/dist/mcp/client.js +3 -9
- package/dist/mcp/do-oauth-client-provider.d.ts +2 -42
- package/dist/mcp/do-oauth-client-provider.js +3 -7
- package/dist/mcp/index.d.ts +72 -94
- package/dist/mcp/index.js +831 -1013
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/x402.d.ts +34 -0
- package/dist/mcp/x402.js +194 -0
- package/dist/mcp/x402.js.map +1 -0
- package/dist/mcp-BEwaCsxO.d.ts +61 -0
- package/dist/observability/index.d.ts +3 -46
- package/dist/observability/index.js +7 -11
- package/dist/react-LfPKBVtU.d.ts +113 -0
- package/dist/react.d.ts +10 -123
- package/dist/react.js +183 -112
- package/dist/react.js.map +1 -1
- package/dist/schedule.d.ts +13 -10
- package/dist/schedule.js +43 -31
- package/dist/schedule.js.map +1 -1
- package/dist/serializable-gtr9YMhp.d.ts +34 -0
- package/dist/serializable.d.ts +7 -32
- package/dist/serializable.js +1 -1
- package/dist/src-L3cHuAag.js +1231 -0
- package/dist/src-L3cHuAag.js.map +1 -0
- package/package.json +36 -11
- package/src/index.ts +289 -69
- package/dist/ai-chat-v5-migration.js.map +0 -1
- package/dist/ai-types.js.map +0 -1
- package/dist/chunk-AVYJQSLW.js +0 -17
- package/dist/chunk-AVYJQSLW.js.map +0 -1
- package/dist/chunk-LL2AFX7V.js +0 -109
- package/dist/chunk-LL2AFX7V.js.map +0 -1
- package/dist/chunk-MH46VMM4.js +0 -612
- package/dist/chunk-MH46VMM4.js.map +0 -1
- package/dist/chunk-QEVM4BVL.js +0 -116
- package/dist/chunk-QEVM4BVL.js.map +0 -1
- package/dist/chunk-UJVEAURM.js +0 -150
- package/dist/chunk-UJVEAURM.js.map +0 -1
- package/dist/chunk-YDUDMOL6.js +0 -1296
- package/dist/chunk-YDUDMOL6.js.map +0 -1
- package/dist/client-CvaJdLQA.d.ts +0 -5015
- package/dist/client.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/mcp/client.js.map +0 -1
- package/dist/mcp/do-oauth-client-provider.js.map +0 -1
- package/dist/observability/index.js.map +0 -1
- package/dist/serializable.js.map +0 -1
package/src/index.ts
CHANGED
|
@@ -22,10 +22,12 @@ 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";
|
|
29
31
|
import { MessageType } from "./ai-types";
|
|
30
32
|
|
|
31
33
|
export type { Connection, ConnectionContext, WSMessage } from "partyserver";
|
|
@@ -197,6 +199,8 @@ function getNextCronTime(cron: string) {
|
|
|
197
199
|
return interval.getNextDate();
|
|
198
200
|
}
|
|
199
201
|
|
|
202
|
+
export type { TransportType } from "./mcp/types";
|
|
203
|
+
|
|
200
204
|
/**
|
|
201
205
|
* MCP Server state update message from server -> Client
|
|
202
206
|
*/
|
|
@@ -221,7 +225,7 @@ export type MCPServer = {
|
|
|
221
225
|
// This state is specifically about the temporary process of getting a token (if needed).
|
|
222
226
|
// Scope outside of that can't be relied upon because when the DO sleeps, there's no way
|
|
223
227
|
// to communicate a change to a non-ready state.
|
|
224
|
-
state:
|
|
228
|
+
state: MCPConnectionState;
|
|
225
229
|
instructions: string | null;
|
|
226
230
|
capabilities: ServerCapabilities | null;
|
|
227
231
|
};
|
|
@@ -314,11 +318,15 @@ export class Agent<
|
|
|
314
318
|
Props extends Record<string, unknown> = Record<string, unknown>
|
|
315
319
|
> extends Server<Env, Props> {
|
|
316
320
|
private _state = DEFAULT_STATE as State;
|
|
321
|
+
private _disposables = new DisposableStore();
|
|
317
322
|
|
|
318
323
|
private _ParentClass: typeof Agent<Env, State> =
|
|
319
324
|
Object.getPrototypeOf(this).constructor;
|
|
320
325
|
|
|
321
|
-
mcp: MCPClientManager = new MCPClientManager(
|
|
326
|
+
readonly mcp: MCPClientManager = new MCPClientManager(
|
|
327
|
+
this._ParentClass.name,
|
|
328
|
+
"0.0.1"
|
|
329
|
+
);
|
|
322
330
|
|
|
323
331
|
/**
|
|
324
332
|
* Initial state for the Agent
|
|
@@ -411,8 +419,25 @@ export class Agent<
|
|
|
411
419
|
constructor(ctx: AgentContext, env: Env) {
|
|
412
420
|
super(ctx, env);
|
|
413
421
|
|
|
414
|
-
|
|
415
|
-
|
|
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
|
+
);
|
|
416
441
|
|
|
417
442
|
this.sql`
|
|
418
443
|
CREATE TABLE IF NOT EXISTS cf_agents_state (
|
|
@@ -468,22 +493,11 @@ export class Agent<
|
|
|
468
493
|
return agentContext.run(
|
|
469
494
|
{ agent: this, connection: undefined, request, email: undefined },
|
|
470
495
|
async () => {
|
|
471
|
-
if
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
JSON.stringify({
|
|
477
|
-
mcp: this.getMcpServers(),
|
|
478
|
-
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
479
|
-
})
|
|
480
|
-
);
|
|
481
|
-
|
|
482
|
-
// We probably should let the user configure this response/redirect, but this is fine for now.
|
|
483
|
-
return new Response("<script>window.close();</script>", {
|
|
484
|
-
headers: { "content-type": "text/html" },
|
|
485
|
-
status: 200
|
|
486
|
-
});
|
|
496
|
+
// Check if this is an OAuth callback and restore state if needed
|
|
497
|
+
const callbackResult =
|
|
498
|
+
await this._handlePotentialOAuthCallback(request);
|
|
499
|
+
if (callbackResult) {
|
|
500
|
+
return callbackResult;
|
|
487
501
|
}
|
|
488
502
|
|
|
489
503
|
return this._tryCatch(() => _onRequest(request));
|
|
@@ -636,15 +650,20 @@ export class Agent<
|
|
|
636
650
|
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options FROM cf_agents_mcp_servers;
|
|
637
651
|
`;
|
|
638
652
|
|
|
639
|
-
this.
|
|
640
|
-
JSON.stringify({
|
|
641
|
-
mcp: this.getMcpServers(),
|
|
642
|
-
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
643
|
-
})
|
|
644
|
-
);
|
|
653
|
+
this.broadcastMcpServers();
|
|
645
654
|
|
|
646
655
|
// from DO storage, reconnect to all servers not currently in the oauth flow using our saved auth information
|
|
647
656
|
if (servers && Array.isArray(servers) && servers.length > 0) {
|
|
657
|
+
// Restore callback URLs for OAuth-enabled servers
|
|
658
|
+
servers.forEach((server) => {
|
|
659
|
+
if (server.callback_url) {
|
|
660
|
+
// Register the full redirect URL including serverId to avoid ambiguous matches
|
|
661
|
+
this.mcp.registerCallbackUrl(
|
|
662
|
+
`${server.callback_url}/${server.id}`
|
|
663
|
+
);
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
|
|
648
667
|
servers.forEach((server) => {
|
|
649
668
|
this._connectToMcpServerInternal(
|
|
650
669
|
server.name,
|
|
@@ -660,12 +679,7 @@ export class Agent<
|
|
|
660
679
|
)
|
|
661
680
|
.then(() => {
|
|
662
681
|
// Broadcast updated MCP servers state after each server connects
|
|
663
|
-
this.
|
|
664
|
-
JSON.stringify({
|
|
665
|
-
mcp: this.getMcpServers(),
|
|
666
|
-
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
667
|
-
})
|
|
668
|
-
);
|
|
682
|
+
this.broadcastMcpServers();
|
|
669
683
|
})
|
|
670
684
|
.catch((error) => {
|
|
671
685
|
console.error(
|
|
@@ -673,12 +687,7 @@ export class Agent<
|
|
|
673
687
|
error
|
|
674
688
|
);
|
|
675
689
|
// Still broadcast even if connection fails, so clients know about the failure
|
|
676
|
-
this.
|
|
677
|
-
JSON.stringify({
|
|
678
|
-
mcp: this.getMcpServers(),
|
|
679
|
-
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
680
|
-
})
|
|
681
|
-
);
|
|
690
|
+
this.broadcastMcpServers();
|
|
682
691
|
});
|
|
683
692
|
});
|
|
684
693
|
}
|
|
@@ -1371,6 +1380,8 @@ export class Agent<
|
|
|
1371
1380
|
// delete all alarms
|
|
1372
1381
|
await this.ctx.storage.deleteAlarm();
|
|
1373
1382
|
await this.ctx.storage.deleteAll();
|
|
1383
|
+
this._disposables.dispose();
|
|
1384
|
+
await this.mcp.dispose?.();
|
|
1374
1385
|
this.ctx.abort("destroyed"); // enforce that the agent is evicted
|
|
1375
1386
|
|
|
1376
1387
|
this.observability?.emit(
|
|
@@ -1396,57 +1407,220 @@ export class Agent<
|
|
|
1396
1407
|
/**
|
|
1397
1408
|
* Connect to a new MCP Server
|
|
1398
1409
|
*
|
|
1410
|
+
* @param serverName Name of the MCP server
|
|
1399
1411
|
* @param url MCP Server SSE URL
|
|
1400
|
-
* @param callbackHost Base host for the agent, used for the redirect URI.
|
|
1412
|
+
* @param callbackHost Base host for the agent, used for the redirect URI. If not provided, will be derived from the current request.
|
|
1401
1413
|
* @param agentsPrefix agents routing prefix if not using `agents`
|
|
1402
|
-
* @param options MCP client and transport
|
|
1414
|
+
* @param options MCP client and transport options
|
|
1403
1415
|
* @returns authUrl
|
|
1404
1416
|
*/
|
|
1405
1417
|
async addMcpServer(
|
|
1406
1418
|
serverName: string,
|
|
1407
1419
|
url: string,
|
|
1408
|
-
callbackHost
|
|
1420
|
+
callbackHost?: string,
|
|
1409
1421
|
agentsPrefix = "agents",
|
|
1410
1422
|
options?: {
|
|
1411
1423
|
client?: ConstructorParameters<typeof Client>[1];
|
|
1412
1424
|
transport?: {
|
|
1413
|
-
headers
|
|
1425
|
+
headers?: HeadersInit;
|
|
1426
|
+
type?: TransportType;
|
|
1414
1427
|
};
|
|
1415
1428
|
}
|
|
1416
1429
|
): Promise<{ id: string; authUrl: string | undefined }> {
|
|
1417
|
-
|
|
1430
|
+
// If callbackHost is not provided, derive it from the current request
|
|
1431
|
+
let resolvedCallbackHost = callbackHost;
|
|
1432
|
+
if (!resolvedCallbackHost) {
|
|
1433
|
+
const { request } = getCurrentAgent();
|
|
1434
|
+
if (!request) {
|
|
1435
|
+
throw new Error(
|
|
1436
|
+
"callbackHost is required when not called within a request context"
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1418
1439
|
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
)
|
|
1440
|
+
// Extract the origin from the request
|
|
1441
|
+
const requestUrl = new URL(request.url);
|
|
1442
|
+
resolvedCallbackHost = `${requestUrl.protocol}//${requestUrl.host}`;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1445
|
+
const callbackUrl = `${resolvedCallbackHost}/${agentsPrefix}/${camelCaseToKebabCase(this._ParentClass.name)}/${this.name}/callback`;
|
|
1446
|
+
|
|
1447
|
+
// Generate a serverId upfront
|
|
1448
|
+
const serverId = nanoid(8);
|
|
1449
|
+
|
|
1450
|
+
// Persist to database BEFORE starting OAuth flow to survive DO hibernation
|
|
1425
1451
|
this.sql`
|
|
1426
|
-
INSERT
|
|
1427
|
-
OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)
|
|
1452
|
+
INSERT OR REPLACE INTO cf_agents_mcp_servers (id, name, server_url, client_id, auth_url, callback_url, server_options)
|
|
1428
1453
|
VALUES (
|
|
1429
|
-
${
|
|
1454
|
+
${serverId},
|
|
1430
1455
|
${serverName},
|
|
1431
1456
|
${url},
|
|
1432
|
-
${
|
|
1433
|
-
${
|
|
1457
|
+
${null},
|
|
1458
|
+
${null},
|
|
1434
1459
|
${callbackUrl},
|
|
1435
1460
|
${options ? JSON.stringify(options) : null}
|
|
1436
1461
|
);
|
|
1437
1462
|
`;
|
|
1438
1463
|
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1464
|
+
// _connectToMcpServerInternal will call mcp.connect which registers the callback URL
|
|
1465
|
+
const result = await this._connectToMcpServerInternal(
|
|
1466
|
+
serverName,
|
|
1467
|
+
url,
|
|
1468
|
+
callbackUrl,
|
|
1469
|
+
options,
|
|
1470
|
+
{ id: serverId }
|
|
1444
1471
|
);
|
|
1445
1472
|
|
|
1473
|
+
// Update database with OAuth client info if auth is required
|
|
1474
|
+
if (result.clientId || result.authUrl) {
|
|
1475
|
+
this.sql`
|
|
1476
|
+
UPDATE cf_agents_mcp_servers
|
|
1477
|
+
SET client_id = ${result.clientId ?? null}, auth_url = ${result.authUrl ?? null}
|
|
1478
|
+
WHERE id = ${serverId}
|
|
1479
|
+
`;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
this.broadcastMcpServers();
|
|
1483
|
+
|
|
1446
1484
|
return result;
|
|
1447
1485
|
}
|
|
1448
1486
|
|
|
1449
|
-
|
|
1487
|
+
/**
|
|
1488
|
+
* Handle potential OAuth callback requests after DO hibernation.
|
|
1489
|
+
* Detects OAuth callbacks, restores state from database, and processes the callback.
|
|
1490
|
+
* Returns a Response if this was an OAuth callback, otherwise returns undefined.
|
|
1491
|
+
*/
|
|
1492
|
+
private async _handlePotentialOAuthCallback(
|
|
1493
|
+
request: Request
|
|
1494
|
+
): Promise<Response | undefined> {
|
|
1495
|
+
// Quick check: must be GET with callback pattern and code parameter
|
|
1496
|
+
if (request.method !== "GET") {
|
|
1497
|
+
return undefined;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
const url = new URL(request.url);
|
|
1501
|
+
const hasCallbackPattern =
|
|
1502
|
+
url.pathname.includes("/callback/") && url.searchParams.has("code");
|
|
1503
|
+
|
|
1504
|
+
if (!hasCallbackPattern) {
|
|
1505
|
+
return undefined;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// Extract serverId from callback URL
|
|
1509
|
+
const pathParts = url.pathname.split("/");
|
|
1510
|
+
const callbackIndex = pathParts.indexOf("callback");
|
|
1511
|
+
const serverId = callbackIndex !== -1 ? pathParts[callbackIndex + 1] : null;
|
|
1512
|
+
|
|
1513
|
+
if (!serverId) {
|
|
1514
|
+
return new Response("Invalid callback URL: missing serverId", {
|
|
1515
|
+
status: 400
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
// Check if callback is already registered AND connection exists (not hibernated)
|
|
1520
|
+
if (
|
|
1521
|
+
this.mcp.isCallbackRequest(request) &&
|
|
1522
|
+
this.mcp.mcpConnections[serverId]
|
|
1523
|
+
) {
|
|
1524
|
+
// State already restored, handle normally
|
|
1525
|
+
return this._processOAuthCallback(request);
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
// Need to restore from database after hibernation
|
|
1529
|
+
try {
|
|
1530
|
+
const server = this.sql<MCPServerRow>`
|
|
1531
|
+
SELECT id, name, server_url, client_id, auth_url, callback_url, server_options
|
|
1532
|
+
FROM cf_agents_mcp_servers
|
|
1533
|
+
WHERE id = ${serverId}
|
|
1534
|
+
`.find((s) => s.id === serverId);
|
|
1535
|
+
|
|
1536
|
+
if (!server) {
|
|
1537
|
+
return new Response(
|
|
1538
|
+
`OAuth callback failed: Server ${serverId} not found in database`,
|
|
1539
|
+
{ status: 404 }
|
|
1540
|
+
);
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
// Register callback URL (restores it after hibernation)
|
|
1544
|
+
if (!server.callback_url) {
|
|
1545
|
+
return new Response(
|
|
1546
|
+
`OAuth callback failed: No callback URL stored for server ${serverId}`,
|
|
1547
|
+
{ status: 500 }
|
|
1548
|
+
);
|
|
1549
|
+
}
|
|
1550
|
+
|
|
1551
|
+
this.mcp.registerCallbackUrl(`${server.callback_url}/${server.id}`);
|
|
1552
|
+
|
|
1553
|
+
// Restore connection if not in memory
|
|
1554
|
+
if (!this.mcp.mcpConnections[serverId]) {
|
|
1555
|
+
let parsedOptions:
|
|
1556
|
+
| {
|
|
1557
|
+
client?: ConstructorParameters<typeof Client>[1];
|
|
1558
|
+
transport?: {
|
|
1559
|
+
headers?: HeadersInit;
|
|
1560
|
+
type?: TransportType;
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
| undefined;
|
|
1564
|
+
try {
|
|
1565
|
+
parsedOptions = server.server_options
|
|
1566
|
+
? JSON.parse(server.server_options)
|
|
1567
|
+
: undefined;
|
|
1568
|
+
} catch {
|
|
1569
|
+
return new Response(
|
|
1570
|
+
`OAuth callback failed: Invalid server options in database for ${serverId}`,
|
|
1571
|
+
{ status: 500 }
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
await this._connectToMcpServerInternal(
|
|
1576
|
+
server.name,
|
|
1577
|
+
server.server_url,
|
|
1578
|
+
server.callback_url,
|
|
1579
|
+
parsedOptions,
|
|
1580
|
+
{
|
|
1581
|
+
id: server.id,
|
|
1582
|
+
oauthClientId: server.client_id ?? undefined
|
|
1583
|
+
}
|
|
1584
|
+
);
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
// Now process the OAuth callback
|
|
1588
|
+
return this._processOAuthCallback(request);
|
|
1589
|
+
} catch (error) {
|
|
1590
|
+
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
1591
|
+
console.error(`Failed to restore MCP state for ${serverId}:`, error);
|
|
1592
|
+
return new Response(
|
|
1593
|
+
`OAuth callback failed during state restoration: ${errorMsg}`,
|
|
1594
|
+
{ status: 500 }
|
|
1595
|
+
);
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
/**
|
|
1600
|
+
* Process an OAuth callback request (assumes state is already restored)
|
|
1601
|
+
*/
|
|
1602
|
+
private async _processOAuthCallback(request: Request): Promise<Response> {
|
|
1603
|
+
const result = await this.mcp.handleCallbackRequest(request);
|
|
1604
|
+
this.broadcastMcpServers();
|
|
1605
|
+
|
|
1606
|
+
if (result.authSuccess) {
|
|
1607
|
+
// Start background connection if auth was successful
|
|
1608
|
+
this.mcp
|
|
1609
|
+
.establishConnection(result.serverId)
|
|
1610
|
+
.catch((error) => {
|
|
1611
|
+
console.error("Background connection failed:", error);
|
|
1612
|
+
})
|
|
1613
|
+
.finally(() => {
|
|
1614
|
+
// Broadcast after background connection resolves (success/failure)
|
|
1615
|
+
this.broadcastMcpServers();
|
|
1616
|
+
});
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
// Handle OAuth callback response using MCPClientManager configuration
|
|
1620
|
+
return this.handleOAuthCallbackResponse(result, request);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
private async _connectToMcpServerInternal(
|
|
1450
1624
|
_serverName: string,
|
|
1451
1625
|
url: string,
|
|
1452
1626
|
callbackUrl: string,
|
|
@@ -1462,6 +1636,7 @@ export class Agent<
|
|
|
1462
1636
|
*/
|
|
1463
1637
|
transport?: {
|
|
1464
1638
|
headers?: HeadersInit;
|
|
1639
|
+
type?: TransportType;
|
|
1465
1640
|
};
|
|
1466
1641
|
},
|
|
1467
1642
|
reconnect?: {
|
|
@@ -1486,6 +1661,9 @@ export class Agent<
|
|
|
1486
1661
|
}
|
|
1487
1662
|
}
|
|
1488
1663
|
|
|
1664
|
+
// Use the transport type specified in options, or default to "auto"
|
|
1665
|
+
const transportType: TransportType = options?.transport?.type ?? "auto";
|
|
1666
|
+
|
|
1489
1667
|
// allows passing through transport headers if necessary
|
|
1490
1668
|
// this handles some non-standard bearer auth setups (i.e. MCP server behind CF access instead of OAuth)
|
|
1491
1669
|
let headerTransportOpts: SSEClientTransportOptions = {};
|
|
@@ -1509,7 +1687,8 @@ export class Agent<
|
|
|
1509
1687
|
reconnect,
|
|
1510
1688
|
transport: {
|
|
1511
1689
|
...headerTransportOpts,
|
|
1512
|
-
authProvider
|
|
1690
|
+
authProvider,
|
|
1691
|
+
type: transportType
|
|
1513
1692
|
}
|
|
1514
1693
|
});
|
|
1515
1694
|
|
|
@@ -1522,15 +1701,11 @@ export class Agent<
|
|
|
1522
1701
|
|
|
1523
1702
|
async removeMcpServer(id: string) {
|
|
1524
1703
|
this.mcp.closeConnection(id);
|
|
1704
|
+
this.mcp.unregisterCallbackUrl(id);
|
|
1525
1705
|
this.sql`
|
|
1526
1706
|
DELETE FROM cf_agents_mcp_servers WHERE id = ${id};
|
|
1527
1707
|
`;
|
|
1528
|
-
this.
|
|
1529
|
-
JSON.stringify({
|
|
1530
|
-
mcp: this.getMcpServers(),
|
|
1531
|
-
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
1532
|
-
})
|
|
1533
|
-
);
|
|
1708
|
+
this.broadcastMcpServers();
|
|
1534
1709
|
}
|
|
1535
1710
|
|
|
1536
1711
|
getMcpServers(): MCPServersState {
|
|
@@ -1562,8 +1737,53 @@ export class Agent<
|
|
|
1562
1737
|
|
|
1563
1738
|
return mcpState;
|
|
1564
1739
|
}
|
|
1740
|
+
|
|
1741
|
+
private broadcastMcpServers() {
|
|
1742
|
+
this.broadcast(
|
|
1743
|
+
JSON.stringify({
|
|
1744
|
+
mcp: this.getMcpServers(),
|
|
1745
|
+
type: MessageType.CF_AGENT_MCP_SERVERS
|
|
1746
|
+
})
|
|
1747
|
+
);
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
/**
|
|
1751
|
+
* Handle OAuth callback response using MCPClientManager configuration
|
|
1752
|
+
* @param result OAuth callback result
|
|
1753
|
+
* @param request The original request (needed for base URL)
|
|
1754
|
+
* @returns Response for the OAuth callback
|
|
1755
|
+
*/
|
|
1756
|
+
private handleOAuthCallbackResponse(
|
|
1757
|
+
result: MCPClientOAuthResult,
|
|
1758
|
+
request: Request
|
|
1759
|
+
): Response {
|
|
1760
|
+
const config = this.mcp.getOAuthCallbackConfig();
|
|
1761
|
+
|
|
1762
|
+
// Use custom handler if configured
|
|
1763
|
+
if (config?.customHandler) {
|
|
1764
|
+
return config.customHandler(result);
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
// Use redirect URLs if configured
|
|
1768
|
+
if (config?.successRedirect && result.authSuccess) {
|
|
1769
|
+
return Response.redirect(config.successRedirect);
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
if (config?.errorRedirect && !result.authSuccess) {
|
|
1773
|
+
return Response.redirect(
|
|
1774
|
+
`${config.errorRedirect}?error=${encodeURIComponent(result.authError || "Unknown error")}`
|
|
1775
|
+
);
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
// Default behavior - redirect to base URL
|
|
1779
|
+
const baseUrl = new URL(request.url).origin;
|
|
1780
|
+
return Response.redirect(baseUrl);
|
|
1781
|
+
}
|
|
1565
1782
|
}
|
|
1566
1783
|
|
|
1784
|
+
// A set of classes that have been wrapped with agent context
|
|
1785
|
+
const wrappedClasses = new Set<typeof Agent.prototype.constructor>();
|
|
1786
|
+
|
|
1567
1787
|
/**
|
|
1568
1788
|
* Namespace for creating Agent instances
|
|
1569
1789
|
* @template Agentic Type of the Agent class
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/ai-types.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/chunk-AVYJQSLW.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// src/ai-types.ts
|
|
2
|
-
var MessageType = /* @__PURE__ */ ((MessageType2) => {
|
|
3
|
-
MessageType2["CF_AGENT_CHAT_MESSAGES"] = "cf_agent_chat_messages";
|
|
4
|
-
MessageType2["CF_AGENT_USE_CHAT_REQUEST"] = "cf_agent_use_chat_request";
|
|
5
|
-
MessageType2["CF_AGENT_USE_CHAT_RESPONSE"] = "cf_agent_use_chat_response";
|
|
6
|
-
MessageType2["CF_AGENT_CHAT_CLEAR"] = "cf_agent_chat_clear";
|
|
7
|
-
MessageType2["CF_AGENT_CHAT_REQUEST_CANCEL"] = "cf_agent_chat_request_cancel";
|
|
8
|
-
MessageType2["CF_AGENT_MCP_SERVERS"] = "cf_agent_mcp_servers";
|
|
9
|
-
MessageType2["CF_AGENT_STATE"] = "cf_agent_state";
|
|
10
|
-
MessageType2["RPC"] = "rpc";
|
|
11
|
-
return MessageType2;
|
|
12
|
-
})(MessageType || {});
|
|
13
|
-
|
|
14
|
-
export {
|
|
15
|
-
MessageType
|
|
16
|
-
};
|
|
17
|
-
//# sourceMappingURL=chunk-AVYJQSLW.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ai-types.ts"],"sourcesContent":["import type { UIMessage } from \"ai\";\n\n/**\n * Enum for message types to improve type safety and maintainability\n */\nexport enum MessageType {\n CF_AGENT_CHAT_MESSAGES = \"cf_agent_chat_messages\",\n CF_AGENT_USE_CHAT_REQUEST = \"cf_agent_use_chat_request\",\n CF_AGENT_USE_CHAT_RESPONSE = \"cf_agent_use_chat_response\",\n CF_AGENT_CHAT_CLEAR = \"cf_agent_chat_clear\",\n CF_AGENT_CHAT_REQUEST_CANCEL = \"cf_agent_chat_request_cancel\",\n\n CF_AGENT_MCP_SERVERS = \"cf_agent_mcp_servers\",\n CF_AGENT_STATE = \"cf_agent_state\",\n RPC = \"rpc\"\n}\n\n/**\n * Types of messages sent from the Agent to clients\n */\nexport type OutgoingMessage<ChatMessage extends UIMessage = UIMessage> =\n | {\n /** Indicates this message is a command to clear chat history */\n type: MessageType.CF_AGENT_CHAT_CLEAR;\n }\n | {\n /** Indicates this message contains updated chat messages */\n type: MessageType.CF_AGENT_CHAT_MESSAGES;\n /** Array of chat messages */\n messages: ChatMessage[];\n }\n | {\n /** Indicates this message is a response to a chat request */\n type: MessageType.CF_AGENT_USE_CHAT_RESPONSE;\n /** Unique ID of the request this response corresponds to */\n id: string;\n /** Content body of the response */\n body: string;\n /** Whether this is the final chunk of the response */\n done: boolean;\n /** Whether this response contains an error */\n error?: boolean;\n }\n | {\n /** Indicates this message is a command to clear chat history */\n type: MessageType.CF_AGENT_CHAT_CLEAR;\n };\n\n/**\n * Types of messages sent from clients to the Agent\n */\nexport type IncomingMessage<ChatMessage extends UIMessage = UIMessage> =\n | {\n /** Indicates this message is a command to clear chat history */\n type: MessageType.CF_AGENT_CHAT_CLEAR;\n }\n | {\n /** Indicates this message is a request to the chat API */\n type: MessageType.CF_AGENT_USE_CHAT_REQUEST;\n /** Unique ID for this request */\n id: string;\n /** Request initialization options */\n init: Pick<\n RequestInit,\n | \"method\"\n | \"keepalive\"\n | \"headers\"\n | \"body\"\n | \"redirect\"\n | \"integrity\"\n | \"credentials\"\n | \"mode\"\n | \"referrer\"\n | \"referrerPolicy\"\n | \"window\"\n >;\n }\n | {\n /** Indicates this message is a command to clear chat history */\n type: MessageType.CF_AGENT_CHAT_CLEAR;\n }\n | {\n /** Indicates this message contains updated chat messages */\n type: MessageType.CF_AGENT_CHAT_MESSAGES;\n /** Array of chat messages */\n messages: ChatMessage[];\n }\n | {\n /** Indicates the user wants to stop generation of this message */\n type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL;\n id: string;\n };\n"],"mappings":";AAKO,IAAK,cAAL,kBAAKA,iBAAL;AACL,EAAAA,aAAA,4BAAyB;AACzB,EAAAA,aAAA,+BAA4B;AAC5B,EAAAA,aAAA,gCAA6B;AAC7B,EAAAA,aAAA,yBAAsB;AACtB,EAAAA,aAAA,kCAA+B;AAE/B,EAAAA,aAAA,0BAAuB;AACvB,EAAAA,aAAA,oBAAiB;AACjB,EAAAA,aAAA,SAAM;AATI,SAAAA;AAAA,GAAA;","names":["MessageType"]}
|
package/dist/chunk-LL2AFX7V.js
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
// src/mcp/do-oauth-client-provider.ts
|
|
2
|
-
var DurableObjectOAuthClientProvider = class {
|
|
3
|
-
constructor(storage, clientName, baseRedirectUrl) {
|
|
4
|
-
this.storage = storage;
|
|
5
|
-
this.clientName = clientName;
|
|
6
|
-
this.baseRedirectUrl = baseRedirectUrl;
|
|
7
|
-
}
|
|
8
|
-
get clientMetadata() {
|
|
9
|
-
return {
|
|
10
|
-
client_name: this.clientName,
|
|
11
|
-
client_uri: this.clientUri,
|
|
12
|
-
grant_types: ["authorization_code", "refresh_token"],
|
|
13
|
-
redirect_uris: [this.redirectUrl],
|
|
14
|
-
response_types: ["code"],
|
|
15
|
-
token_endpoint_auth_method: "none"
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
get clientUri() {
|
|
19
|
-
return new URL(this.redirectUrl).origin;
|
|
20
|
-
}
|
|
21
|
-
get redirectUrl() {
|
|
22
|
-
return `${this.baseRedirectUrl}/${this.serverId}`;
|
|
23
|
-
}
|
|
24
|
-
get clientId() {
|
|
25
|
-
if (!this._clientId_) {
|
|
26
|
-
throw new Error("Trying to access clientId before it was set");
|
|
27
|
-
}
|
|
28
|
-
return this._clientId_;
|
|
29
|
-
}
|
|
30
|
-
set clientId(clientId_) {
|
|
31
|
-
this._clientId_ = clientId_;
|
|
32
|
-
}
|
|
33
|
-
get serverId() {
|
|
34
|
-
if (!this._serverId_) {
|
|
35
|
-
throw new Error("Trying to access serverId before it was set");
|
|
36
|
-
}
|
|
37
|
-
return this._serverId_;
|
|
38
|
-
}
|
|
39
|
-
set serverId(serverId_) {
|
|
40
|
-
this._serverId_ = serverId_;
|
|
41
|
-
}
|
|
42
|
-
keyPrefix(clientId) {
|
|
43
|
-
return `/${this.clientName}/${this.serverId}/${clientId}`;
|
|
44
|
-
}
|
|
45
|
-
clientInfoKey(clientId) {
|
|
46
|
-
return `${this.keyPrefix(clientId)}/client_info/`;
|
|
47
|
-
}
|
|
48
|
-
async clientInformation() {
|
|
49
|
-
if (!this._clientId_) {
|
|
50
|
-
return void 0;
|
|
51
|
-
}
|
|
52
|
-
return await this.storage.get(
|
|
53
|
-
this.clientInfoKey(this.clientId)
|
|
54
|
-
) ?? void 0;
|
|
55
|
-
}
|
|
56
|
-
async saveClientInformation(clientInformation) {
|
|
57
|
-
await this.storage.put(
|
|
58
|
-
this.clientInfoKey(clientInformation.client_id),
|
|
59
|
-
clientInformation
|
|
60
|
-
);
|
|
61
|
-
this.clientId = clientInformation.client_id;
|
|
62
|
-
}
|
|
63
|
-
tokenKey(clientId) {
|
|
64
|
-
return `${this.keyPrefix(clientId)}/token`;
|
|
65
|
-
}
|
|
66
|
-
async tokens() {
|
|
67
|
-
if (!this._clientId_) {
|
|
68
|
-
return void 0;
|
|
69
|
-
}
|
|
70
|
-
return await this.storage.get(this.tokenKey(this.clientId)) ?? void 0;
|
|
71
|
-
}
|
|
72
|
-
async saveTokens(tokens) {
|
|
73
|
-
await this.storage.put(this.tokenKey(this.clientId), tokens);
|
|
74
|
-
}
|
|
75
|
-
get authUrl() {
|
|
76
|
-
return this._authUrl_;
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Because this operates on the server side (but we need browser auth), we send this url back to the user
|
|
80
|
-
* and require user interact to initiate the redirect flow
|
|
81
|
-
*/
|
|
82
|
-
async redirectToAuthorization(authUrl) {
|
|
83
|
-
const client_id = authUrl.searchParams.get("client_id");
|
|
84
|
-
if (client_id) {
|
|
85
|
-
authUrl.searchParams.append("state", client_id);
|
|
86
|
-
}
|
|
87
|
-
this._authUrl_ = authUrl.toString();
|
|
88
|
-
}
|
|
89
|
-
codeVerifierKey(clientId) {
|
|
90
|
-
return `${this.keyPrefix(clientId)}/code_verifier`;
|
|
91
|
-
}
|
|
92
|
-
async saveCodeVerifier(verifier) {
|
|
93
|
-
await this.storage.put(this.codeVerifierKey(this.clientId), verifier);
|
|
94
|
-
}
|
|
95
|
-
async codeVerifier() {
|
|
96
|
-
const codeVerifier = await this.storage.get(
|
|
97
|
-
this.codeVerifierKey(this.clientId)
|
|
98
|
-
);
|
|
99
|
-
if (!codeVerifier) {
|
|
100
|
-
throw new Error("No code verifier found");
|
|
101
|
-
}
|
|
102
|
-
return codeVerifier;
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
export {
|
|
107
|
-
DurableObjectOAuthClientProvider
|
|
108
|
-
};
|
|
109
|
-
//# sourceMappingURL=chunk-LL2AFX7V.js.map
|
|
@@ -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 OAuthClientInformation,\n OAuthClientInformationFull,\n OAuthClientMetadata,\n OAuthTokens\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 client_name: this.clientName,\n client_uri: this.clientUri,\n grant_types: [\"authorization_code\", \"refresh_token\"],\n redirect_uris: [this.redirectUrl],\n response_types: [\"code\"],\n token_endpoint_auth_method: \"none\"\n };\n }\n\n get clientUri() {\n return new URL(this.redirectUrl).origin;\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,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,aAAa,CAAC,sBAAsB,eAAe;AAAA,MACnD,eAAe,CAAC,KAAK,WAAW;AAAA,MAChC,gBAAgB,CAAC,MAAM;AAAA,MACvB,4BAA4B;AAAA,IAC9B;AAAA,EACF;AAAA,EAEA,IAAI,YAAY;AACd,WAAO,IAAI,IAAI,KAAK,WAAW,EAAE;AAAA,EACnC;AAAA,EAEA,IAAI,cAAc;AAChB,WAAO,GAAG,KAAK,eAAe,IAAI,KAAK,QAAQ;AAAA,EACjD;AAAA,EAEA,IAAI,WAAW;AACb,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAS,WAAmB;AAC9B,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,IAAI,WAAW;AACb,QAAI,CAAC,KAAK,YAAY;AACpB,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAS,WAAmB;AAC9B,SAAK,aAAa;AAAA,EACpB;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,YAAY;AACpB,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,YAAY;AACpB,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,YAAY,QAAQ,SAAS;AAAA,EACpC;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":[]}
|