agents 0.21.0 → 0.22.0
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 +1 -0
- package/dist/{agent-tool-types-CzGGB-20.d.ts → agent-routing-CnkaHb-v.d.ts} +2921 -3057
- package/dist/agent-routing.d.ts +14 -0
- package/dist/agent-routing.js +187 -0
- package/dist/agent-routing.js.map +1 -0
- package/dist/agent-tool-types.d.ts +26 -26
- package/dist/{agent-tools-zR2d5uij.d.ts → agent-tools-C0XJqWzB.d.ts} +7 -7
- package/dist/agent-tools.d.ts +21 -21
- package/dist/agent-tools.js +2 -1
- package/dist/agent-tools.js.map +1 -1
- package/dist/browser/ai.js +2 -1
- package/dist/browser/ai.js.map +1 -1
- package/dist/capability-BjSKYpzg.js +42 -0
- package/dist/capability-BjSKYpzg.js.map +1 -0
- package/dist/capability-runner-CvHGZqUu.d.ts +150 -0
- package/dist/chat/index.d.ts +22 -15
- package/dist/chat/index.js +4 -4
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +14 -1
- package/dist/chat/react.js +82 -52
- package/dist/chat/react.js.map +1 -1
- package/dist/chat/transport.js +1 -1
- package/dist/chat-sdk/index.d.ts +4 -4
- package/dist/chat-sdk/index.js +1 -1
- package/dist/{client-zqKcsyFa.js → client-jagG8a9_.js} +129 -37
- package/dist/client-jagG8a9_.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/client.js +1 -1
- package/dist/{cloudflare-BduZwmYK.js → cloudflare-Dzvc7V2N.js} +10 -3
- package/dist/{cloudflare-BduZwmYK.js.map → cloudflare-Dzvc7V2N.js.map} +1 -1
- package/dist/current-agent-CuMErtly.d.ts +283 -0
- package/dist/current-agent-DhoDkSnH.js +51 -0
- package/dist/current-agent-DhoDkSnH.js.map +1 -0
- package/dist/diagnostics-CaBjfz4J.js +41 -0
- package/dist/diagnostics-CaBjfz4J.js.map +1 -0
- package/dist/{do-oauth-client-provider-VTZj2VtM.d.ts → do-oauth-client-provider-Tmf1vgKz.d.ts} +2 -2
- package/dist/durable-object-lifecycle-D6nNQJJd.js +862 -0
- package/dist/durable-object-lifecycle-D6nNQJJd.js.map +1 -0
- package/dist/{email-CL27preh.d.ts → email-7TatiTnl.d.ts} +38 -9
- package/dist/email-send.d.ts +15 -0
- package/dist/email-send.js +32 -0
- package/dist/email-send.js.map +1 -0
- package/dist/email.d.ts +14 -10
- package/dist/email.js.map +1 -1
- package/dist/experimental/memory/session/index.d.ts +3 -2
- package/dist/experimental/memory/session/index.js +15 -10
- package/dist/experimental/memory/session/index.js.map +1 -1
- package/dist/{handler-stateless-C_bo-Ytq.d.ts → handler-stateless-DxYpJ_XF.d.ts} +3 -3
- package/dist/{handler-stateless-CIkKPETH.js → handler-stateless-VvrWSAVA.js} +5 -5
- package/dist/handler-stateless-VvrWSAVA.js.map +1 -0
- package/dist/{index-BRnybD6X.d.ts → index-DcSAZKsB.d.ts} +19 -31
- package/dist/index.d.ts +98 -95
- package/dist/index.js +10 -7234
- package/dist/internal_context-BlxFEWfn.d.ts +19 -0
- package/dist/internal_context.d.ts +10 -4
- package/dist/internal_context.js +1 -10
- package/dist/{client-invoker-BNSZxAkv.d.ts → invoker-CG0_p_Wq.d.ts} +2 -2
- package/dist/{client-invoker-VNZ7X0nn.js → invoker-CHMnoxIA.js} +2 -2
- package/dist/invoker-CHMnoxIA.js.map +1 -0
- package/dist/lifecycle/index.d.ts +48 -0
- package/dist/lifecycle/index.js +4 -0
- package/dist/mcp/{do-oauth-client-provider.d.ts → client/do-oauth-client-provider.d.ts} +1 -1
- package/dist/mcp/{do-oauth-client-provider.js → client/do-oauth-client-provider.js} +1 -1
- package/dist/mcp/client/do-oauth-client-provider.js.map +1 -0
- package/dist/mcp/client/index.d.ts +42 -0
- package/dist/mcp/{client.js → client/index.js} +1 -1
- package/dist/mcp/{x402.d.ts → client/x402.d.ts} +2 -2
- package/dist/mcp/{x402.js → client/x402.js} +2 -2
- package/dist/mcp/client/x402.js.map +1 -0
- package/dist/mcp/index.d.ts +36 -36
- package/dist/mcp/index.js +14 -16
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/{server.d.ts → server/index.d.ts} +1 -1
- package/dist/mcp/{server.js → server/index.js} +1 -1
- package/dist/observability/ai/index.js +50 -35
- package/dist/observability/ai/index.js.map +1 -1
- package/dist/observability/index.d.ts +4 -4
- package/dist/observability/index.js +3 -50
- package/dist/observability/index.js.map +1 -1
- package/dist/{protocol-Dqc2MQxo.js → protocol-B0nh6KNf.js} +19 -21
- package/dist/protocol-B0nh6KNf.js.map +1 -0
- package/dist/react.d.ts +4 -4
- package/dist/react.js +1 -1
- package/dist/schedule.d.ts +25 -94
- package/dist/schedule.js +1 -98
- package/dist/schedule.js.map +1 -1
- package/dist/scheduler-CR9RHGos.js +857 -0
- package/dist/scheduler-CR9RHGos.js.map +1 -0
- package/dist/scheduler-DQoTGoAW.d.ts +224 -0
- package/dist/schedules/index.d.ts +22 -0
- package/dist/schedules/index.js +2 -0
- package/dist/schedules/parser.d.ts +79 -0
- package/dist/schedules/parser.js +103 -0
- package/dist/schedules/parser.js.map +1 -0
- package/dist/serializable.d.ts +1 -1
- package/dist/sql-error-CPY-GXyI.d.ts +12 -0
- package/dist/sql-error.d.ts +2 -0
- package/dist/sql-error.js +16 -0
- package/dist/sql-error.js.map +1 -0
- package/dist/src-5W6JNKVb.js +6613 -0
- package/dist/src-5W6JNKVb.js.map +1 -0
- package/dist/sub-routing.d.ts +12 -12
- package/dist/workflow-types.d.ts +25 -25
- package/dist/workflows.d.ts +22 -22
- package/dist/workflows.js +2 -1
- package/dist/workflows.js.map +1 -1
- package/dist/{ws-chat-transport-CIoOBbO7.js → ws-chat-transport-rWwta645.js} +152 -15
- package/dist/ws-chat-transport-rWwta645.js.map +1 -0
- package/docs/agent-class.md +28 -86
- package/docs/chat-agents.md +13 -12
- package/docs/durable-execution.md +1 -1
- package/docs/http-websockets.md +1 -11
- package/docs/human-in-the-loop.md +1 -1
- package/docs/index.md +1 -0
- package/docs/lifecycle.md +323 -0
- package/docs/long-running-agents.md +2 -4
- package/docs/mcp-client.md +55 -0
- package/docs/observability.md +11 -11
- package/docs/resumable-streaming.md +1 -1
- package/docs/scheduling.md +175 -15
- package/docs/server-driven-messages.md +1 -1
- package/docs/sub-agents.md +1 -1
- package/package.json +30 -21
- package/dist/cli/index.d.ts +0 -1
- package/dist/cli/index.js +0 -26
- package/dist/cli/index.js.map +0 -1
- package/dist/client-invoker-VNZ7X0nn.js.map +0 -1
- package/dist/client-zqKcsyFa.js.map +0 -1
- package/dist/handler-stateless-CIkKPETH.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/internal_context-Dg4Cgjcu.d.ts +0 -37
- package/dist/internal_context.js.map +0 -1
- package/dist/mcp/client.d.ts +0 -42
- package/dist/mcp/do-oauth-client-provider.js.map +0 -1
- package/dist/mcp/x402.js.map +0 -1
- package/dist/protocol-Dqc2MQxo.js.map +0 -1
- package/dist/ws-chat-transport-CIoOBbO7.js.map +0 -1
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
-
import { Connection } from "partyserver";
|
|
3
|
-
|
|
4
|
-
//#region src/internal_context.d.ts
|
|
5
|
-
type AgentEmail = {
|
|
6
|
-
from: string;
|
|
7
|
-
to: string;
|
|
8
|
-
getRaw: () => Promise<Uint8Array>;
|
|
9
|
-
headers: Headers;
|
|
10
|
-
rawSize: number;
|
|
11
|
-
setReject: (reason: string) => void;
|
|
12
|
-
forward: (rcptTo: string, headers?: Headers) => Promise<EmailSendResult>;
|
|
13
|
-
reply: (options: {
|
|
14
|
-
from: string;
|
|
15
|
-
to: string;
|
|
16
|
-
raw: string;
|
|
17
|
-
}) => Promise<EmailSendResult> /** @internal Indicates email was routed via createSecureReplyEmailResolver */;
|
|
18
|
-
_secureRouted?: boolean;
|
|
19
|
-
};
|
|
20
|
-
type AgentContextStore = {
|
|
21
|
-
agent: unknown;
|
|
22
|
-
connection: Connection | undefined;
|
|
23
|
-
request: Request | undefined;
|
|
24
|
-
email: AgentEmail | undefined;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* @internal — This is an internal implementation detail.
|
|
28
|
-
* Importing or relying on this symbol **will** break your code in a future release.
|
|
29
|
-
*/
|
|
30
|
-
declare const __DO_NOT_USE_WILL_BREAK__agentContext: AsyncLocalStorage<AgentContextStore>;
|
|
31
|
-
//#endregion
|
|
32
|
-
export {
|
|
33
|
-
AgentEmail as n,
|
|
34
|
-
__DO_NOT_USE_WILL_BREAK__agentContext as r,
|
|
35
|
-
AgentContextStore as t
|
|
36
|
-
};
|
|
37
|
-
//# sourceMappingURL=internal_context-Dg4Cgjcu.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"internal_context.js","names":[],"sources":["../src/internal_context.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport type { Connection } from \"partyserver\";\n\nexport type AgentEmail = {\n from: string;\n to: string;\n getRaw: () => Promise<Uint8Array>;\n headers: Headers;\n rawSize: number;\n setReject: (reason: string) => void;\n forward: (rcptTo: string, headers?: Headers) => Promise<EmailSendResult>;\n reply: (options: {\n from: string;\n to: string;\n raw: string;\n }) => Promise<EmailSendResult>;\n /** @internal Indicates email was routed via createSecureReplyEmailResolver */\n _secureRouted?: boolean;\n};\n\nexport type AgentContextStore = {\n // Using unknown to avoid circular dependency with Agent\n agent: unknown;\n connection: Connection | undefined;\n request: Request | undefined;\n email: AgentEmail | undefined;\n};\n\n/**\n * @internal — This is an internal implementation detail.\n * Importing or relying on this symbol **will** break your code in a future release.\n */\nexport const __DO_NOT_USE_WILL_BREAK__agentContext =\n new AsyncLocalStorage<AgentContextStore>();\n"],"mappings":";;;;;;AAgCA,MAAa,wCACX,IAAI,kBAAqC"}
|
package/dist/mcp/client.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
$t as MCPOAuthCallbackResult,
|
|
3
|
-
Gt as MCPClientElicitationHandler,
|
|
4
|
-
Ht as ElicitResult,
|
|
5
|
-
Jt as MCPClientManagerOptions,
|
|
6
|
-
Kt as MCPClientElicitationHandlers,
|
|
7
|
-
Qt as MCPDiscoverResult,
|
|
8
|
-
Ut as MCPAITool,
|
|
9
|
-
Vt as ElicitRequest,
|
|
10
|
-
Wt as MCPAIToolSet,
|
|
11
|
-
Xt as MCPClientOAuthResult,
|
|
12
|
-
Yt as MCPClientOAuthCallbackConfig,
|
|
13
|
-
Zt as MCPConnectionResult,
|
|
14
|
-
an as normalizeServerId,
|
|
15
|
-
en as MCPServerFilter,
|
|
16
|
-
in as getNamespacedData,
|
|
17
|
-
nn as MCP_SERVER_ID_MAX_LENGTH,
|
|
18
|
-
qt as MCPClientManager,
|
|
19
|
-
rn as RegisterServerOptions,
|
|
20
|
-
tn as MCPServerOptions
|
|
21
|
-
} from "../agent-tool-types-CzGGB-20.js";
|
|
22
|
-
export {
|
|
23
|
-
type ElicitRequest,
|
|
24
|
-
type ElicitResult,
|
|
25
|
-
MCPAITool,
|
|
26
|
-
MCPAIToolSet,
|
|
27
|
-
MCPClientElicitationHandler,
|
|
28
|
-
MCPClientElicitationHandlers,
|
|
29
|
-
MCPClientManager,
|
|
30
|
-
MCPClientManagerOptions,
|
|
31
|
-
MCPClientOAuthCallbackConfig,
|
|
32
|
-
MCPClientOAuthResult,
|
|
33
|
-
MCPConnectionResult,
|
|
34
|
-
MCPDiscoverResult,
|
|
35
|
-
MCPOAuthCallbackResult,
|
|
36
|
-
MCPServerFilter,
|
|
37
|
-
MCPServerOptions,
|
|
38
|
-
MCP_SERVER_ID_MAX_LENGTH,
|
|
39
|
-
RegisterServerOptions,
|
|
40
|
-
getNamespacedData,
|
|
41
|
-
normalizeServerId
|
|
42
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"do-oauth-client-provider.js","names":[],"sources":["../../src/mcp/do-oauth-client-provider.ts"],"sourcesContent":["import type {\n OAuthClientInformationContext,\n OAuthClientMetadata,\n OAuthClientProvider,\n OAuthDiscoveryState,\n StoredOAuthClientInformation,\n StoredOAuthTokens\n} from \"@modelcontextprotocol/client\";\nimport { AsyncLocalStorage } from \"node:async_hooks\";\nimport { nanoid } from \"nanoid\";\n\nconst STATE_EXPIRATION_MS = 10 * 60 * 1000; // 10 minutes\n\nconst codeVerifierStateStorage = new AsyncLocalStorage<{\n state: string;\n servedKey?: string;\n}>();\n\ninterface StoredState {\n nonce: string;\n serverId: string;\n createdAt: number;\n}\n\ninterface StoredCodeVerifier {\n verifier: string;\n createdAt: number;\n}\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 AgentMcpOAuthProvider extends OAuthClientProvider {\n authUrl: string | undefined;\n clientId: string | undefined;\n serverId: string | undefined;\n checkState(\n state: string\n ): Promise<{ valid: boolean; serverId?: string; error?: string }>;\n consumeState(state: string): Promise<void>;\n runWithCodeVerifierState?<T>(\n state: string,\n callback: () => Promise<T>\n ): Promise<T>;\n deleteCodeVerifier(): Promise<void>;\n}\n\nfunction parseOAuthState(\n state: string\n): { nonce: string; serverId: string } | undefined {\n const parts = state.split(\".\");\n if (parts.length !== 2) {\n return undefined;\n }\n\n const [nonce, serverId] = parts;\n if (!nonce || !serverId) {\n return undefined;\n }\n\n return { nonce, serverId };\n}\n\nfunction base64UrlEncode(bytes: Uint8Array): string {\n let binary = \"\";\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n return btoa(binary)\n .replace(/\\+/g, \"-\")\n .replace(/\\//g, \"_\")\n .replace(/=+$/, \"\");\n}\n\nasync function createCodeChallenge(verifier: string): Promise<string> {\n const digest = await crypto.subtle.digest(\n \"SHA-256\",\n new TextEncoder().encode(verifier)\n );\n return base64UrlEncode(new Uint8Array(digest));\n}\n\nfunction isExpired(createdAt: number): boolean {\n return Date.now() - createdAt > STATE_EXPIRATION_MS;\n}\n\n/**\n * @deprecated Use {@link AgentMcpOAuthProvider} instead.\n */\nexport type AgentsOAuthProvider = AgentMcpOAuthProvider;\n\nexport class DurableObjectOAuthClientProvider implements AgentMcpOAuthProvider {\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 if (!storage) {\n throw new Error(\n \"DurableObjectOAuthClientProvider requires a valid DurableObjectStorage instance\"\n );\n }\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;\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 discoveryStateKey() {\n return `/${this.clientName}/${this.serverId}/oauth_discovery`;\n }\n\n async saveDiscoveryState(state: OAuthDiscoveryState): Promise<void> {\n await this.storage.put(this.discoveryStateKey(), state);\n }\n\n async discoveryState(): Promise<OAuthDiscoveryState | undefined> {\n return (\n (await this.storage.get<OAuthDiscoveryState>(this.discoveryStateKey())) ??\n undefined\n );\n }\n\n async clientInformation(\n _context?: OAuthClientInformationContext\n ): Promise<StoredOAuthClientInformation | undefined> {\n if (!this._clientId_) return undefined;\n return (\n (await this.storage.get<StoredOAuthClientInformation>(\n this.clientInfoKey(this.clientId)\n )) ?? undefined\n );\n }\n\n async saveClientInformation(\n clientInformation: StoredOAuthClientInformation,\n _context?: OAuthClientInformationContext\n ): Promise<void> {\n this.clientId = clientInformation.client_id;\n // Round-trip the SDK's issuer stamp verbatim. The SDK treats a credential\n // stamped for another issuer as absent, so one durable slot per MCP server\n // is both sufficient and safer than maintaining our own issuer index.\n await this.storage.put(\n this.clientInfoKey(clientInformation.client_id),\n clientInformation\n );\n }\n\n tokenKey(clientId: string) {\n return `${this.keyPrefix(clientId)}/token`;\n }\n\n async tokens(\n _context?: OAuthClientInformationContext\n ): Promise<StoredOAuthTokens | undefined> {\n if (!this._clientId_) return undefined;\n return (\n (await this.storage.get<StoredOAuthTokens>(\n this.tokenKey(this.clientId)\n )) ?? undefined\n );\n }\n\n async saveTokens(\n tokens: StoredOAuthTokens,\n _context?: OAuthClientInformationContext\n ): Promise<void> {\n // Keep the SDK-owned issuer stamp intact for SEP-2352 validation. Discovery\n // is needed across the browser redirect, but once token issuance succeeds\n // it must not pin later re-authorization to this AS: a subsequent 401 must\n // re-read PRM so an authorization-server migration can be observed.\n await this.storage.put(this.tokenKey(this.clientId), tokens);\n await this.storage.delete(this.discoveryStateKey());\n }\n\n get authUrl() {\n return this._authUrl_;\n }\n\n stateKey(nonce: string) {\n return `/${this.clientName}/${this.serverId}/state/${nonce}`;\n }\n\n async state(): Promise<string> {\n const nonce = nanoid();\n const state = `${nonce}.${this.serverId}`;\n const storedState: StoredState = {\n nonce,\n serverId: this.serverId,\n createdAt: Date.now()\n };\n await this.storage.put(this.stateKey(nonce), storedState);\n return state;\n }\n\n async checkState(\n state: string\n ): Promise<{ valid: boolean; serverId?: string; error?: string }> {\n const parsed = parseOAuthState(state);\n if (!parsed) {\n return { valid: false, error: \"Invalid state format\" };\n }\n\n const { nonce, serverId } = parsed;\n const key = this.stateKey(nonce);\n const storedState = await this.storage.get<StoredState>(key);\n\n if (!storedState) {\n return { valid: false, error: \"State not found or already used\" };\n }\n\n if (storedState.serverId !== serverId) {\n await this.storage.delete(key);\n return { valid: false, error: \"State serverId mismatch\" };\n }\n\n if (isExpired(storedState.createdAt)) {\n const deleteKeys = [key];\n if (this._clientId_) {\n deleteKeys.push(this.stateCodeVerifierKey(this.clientId, nonce));\n }\n await this.storage.delete(deleteKeys);\n return { valid: false, error: \"State expired\" };\n }\n\n return { valid: true, serverId };\n }\n\n async consumeState(state: string): Promise<void> {\n const parsed = parseOAuthState(state);\n if (!parsed) {\n // This should never happen since checkState validates format first.\n // Log for debugging but don't throw - state consumption is best-effort.\n console.warn(`[OAuth] consumeState called with invalid state format`);\n return;\n }\n await this.storage.delete(this.stateKey(parsed.nonce));\n }\n\n async redirectToAuthorization(authUrl: URL): Promise<void> {\n this._authUrl_ = authUrl.toString();\n\n const clientId = this._clientId_;\n const serverId = this._serverId_;\n if (!clientId || !serverId) {\n return;\n }\n\n const state = authUrl.searchParams.get(\"state\");\n const codeChallenge = authUrl.searchParams.get(\"code_challenge\");\n if (!state || !codeChallenge) {\n return;\n }\n\n const parsed = parseOAuthState(state);\n if (!parsed || parsed.serverId !== serverId) {\n return;\n }\n\n const challengeKey = this.challengeCodeVerifierKey(clientId, codeChallenge);\n const pendingVerifier =\n await this.storage.get<StoredCodeVerifier>(challengeKey);\n if (!pendingVerifier) {\n return;\n }\n\n if (isExpired(pendingVerifier.createdAt)) {\n await this.storage.delete(challengeKey);\n return;\n }\n\n await this.storage.put(\n this.stateCodeVerifierKey(clientId, parsed.nonce),\n pendingVerifier\n );\n await this.storage.delete(challengeKey);\n }\n\n async invalidateCredentials(\n scope: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\"\n ): Promise<void> {\n const deleteKeys: string[] = [];\n\n if (scope === \"all\" || scope === \"discovery\") {\n deleteKeys.push(this.discoveryStateKey());\n }\n\n if (this._clientId_) {\n const clientId = this.clientId;\n if (scope === \"all\" || scope === \"client\") {\n deleteKeys.push(this.clientInfoKey(clientId));\n }\n if (scope === \"all\" || scope === \"tokens\") {\n deleteKeys.push(this.tokenKey(clientId));\n }\n if (scope === \"all\" || scope === \"verifier\") {\n deleteKeys.push(\n ...(await this.codeVerifierKeys(clientId, {\n includeChallengeKeys: true\n }))\n );\n }\n }\n\n if (deleteKeys.length > 0) {\n await this.storage.delete([...new Set(deleteKeys)]);\n }\n }\n\n codeVerifierKey(clientId: string) {\n return `${this.keyPrefix(clientId)}/code_verifier`;\n }\n\n stateCodeVerifierPrefix(clientId: string) {\n return `${this.keyPrefix(clientId)}/code_verifier/`;\n }\n\n stateCodeVerifierKey(clientId: string, nonce: string) {\n return `${this.stateCodeVerifierPrefix(clientId)}${nonce}`;\n }\n\n challengeCodeVerifierPrefix(clientId: string) {\n return `${this.keyPrefix(clientId)}/code_verifier_challenge/`;\n }\n\n challengeCodeVerifierKey(clientId: string, codeChallenge: string) {\n return `${this.challengeCodeVerifierPrefix(clientId)}${codeChallenge}`;\n }\n\n async codeVerifierKeys(\n clientId: string,\n options: { includeChallengeKeys?: boolean } = {}\n ): Promise<string[]> {\n const legacyKey = this.codeVerifierKey(clientId);\n const keys: string[] = [];\n\n if (await this.storage.get(legacyKey)) {\n keys.push(legacyKey);\n }\n\n const stateKeys = await this.storage.list({\n prefix: this.stateCodeVerifierPrefix(clientId)\n });\n keys.push(...stateKeys.keys());\n\n if (options.includeChallengeKeys) {\n const challengeKeys = await this.storage.list({\n prefix: this.challengeCodeVerifierPrefix(clientId)\n });\n keys.push(...challengeKeys.keys());\n }\n\n return keys;\n }\n\n async saveCodeVerifier(verifier: string): Promise<void> {\n await this.deleteExpiredChallengeCodeVerifiers(this.clientId);\n\n const codeChallenge = await createCodeChallenge(verifier);\n const storedVerifier: StoredCodeVerifier = {\n verifier,\n createdAt: Date.now()\n };\n\n await this.storage.put(\n this.challengeCodeVerifierKey(this.clientId, codeChallenge),\n storedVerifier\n );\n }\n\n private async deleteExpiredChallengeCodeVerifiers(\n clientId: string\n ): Promise<void> {\n const challengeVerifiers = await this.storage.list<StoredCodeVerifier>({\n prefix: this.challengeCodeVerifierPrefix(clientId)\n });\n const expiredKeys = [...challengeVerifiers.entries()]\n .filter(([, storedVerifier]) => isExpired(storedVerifier.createdAt))\n .map(([key]) => key);\n if (expiredKeys.length > 0) {\n await this.storage.delete(expiredKeys);\n }\n }\n\n async codeVerifier(): Promise<string> {\n const context = codeVerifierStateStorage.getStore();\n if (context) {\n const stateVerifier = await this.codeVerifierForState(context.state);\n if (stateVerifier) {\n context.servedKey = stateVerifier.key;\n return stateVerifier.verifier;\n }\n }\n\n const legacyVerifier = await this.storage.get<string>(\n this.codeVerifierKey(this.clientId)\n );\n if (legacyVerifier) {\n if (context) {\n context.servedKey = this.codeVerifierKey(this.clientId);\n }\n return legacyVerifier;\n }\n\n if (context) {\n throw new Error(\"No code verifier found for OAuth state\");\n }\n\n const pendingVerifiers = await this.storage.list<StoredCodeVerifier>({\n prefix: this.stateCodeVerifierPrefix(this.clientId)\n });\n const unexpiredPendingVerifiers = [...pendingVerifiers.entries()].filter(\n ([, storedVerifier]) => !isExpired(storedVerifier.createdAt)\n );\n const expiredKeys = [...pendingVerifiers.entries()]\n .filter(([, storedVerifier]) => isExpired(storedVerifier.createdAt))\n .map(([key]) => key);\n if (expiredKeys.length > 0) {\n await this.storage.delete(expiredKeys);\n }\n\n if (unexpiredPendingVerifiers.length === 1) {\n const [[, storedVerifier]] = unexpiredPendingVerifiers;\n return storedVerifier.verifier;\n }\n\n if (unexpiredPendingVerifiers.length > 1) {\n throw new Error(\n \"Multiple OAuth code verifiers are pending; complete authorization with the callback state\"\n );\n }\n\n throw new Error(\"No code verifier found\");\n }\n\n private async codeVerifierForState(\n state: string\n ): Promise<{ key: string; verifier: string } | undefined> {\n const parsed = parseOAuthState(state);\n if (!parsed) {\n throw new Error(\"Invalid state format\");\n }\n\n const key = this.stateCodeVerifierKey(this.clientId, parsed.nonce);\n const storedVerifier = await this.storage.get<StoredCodeVerifier>(key);\n if (!storedVerifier) {\n return undefined;\n }\n\n if (isExpired(storedVerifier.createdAt)) {\n await this.storage.delete(key);\n throw new Error(\"Code verifier expired\");\n }\n\n return { key, verifier: storedVerifier.verifier };\n }\n\n async runWithCodeVerifierState<T>(\n state: string,\n callback: () => Promise<T>\n ): Promise<T> {\n return codeVerifierStateStorage.run({ state }, callback);\n }\n\n async deleteCodeVerifier(): Promise<void> {\n const context = codeVerifierStateStorage.getStore();\n if (context?.servedKey) {\n await this.storage.delete(context.servedKey);\n return;\n }\n\n if (context) {\n const parsed = parseOAuthState(context.state);\n if (parsed) {\n await this.storage.delete(\n this.stateCodeVerifierKey(this.clientId, parsed.nonce)\n );\n return;\n }\n }\n\n const keys = await this.codeVerifierKeys(this.clientId);\n if (keys.length > 0) {\n await this.storage.delete(keys);\n }\n }\n}\n"],"mappings":";;;AAWA,MAAM,sBAAsB,MAAU;AAEtC,MAAM,2BAA2B,IAAI,kBAGlC;AA8BH,SAAS,gBACP,OACiD;CACjD,MAAM,QAAQ,MAAM,MAAM,GAAG;CAC7B,IAAI,MAAM,WAAW,GACnB;CAGF,MAAM,CAAC,OAAO,YAAY;CAC1B,IAAI,CAAC,SAAS,CAAC,UACb;CAGF,OAAO;EAAE;EAAO;CAAS;AAC3B;AAEA,SAAS,gBAAgB,OAA2B;CAClD,IAAI,SAAS;CACb,KAAK,MAAM,QAAQ,OACjB,UAAU,OAAO,aAAa,IAAI;CAEpC,OAAO,KAAK,MAAM,CAAC,CAChB,QAAQ,OAAO,GAAG,CAAC,CACnB,QAAQ,OAAO,GAAG,CAAC,CACnB,QAAQ,OAAO,EAAE;AACtB;AAEA,eAAe,oBAAoB,UAAmC;CACpE,MAAM,SAAS,MAAM,OAAO,OAAO,OACjC,WACA,IAAI,YAAY,CAAC,CAAC,OAAO,QAAQ,CACnC;CACA,OAAO,gBAAgB,IAAI,WAAW,MAAM,CAAC;AAC/C;AAEA,SAAS,UAAU,WAA4B;CAC7C,OAAO,KAAK,IAAI,IAAI,YAAY;AAClC;AAOA,IAAa,mCAAb,MAA+E;CAK7E,YACE,SACA,YACA,iBACA;EAHO,KAAA,UAAA;EACA,KAAA,aAAA;EACA,KAAA,kBAAA;EAEP,IAAI,CAAC,SACH,MAAM,IAAI,MACR,iFACF;CAEJ;CAEA,IAAI,iBAAsC;EACxC,OAAO;GACL,aAAa,KAAK;GAClB,YAAY,KAAK;GACjB,aAAa,CAAC,sBAAsB,eAAe;GACnD,eAAe,CAAC,KAAK,WAAW;GAChC,gBAAgB,CAAC,MAAM;GACvB,4BAA4B;EAC9B;CACF;CAEA,IAAI,YAAY;EACd,OAAO,IAAI,IAAI,KAAK,WAAW,CAAC,CAAC;CACnC;CAEA,IAAI,cAAc;EAChB,OAAO,KAAK;CACd;CAEA,IAAI,WAAW;EACb,IAAI,CAAC,KAAK,YACR,MAAM,IAAI,MAAM,6CAA6C;EAE/D,OAAO,KAAK;CACd;CAEA,IAAI,SAAS,WAAmB;EAC9B,KAAK,aAAa;CACpB;CAEA,IAAI,WAAW;EACb,IAAI,CAAC,KAAK,YACR,MAAM,IAAI,MAAM,6CAA6C;EAE/D,OAAO,KAAK;CACd;CAEA,IAAI,SAAS,WAAmB;EAC9B,KAAK,aAAa;CACpB;CAEA,UAAU,UAAkB;EAC1B,OAAO,IAAI,KAAK,WAAW,GAAG,KAAK,SAAS,GAAG;CACjD;CAEA,cAAc,UAAkB;EAC9B,OAAO,GAAG,KAAK,UAAU,QAAQ,EAAE;CACrC;CAEA,oBAAoB;EAClB,OAAO,IAAI,KAAK,WAAW,GAAG,KAAK,SAAS;CAC9C;CAEA,MAAM,mBAAmB,OAA2C;EAClE,MAAM,KAAK,QAAQ,IAAI,KAAK,kBAAkB,GAAG,KAAK;CACxD;CAEA,MAAM,iBAA2D;EAC/D,OACG,MAAM,KAAK,QAAQ,IAAyB,KAAK,kBAAkB,CAAC,KACrE,KAAA;CAEJ;CAEA,MAAM,kBACJ,UACmD;EACnD,IAAI,CAAC,KAAK,YAAY,OAAO,KAAA;EAC7B,OACG,MAAM,KAAK,QAAQ,IAClB,KAAK,cAAc,KAAK,QAAQ,CAClC,KAAM,KAAA;CAEV;CAEA,MAAM,sBACJ,mBACA,UACe;EACf,KAAK,WAAW,kBAAkB;EAIlC,MAAM,KAAK,QAAQ,IACjB,KAAK,cAAc,kBAAkB,SAAS,GAC9C,iBACF;CACF;CAEA,SAAS,UAAkB;EACzB,OAAO,GAAG,KAAK,UAAU,QAAQ,EAAE;CACrC;CAEA,MAAM,OACJ,UACwC;EACxC,IAAI,CAAC,KAAK,YAAY,OAAO,KAAA;EAC7B,OACG,MAAM,KAAK,QAAQ,IAClB,KAAK,SAAS,KAAK,QAAQ,CAC7B,KAAM,KAAA;CAEV;CAEA,MAAM,WACJ,QACA,UACe;EAKf,MAAM,KAAK,QAAQ,IAAI,KAAK,SAAS,KAAK,QAAQ,GAAG,MAAM;EAC3D,MAAM,KAAK,QAAQ,OAAO,KAAK,kBAAkB,CAAC;CACpD;CAEA,IAAI,UAAU;EACZ,OAAO,KAAK;CACd;CAEA,SAAS,OAAe;EACtB,OAAO,IAAI,KAAK,WAAW,GAAG,KAAK,SAAS,SAAS;CACvD;CAEA,MAAM,QAAyB;EAC7B,MAAM,QAAQ,OAAO;EACrB,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK;EAC/B,MAAM,cAA2B;GAC/B;GACA,UAAU,KAAK;GACf,WAAW,KAAK,IAAI;EACtB;EACA,MAAM,KAAK,QAAQ,IAAI,KAAK,SAAS,KAAK,GAAG,WAAW;EACxD,OAAO;CACT;CAEA,MAAM,WACJ,OACgE;EAChE,MAAM,SAAS,gBAAgB,KAAK;EACpC,IAAI,CAAC,QACH,OAAO;GAAE,OAAO;GAAO,OAAO;EAAuB;EAGvD,MAAM,EAAE,OAAO,aAAa;EAC5B,MAAM,MAAM,KAAK,SAAS,KAAK;EAC/B,MAAM,cAAc,MAAM,KAAK,QAAQ,IAAiB,GAAG;EAE3D,IAAI,CAAC,aACH,OAAO;GAAE,OAAO;GAAO,OAAO;EAAkC;EAGlE,IAAI,YAAY,aAAa,UAAU;GACrC,MAAM,KAAK,QAAQ,OAAO,GAAG;GAC7B,OAAO;IAAE,OAAO;IAAO,OAAO;GAA0B;EAC1D;EAEA,IAAI,UAAU,YAAY,SAAS,GAAG;GACpC,MAAM,aAAa,CAAC,GAAG;GACvB,IAAI,KAAK,YACP,WAAW,KAAK,KAAK,qBAAqB,KAAK,UAAU,KAAK,CAAC;GAEjE,MAAM,KAAK,QAAQ,OAAO,UAAU;GACpC,OAAO;IAAE,OAAO;IAAO,OAAO;GAAgB;EAChD;EAEA,OAAO;GAAE,OAAO;GAAM;EAAS;CACjC;CAEA,MAAM,aAAa,OAA8B;EAC/C,MAAM,SAAS,gBAAgB,KAAK;EACpC,IAAI,CAAC,QAAQ;GAGX,QAAQ,KAAK,uDAAuD;GACpE;EACF;EACA,MAAM,KAAK,QAAQ,OAAO,KAAK,SAAS,OAAO,KAAK,CAAC;CACvD;CAEA,MAAM,wBAAwB,SAA6B;EACzD,KAAK,YAAY,QAAQ,SAAS;EAElC,MAAM,WAAW,KAAK;EACtB,MAAM,WAAW,KAAK;EACtB,IAAI,CAAC,YAAY,CAAC,UAChB;EAGF,MAAM,QAAQ,QAAQ,aAAa,IAAI,OAAO;EAC9C,MAAM,gBAAgB,QAAQ,aAAa,IAAI,gBAAgB;EAC/D,IAAI,CAAC,SAAS,CAAC,eACb;EAGF,MAAM,SAAS,gBAAgB,KAAK;EACpC,IAAI,CAAC,UAAU,OAAO,aAAa,UACjC;EAGF,MAAM,eAAe,KAAK,yBAAyB,UAAU,aAAa;EAC1E,MAAM,kBACJ,MAAM,KAAK,QAAQ,IAAwB,YAAY;EACzD,IAAI,CAAC,iBACH;EAGF,IAAI,UAAU,gBAAgB,SAAS,GAAG;GACxC,MAAM,KAAK,QAAQ,OAAO,YAAY;GACtC;EACF;EAEA,MAAM,KAAK,QAAQ,IACjB,KAAK,qBAAqB,UAAU,OAAO,KAAK,GAChD,eACF;EACA,MAAM,KAAK,QAAQ,OAAO,YAAY;CACxC;CAEA,MAAM,sBACJ,OACe;EACf,MAAM,aAAuB,CAAC;EAE9B,IAAI,UAAU,SAAS,UAAU,aAC/B,WAAW,KAAK,KAAK,kBAAkB,CAAC;EAG1C,IAAI,KAAK,YAAY;GACnB,MAAM,WAAW,KAAK;GACtB,IAAI,UAAU,SAAS,UAAU,UAC/B,WAAW,KAAK,KAAK,cAAc,QAAQ,CAAC;GAE9C,IAAI,UAAU,SAAS,UAAU,UAC/B,WAAW,KAAK,KAAK,SAAS,QAAQ,CAAC;GAEzC,IAAI,UAAU,SAAS,UAAU,YAC/B,WAAW,KACT,GAAI,MAAM,KAAK,iBAAiB,UAAU,EACxC,sBAAsB,KACxB,CAAC,CACH;EAEJ;EAEA,IAAI,WAAW,SAAS,GACtB,MAAM,KAAK,QAAQ,OAAO,CAAC,GAAG,IAAI,IAAI,UAAU,CAAC,CAAC;CAEtD;CAEA,gBAAgB,UAAkB;EAChC,OAAO,GAAG,KAAK,UAAU,QAAQ,EAAE;CACrC;CAEA,wBAAwB,UAAkB;EACxC,OAAO,GAAG,KAAK,UAAU,QAAQ,EAAE;CACrC;CAEA,qBAAqB,UAAkB,OAAe;EACpD,OAAO,GAAG,KAAK,wBAAwB,QAAQ,IAAI;CACrD;CAEA,4BAA4B,UAAkB;EAC5C,OAAO,GAAG,KAAK,UAAU,QAAQ,EAAE;CACrC;CAEA,yBAAyB,UAAkB,eAAuB;EAChE,OAAO,GAAG,KAAK,4BAA4B,QAAQ,IAAI;CACzD;CAEA,MAAM,iBACJ,UACA,UAA8C,CAAC,GAC5B;EACnB,MAAM,YAAY,KAAK,gBAAgB,QAAQ;EAC/C,MAAM,OAAiB,CAAC;EAExB,IAAI,MAAM,KAAK,QAAQ,IAAI,SAAS,GAClC,KAAK,KAAK,SAAS;EAGrB,MAAM,YAAY,MAAM,KAAK,QAAQ,KAAK,EACxC,QAAQ,KAAK,wBAAwB,QAAQ,EAC/C,CAAC;EACD,KAAK,KAAK,GAAG,UAAU,KAAK,CAAC;EAE7B,IAAI,QAAQ,sBAAsB;GAChC,MAAM,gBAAgB,MAAM,KAAK,QAAQ,KAAK,EAC5C,QAAQ,KAAK,4BAA4B,QAAQ,EACnD,CAAC;GACD,KAAK,KAAK,GAAG,cAAc,KAAK,CAAC;EACnC;EAEA,OAAO;CACT;CAEA,MAAM,iBAAiB,UAAiC;EACtD,MAAM,KAAK,oCAAoC,KAAK,QAAQ;EAE5D,MAAM,gBAAgB,MAAM,oBAAoB,QAAQ;EACxD,MAAM,iBAAqC;GACzC;GACA,WAAW,KAAK,IAAI;EACtB;EAEA,MAAM,KAAK,QAAQ,IACjB,KAAK,yBAAyB,KAAK,UAAU,aAAa,GAC1D,cACF;CACF;CAEA,MAAc,oCACZ,UACe;EAIf,MAAM,cAAc,CAAC,IAAG,MAHS,KAAK,QAAQ,KAAyB,EACrE,QAAQ,KAAK,4BAA4B,QAAQ,EACnD,CAAC,EAAA,CAC0C,QAAQ,CAAC,CAAC,CAClD,QAAQ,GAAG,oBAAoB,UAAU,eAAe,SAAS,CAAC,CAAC,CACnE,KAAK,CAAC,SAAS,GAAG;EACrB,IAAI,YAAY,SAAS,GACvB,MAAM,KAAK,QAAQ,OAAO,WAAW;CAEzC;CAEA,MAAM,eAAgC;EACpC,MAAM,UAAU,yBAAyB,SAAS;EAClD,IAAI,SAAS;GACX,MAAM,gBAAgB,MAAM,KAAK,qBAAqB,QAAQ,KAAK;GACnE,IAAI,eAAe;IACjB,QAAQ,YAAY,cAAc;IAClC,OAAO,cAAc;GACvB;EACF;EAEA,MAAM,iBAAiB,MAAM,KAAK,QAAQ,IACxC,KAAK,gBAAgB,KAAK,QAAQ,CACpC;EACA,IAAI,gBAAgB;GAClB,IAAI,SACF,QAAQ,YAAY,KAAK,gBAAgB,KAAK,QAAQ;GAExD,OAAO;EACT;EAEA,IAAI,SACF,MAAM,IAAI,MAAM,wCAAwC;EAG1D,MAAM,mBAAmB,MAAM,KAAK,QAAQ,KAAyB,EACnE,QAAQ,KAAK,wBAAwB,KAAK,QAAQ,EACpD,CAAC;EACD,MAAM,4BAA4B,CAAC,GAAG,iBAAiB,QAAQ,CAAC,CAAC,CAAC,QAC/D,GAAG,oBAAoB,CAAC,UAAU,eAAe,SAAS,CAC7D;EACA,MAAM,cAAc,CAAC,GAAG,iBAAiB,QAAQ,CAAC,CAAC,CAChD,QAAQ,GAAG,oBAAoB,UAAU,eAAe,SAAS,CAAC,CAAC,CACnE,KAAK,CAAC,SAAS,GAAG;EACrB,IAAI,YAAY,SAAS,GACvB,MAAM,KAAK,QAAQ,OAAO,WAAW;EAGvC,IAAI,0BAA0B,WAAW,GAAG;GAC1C,MAAM,CAAC,GAAG,mBAAmB;GAC7B,OAAO,eAAe;EACxB;EAEA,IAAI,0BAA0B,SAAS,GACrC,MAAM,IAAI,MACR,2FACF;EAGF,MAAM,IAAI,MAAM,wBAAwB;CAC1C;CAEA,MAAc,qBACZ,OACwD;EACxD,MAAM,SAAS,gBAAgB,KAAK;EACpC,IAAI,CAAC,QACH,MAAM,IAAI,MAAM,sBAAsB;EAGxC,MAAM,MAAM,KAAK,qBAAqB,KAAK,UAAU,OAAO,KAAK;EACjE,MAAM,iBAAiB,MAAM,KAAK,QAAQ,IAAwB,GAAG;EACrE,IAAI,CAAC,gBACH;EAGF,IAAI,UAAU,eAAe,SAAS,GAAG;GACvC,MAAM,KAAK,QAAQ,OAAO,GAAG;GAC7B,MAAM,IAAI,MAAM,uBAAuB;EACzC;EAEA,OAAO;GAAE;GAAK,UAAU,eAAe;EAAS;CAClD;CAEA,MAAM,yBACJ,OACA,UACY;EACZ,OAAO,yBAAyB,IAAI,EAAE,MAAM,GAAG,QAAQ;CACzD;CAEA,MAAM,qBAAoC;EACxC,MAAM,UAAU,yBAAyB,SAAS;EAClD,IAAI,SAAS,WAAW;GACtB,MAAM,KAAK,QAAQ,OAAO,QAAQ,SAAS;GAC3C;EACF;EAEA,IAAI,SAAS;GACX,MAAM,SAAS,gBAAgB,QAAQ,KAAK;GAC5C,IAAI,QAAQ;IACV,MAAM,KAAK,QAAQ,OACjB,KAAK,qBAAqB,KAAK,UAAU,OAAO,KAAK,CACvD;IACA;GACF;EACF;EAEA,MAAM,OAAO,MAAM,KAAK,iBAAiB,KAAK,QAAQ;EACtD,IAAI,KAAK,SAAS,GAChB,MAAM,KAAK,QAAQ,OAAO,IAAI;CAElC;AACF"}
|
package/dist/mcp/x402.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"x402.js","names":[],"sources":["../../src/mcp/x402.ts"],"sourcesContent":["/**\n * X402 MCP Integration (v2)\n *\n * Based on:\n * - Coinbase's x402 (Apache 2.0): https://github.com/coinbase/x402\n * - @ethanniser and his work at https://github.com/ethanniser/x402-mcp\n */\n\nimport type {\n McpServer,\n RegisteredTool,\n ToolCallback\n} from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type {\n CallToolRequest,\n CallToolRequestOptions,\n Client as MCPClient\n} from \"@modelcontextprotocol/client\";\nimport type {\n CallToolResult,\n ToolAnnotations\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n bindMcpClient,\n type CallToolSchemaOrOptions,\n type CompatibleMcpClient,\n type LegacyCallToolResultSchema\n} from \"./client-invoker\";\nimport type { ZodRawShape } from \"zod\";\n\n// v2 imports from @x402/core\nimport { x402ResourceServer, HTTPFacilitatorClient } from \"@x402/core/server\";\nimport type { FacilitatorConfig, ResourceConfig } from \"@x402/core/server\";\nimport { x402Client } from \"@x402/core/client\";\nimport type {\n PaymentPayload,\n PaymentRequirements,\n PaymentRequired,\n Network\n} from \"@x402/core/types\";\n\n// v2 imports from @x402/evm\nimport { registerExactEvmScheme as registerServerEvmScheme } from \"@x402/evm/exact/server\";\nimport { registerExactEvmScheme as registerClientEvmScheme } from \"@x402/evm/exact/client\";\nimport type { ClientEvmSigner } from \"@x402/evm\";\n\n// Re-export commonly used types for consumer convenience\nexport type {\n PaymentRequirements,\n PaymentRequired,\n Network\n} from \"@x402/core/types\";\nexport type { FacilitatorConfig } from \"@x402/core/server\";\nexport type { ClientEvmSigner } from \"@x402/evm\";\n\n/**\n * Map of legacy v1 network names to CAIP-2 identifiers.\n * Allows backward compatibility with v1 config.\n */\nconst LEGACY_NETWORK_MAP: Record<string, string> = {\n \"base-sepolia\": \"eip155:84532\",\n base: \"eip155:8453\",\n ethereum: \"eip155:1\",\n sepolia: \"eip155:11155111\"\n};\n\n/**\n * Normalize a network identifier to CAIP-2 format.\n * Accepts both legacy v1 names (\"base-sepolia\") and CAIP-2 (\"eip155:84532\").\n */\nexport function normalizeNetwork(network: string): Network {\n return (LEGACY_NETWORK_MAP[network] ?? network) as Network;\n}\n\n/*\n ======= SERVER SIDE =======\n*/\n\nexport type X402Config = {\n /**\n * Network identifier.\n * Accepts both legacy names (\"base-sepolia\") and CAIP-2 format (\"eip155:84532\").\n */\n network: string;\n /** Payment recipient address */\n recipient: `0x${string}`;\n /** Facilitator configuration. Defaults to https://x402.org/facilitator */\n facilitator?: FacilitatorConfig;\n /** @deprecated No longer used in v2. The protocol version is determined automatically. */\n version?: number;\n};\n\nexport interface X402AugmentedServer {\n paidTool<Args extends ZodRawShape>(\n name: string,\n description: string,\n priceUSD: number,\n paramsSchema: Args,\n annotations: ToolAnnotations,\n cb: ToolCallback<Args>\n ): RegisteredTool;\n}\n\nexport function withX402<T extends McpServer>(\n server: T,\n cfg: X402Config\n): T & X402AugmentedServer {\n const network = normalizeNetwork(cfg.network);\n const facilitatorConfig: FacilitatorConfig = cfg.facilitator ?? {\n url: \"https://x402.org/facilitator\"\n };\n\n // Create v2 resource server with facilitator client\n const facilitatorClient = new HTTPFacilitatorClient(facilitatorConfig);\n const resourceServer = new x402ResourceServer(facilitatorClient);\n registerServerEvmScheme(resourceServer);\n\n // Lazy initialization: fetch supported kinds from facilitator on first use\n let initPromise: Promise<void> | null = null;\n function ensureInitialized(): Promise<void> {\n if (!initPromise) {\n initPromise = resourceServer.initialize().catch((err) => {\n initPromise = null; // allow retry on failure\n throw err;\n });\n }\n return initPromise;\n }\n\n function paidTool<Args extends ZodRawShape>(\n name: string,\n description: string,\n priceUSD: number,\n paramsSchema: Args,\n annotations: ToolAnnotations,\n cb: ToolCallback<Args>\n ): RegisteredTool {\n return server.registerTool(\n name,\n {\n description,\n inputSchema: paramsSchema,\n annotations,\n _meta: {\n \"agents-x402/paymentRequired\": true,\n \"agents-x402/priceUSD\": priceUSD\n }\n },\n (async (args, extra) => {\n await ensureInitialized();\n\n // Build v2 payment requirements for this tool call\n const resourceConfig: ResourceConfig = {\n scheme: \"exact\",\n payTo: cfg.recipient,\n price: priceUSD,\n network,\n maxTimeoutSeconds: 300\n };\n\n let requirements: PaymentRequirements[];\n try {\n requirements =\n await resourceServer.buildPaymentRequirements(resourceConfig);\n } catch {\n const payload = { x402Version: 2, error: \"PRICE_COMPUTE_FAILED\" };\n return {\n isError: true,\n _meta: { \"x402/error\": payload },\n content: [{ type: \"text\", text: JSON.stringify(payload) }]\n } as const;\n }\n\n const resourceInfo = {\n url: `x402://${name}`,\n description,\n mimeType: \"application/json\"\n };\n\n // Get payment token from MCP _meta or HTTP headers\n // Support both v2 (PAYMENT-SIGNATURE) and v1 (X-PAYMENT) header names\n const headers = extra?.requestInfo?.headers ?? {};\n const token =\n (extra?._meta?.[\"x402/payment\"] as string | undefined) ??\n headers[\"PAYMENT-SIGNATURE\"] ??\n headers[\"X-PAYMENT\"];\n\n const paymentRequired = (\n reason = \"PAYMENT_REQUIRED\",\n extraFields: Record<string, unknown> = {}\n ) => {\n const payload = {\n x402Version: 2,\n error: reason,\n resource: resourceInfo,\n accepts: requirements,\n ...extraFields\n };\n return {\n isError: true,\n _meta: { \"x402/error\": payload },\n content: [{ type: \"text\", text: JSON.stringify(payload) }]\n } as const;\n };\n\n if (!token || typeof token !== \"string\") return paymentRequired();\n\n // Decode the payment payload (base64-encoded JSON)\n let paymentPayload: PaymentPayload;\n try {\n paymentPayload = JSON.parse(atob(token));\n } catch {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n // Find matching requirements for this payment\n const matchingReq = resourceServer.findMatchingRequirements(\n requirements,\n paymentPayload\n );\n if (!matchingReq) {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n // Verify payment with facilitator\n try {\n const vr = await resourceServer.verifyPayment(\n paymentPayload,\n matchingReq\n );\n if (!vr.isValid) {\n return paymentRequired(vr.invalidReason ?? \"INVALID_PAYMENT\", {\n payer: vr.payer\n });\n }\n } catch {\n return paymentRequired(\"INVALID_PAYMENT\");\n }\n\n // Execute the tool callback\n let result: CallToolResult;\n let failed = false;\n try {\n result = await cb(args, extra);\n if (\n result &&\n typeof result === \"object\" &&\n \"isError\" in result &&\n result.isError\n ) {\n failed = true;\n }\n } catch (e) {\n failed = true;\n result = {\n isError: true,\n content: [\n { type: \"text\", text: `Tool execution failed: ${String(e)}` }\n ]\n };\n }\n\n // Settle payment only on success\n if (!failed) {\n try {\n const s = await resourceServer.settlePayment(\n paymentPayload,\n matchingReq\n );\n if (s.success) {\n result._meta ??= {};\n result._meta[\"x402/payment-response\"] = {\n success: true,\n transaction: s.transaction,\n network: s.network,\n payer: s.payer\n };\n } else {\n return paymentRequired(s.errorReason ?? \"SETTLEMENT_FAILED\");\n }\n } catch {\n return paymentRequired(\"SETTLEMENT_FAILED\");\n }\n }\n\n return result;\n }) as ToolCallback<Args>\n );\n }\n\n Object.defineProperty(server, \"paidTool\", {\n value: paidTool,\n writable: false,\n enumerable: false,\n configurable: true\n });\n\n // Tell TS the object now also has the paidTool method\n return server as T & X402AugmentedServer;\n}\n\n/*\n ======= CLIENT SIDE =======\n*/\n\nexport interface X402AugmentedClient {\n callTool(\n x402ConfirmationCallback:\n | ((payment: PaymentRequirements[]) => Promise<boolean>)\n | null,\n params: CallToolRequest[\"params\"],\n options?: CallToolRequestOptions\n ): Promise<CallToolResult>;\n /**\n * @deprecated Prefer the request-options overload. Explicit legacy result\n * schemas remain honored through the SDK v2 request funnel.\n */\n callTool(\n x402ConfirmationCallback:\n | ((payment: PaymentRequirements[]) => Promise<boolean>)\n | null,\n params: CallToolRequest[\"params\"],\n resultSchema: LegacyCallToolResultSchema,\n options?: CallToolRequestOptions\n ): Promise<CallToolResult>;\n}\n\nexport type X402ClientConfig = {\n /**\n * EVM account/signer for signing payment authorizations.\n * Use `privateKeyToAccount()` from viem/accounts to create one.\n */\n account: ClientEvmSigner;\n /**\n * Preferred network identifier (optional).\n * Accepts both legacy names (\"base-sepolia\") and CAIP-2 format (\"eip155:84532\").\n * When set, the client prefers payment requirements matching this network.\n * If omitted, the client automatically selects from available requirements.\n */\n network?: string;\n /** Maximum payment value in atomic units (default: 0.10 USDC = 100000) */\n maxPaymentValue?: bigint;\n /** @deprecated No longer used in v2. The protocol version is determined automatically. */\n version?: number;\n /** Confirmation callback for payment approval */\n confirmationCallback?: (payment: PaymentRequirements[]) => Promise<boolean>;\n};\n\nexport function withX402Client<T extends CompatibleMcpClient>(\n client: T,\n x402Config: X402ClientConfig\n): X402AugmentedClient & T {\n const invoker = bindMcpClient(client);\n const { account } = x402Config;\n\n const maxPaymentValue = x402Config.maxPaymentValue ?? BigInt(100_000); // 0.10 USDC\n\n // Create v2 x402 payment client with EVM scheme support\n const paymentClient = new x402Client();\n registerClientEvmScheme(paymentClient, { signer: account });\n\n // If a preferred network is specified, register a policy to prefer it\n if (x402Config.network) {\n const preferredNetwork = normalizeNetwork(x402Config.network);\n paymentClient.registerPolicy((_version, reqs) => {\n const matching = reqs.filter((r) => r.network === preferredNetwork);\n return matching.length > 0 ? matching : reqs;\n });\n }\n\n const listTools = async (\n params?: Parameters<MCPClient[\"listTools\"]>[0],\n options?: Parameters<MCPClient[\"listTools\"]>[1]\n ) => {\n const toolsRes = await invoker.listTools(params, options);\n return {\n ...toolsRes,\n tools: toolsRes.tools.map((tool) => {\n let description = tool.description;\n // Check _meta for payment information (agents-x402/ is our extension for pre-advertising prices)\n if (tool._meta?.[\"agents-x402/paymentRequired\"]) {\n const cost = tool._meta?.[\"agents-x402/priceUSD\"]\n ? `$${tool._meta?.[\"agents-x402/priceUSD\"]}`\n : \"an unknown amount\";\n description += ` (This is a paid tool, you will be charged ${cost} for its execution)`;\n }\n return {\n ...tool,\n description\n };\n })\n };\n };\n\n const callToolWithPayment = async (\n x402ConfirmationCallback:\n | ((payment: PaymentRequirements[]) => Promise<boolean>)\n | null,\n params: CallToolRequest[\"params\"],\n schemaOrOptions?: CallToolSchemaOrOptions,\n options?: CallToolRequestOptions\n ): ReturnType<MCPClient[\"callTool\"]> => {\n const invoke = (callParams: CallToolRequest[\"params\"]) =>\n invoker.callTool(callParams, schemaOrOptions, options);\n const res = await invoke(params);\n\n // Check for x402 payment required error in response metadata\n const maybeX402Error = res._meta?.[\"x402/error\"] as\n | (PaymentRequired & Record<string, unknown>)\n | undefined;\n\n if (\n res.isError &&\n maybeX402Error &&\n maybeX402Error.accepts &&\n Array.isArray(maybeX402Error.accepts) &&\n maybeX402Error.accepts.length > 0\n ) {\n const accepts = maybeX402Error.accepts;\n const confirmationCallback =\n x402ConfirmationCallback ?? x402Config.confirmationCallback;\n\n // Use the confirmation callback if provided\n if (confirmationCallback && !(await confirmationCallback(accepts))) {\n return {\n isError: true,\n content: [{ type: \"text\", text: \"User declined payment\" }]\n };\n }\n\n // Check max payment value against the first requirement's amount\n const selectedReq = accepts[0];\n if (!selectedReq || selectedReq.scheme !== \"exact\") return res;\n\n let amount: bigint;\n try {\n amount = BigInt(selectedReq.amount);\n } catch {\n return res; // malformed amount — return original error\n }\n if (amount > maxPaymentValue) {\n return {\n isError: true,\n content: [\n {\n type: \"text\",\n text: `Payment exceeds client cap: ${amount} > ${maxPaymentValue}`\n }\n ]\n };\n }\n\n // Reconstruct the PaymentRequired response for the v2 x402 client\n const paymentRequiredResponse: PaymentRequired = {\n x402Version: (maybeX402Error.x402Version as number) ?? 2,\n resource: (maybeX402Error.resource as PaymentRequired[\"resource\"]) ?? {\n url: \"\",\n description: \"\",\n mimeType: \"application/json\"\n },\n accepts,\n extensions: maybeX402Error.extensions as\n | Record<string, unknown>\n | undefined\n };\n\n // Create the payment payload using the v2 x402 client\n let paymentPayload: PaymentPayload;\n try {\n paymentPayload = await paymentClient.createPaymentPayload(\n paymentRequiredResponse\n );\n } catch {\n return {\n isError: true,\n content: [{ type: \"text\", text: \"Failed to create payment payload\" }]\n };\n }\n\n // Encode the payment payload as a base64 JSON token for MCP transport\n const token = btoa(JSON.stringify(paymentPayload));\n\n // Retry the tool call with the payment token\n return invoke({\n ...params,\n _meta: {\n ...params._meta,\n \"x402/payment\": token\n }\n });\n }\n\n return res;\n };\n\n const _client = client as X402AugmentedClient & T;\n Object.defineProperty(_client, \"listTools\", {\n value: listTools,\n writable: false,\n enumerable: false,\n configurable: true\n });\n Object.defineProperty(_client, \"callTool\", {\n value: callToolWithPayment,\n writable: false,\n enumerable: false,\n configurable: true\n });\n\n return _client;\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"protocol-Dqc2MQxo.js","names":[],"sources":["../src/chat/stream-accumulator.ts","../src/chat/broadcast-state.ts","../src/chat/protocol.ts"],"sourcesContent":["/**\n * StreamAccumulator — unified chunk-to-message builder.\n *\n * Used by @cloudflare/ai-chat (server + client) and @cloudflare/think\n * to incrementally build a UIMessage from stream chunks. Wraps\n * applyChunkToParts and handles the metadata chunk types (start, finish,\n * message-metadata, error) that applyChunkToParts does not cover.\n *\n * The accumulator signals domain-specific concerns (early persistence,\n * cross-message tool updates) via ChunkAction returns — callers handle\n * these according to their context.\n */\n\nimport type { UIMessage } from \"ai\";\nimport { applyChunkToParts, type StreamChunkData } from \"./message-builder\";\n\nfunction asMetadata(value: unknown): Record<string, unknown> | undefined {\n if (value != null && typeof value === \"object\" && !Array.isArray(value)) {\n return value as Record<string, unknown>;\n }\n return undefined;\n}\n\nexport interface StreamAccumulatorOptions {\n messageId: string;\n continuation?: boolean;\n existingParts?: UIMessage[\"parts\"];\n existingMetadata?: Record<string, unknown>;\n}\n\nexport type ChunkAction =\n | {\n type: \"start\";\n messageId?: string;\n metadata?: Record<string, unknown>;\n }\n | {\n type: \"finish\";\n finishReason?: string;\n metadata?: Record<string, unknown>;\n }\n | { type: \"message-metadata\"; metadata: Record<string, unknown> }\n | { type: \"tool-approval-request\"; toolCallId: string }\n | {\n type: \"cross-message-tool-update\";\n updateType: \"output-available\" | \"output-error\";\n toolCallId: string;\n output?: unknown;\n errorText?: string;\n preliminary?: boolean;\n }\n | { type: \"error\"; error: string };\n\nexport interface ChunkResult {\n handled: boolean;\n action?: ChunkAction;\n}\n\nexport class StreamAccumulator {\n messageId: string;\n readonly parts: UIMessage[\"parts\"];\n metadata?: Record<string, unknown>;\n private _isContinuation: boolean;\n\n constructor(options: StreamAccumulatorOptions) {\n this.messageId = options.messageId;\n this._isContinuation = options.continuation ?? false;\n this.parts = options.existingParts ? [...options.existingParts] : [];\n this.metadata = options.existingMetadata\n ? { ...options.existingMetadata }\n : undefined;\n }\n\n applyChunk(chunk: StreamChunkData): ChunkResult {\n const handled = applyChunkToParts(this.parts, chunk);\n\n // Detect tool-approval-request for early persistence signaling\n if (chunk.type === \"tool-approval-request\" && chunk.toolCallId) {\n return {\n handled,\n action: { type: \"tool-approval-request\", toolCallId: chunk.toolCallId }\n };\n }\n\n // Detect cross-message tool output/error: applyChunkToParts returns true\n // for recognized types but silently does nothing when the toolCallId\n // doesn't exist in the current parts array.\n if (\n (chunk.type === \"tool-output-available\" ||\n chunk.type === \"tool-output-error\") &&\n chunk.toolCallId\n ) {\n const foundInParts = this.parts.some(\n (p) => \"toolCallId\" in p && p.toolCallId === chunk.toolCallId\n );\n if (!foundInParts) {\n return {\n handled,\n action: {\n type: \"cross-message-tool-update\",\n updateType:\n chunk.type === \"tool-output-available\"\n ? \"output-available\"\n : \"output-error\",\n toolCallId: chunk.toolCallId,\n output: chunk.output,\n errorText: chunk.errorText,\n preliminary: chunk.preliminary\n }\n };\n }\n }\n\n if (!handled) {\n switch (chunk.type) {\n case \"start\": {\n if (chunk.messageId != null && !this._isContinuation) {\n this.messageId = chunk.messageId;\n }\n const startMeta = asMetadata(chunk.messageMetadata);\n if (startMeta) {\n this.metadata = this.metadata\n ? { ...this.metadata, ...startMeta }\n : { ...startMeta };\n }\n return {\n handled: true,\n action: {\n type: \"start\",\n messageId: chunk.messageId,\n metadata: startMeta\n }\n };\n }\n case \"finish\": {\n const finishMeta = asMetadata(chunk.messageMetadata);\n if (finishMeta) {\n this.metadata = this.metadata\n ? { ...this.metadata, ...finishMeta }\n : { ...finishMeta };\n }\n const finishReason =\n \"finishReason\" in chunk\n ? (chunk.finishReason as string)\n : undefined;\n return {\n handled: true,\n action: {\n type: \"finish\",\n finishReason,\n metadata: finishMeta\n }\n };\n }\n case \"message-metadata\": {\n const msgMeta = asMetadata(chunk.messageMetadata);\n if (msgMeta) {\n this.metadata = this.metadata\n ? { ...this.metadata, ...msgMeta }\n : { ...msgMeta };\n }\n return {\n handled: true,\n action: {\n type: \"message-metadata\",\n metadata: msgMeta ?? {}\n }\n };\n }\n case \"finish-step\": {\n return { handled: true };\n }\n case \"error\": {\n return {\n handled: true,\n action: {\n type: \"error\",\n error: chunk.errorText ?? JSON.stringify(chunk)\n }\n };\n }\n }\n }\n\n return { handled };\n }\n\n /** Snapshot the current state as a UIMessage. */\n toMessage(): UIMessage {\n return {\n id: this.messageId,\n role: \"assistant\",\n parts: [...this.parts],\n ...(this.metadata != null && { metadata: this.metadata })\n } as UIMessage;\n }\n\n /**\n * Merge this accumulator's message into an existing message array.\n * Handles continuation (walk backward for last assistant), replacement\n * (update existing by messageId), or append (new message).\n */\n mergeInto(messages: UIMessage[]): UIMessage[] {\n let existingIdx = messages.findIndex((m) => m.id === this.messageId);\n\n if (existingIdx < 0 && this._isContinuation) {\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"assistant\") {\n existingIdx = i;\n break;\n }\n }\n }\n\n const messageId =\n existingIdx >= 0 ? messages[existingIdx].id : this.messageId;\n\n const partialMessage: UIMessage = {\n id: messageId,\n role: \"assistant\",\n parts: [...this.parts],\n ...(this.metadata != null && { metadata: this.metadata })\n } as UIMessage;\n\n if (existingIdx >= 0) {\n const updated = [...messages];\n updated[existingIdx] = partialMessage;\n return updated;\n }\n return [...messages, partialMessage];\n }\n}\n","/**\n * Broadcast stream state machine.\n *\n * Manages the lifecycle of a StreamAccumulator for broadcast/resume\n * streams — the path where this client is *observing* a stream owned\n * by another tab or resumed after reconnect, rather than the transport-\n * owned path that feeds directly into useChat.\n *\n * The transition function is pure (no React, no WebSocket, no side\n * effects). Callers dispatch events and apply the returned state +\n * messagesUpdate. Side effects (sending ACKs, calling onData) stay\n * in the caller.\n */\n\nimport type { UIMessage } from \"ai\";\nimport { StreamAccumulator } from \"./stream-accumulator\";\nimport type { StreamChunkData } from \"./message-builder\";\n\n// ── State ──────────────────────────────────────────────────────────\n\nexport type BroadcastStreamState =\n | { status: \"idle\" }\n | {\n status: \"observing\";\n streamId: string;\n accumulator: StreamAccumulator;\n };\n\n// ── Events ─────────────────────────────────────────────────────────\n\nexport type BroadcastStreamEvent =\n | {\n type: \"response\";\n streamId: string;\n /** Fallback message ID for a new accumulator (ignored if one exists for this stream). */\n messageId: string;\n chunkData?: unknown;\n done?: boolean;\n error?: boolean;\n replay?: boolean;\n replayComplete?: boolean;\n continuation?: boolean;\n /** Required when continuation=true so the accumulator can pick up existing parts. */\n currentMessages?: UIMessage[];\n }\n | {\n type: \"resume-fallback\";\n streamId: string;\n messageId: string;\n }\n | { type: \"clear\" };\n\n// ── Result ─────────────────────────────────────────────────────────\n\nexport interface TransitionResult {\n state: BroadcastStreamState;\n messagesUpdate?: (prev: UIMessage[]) => UIMessage[];\n isStreaming: boolean;\n}\n\n// ── Transition ─────────────────────────────────────────────────────\n\nexport function transition(\n state: BroadcastStreamState,\n event: BroadcastStreamEvent\n): TransitionResult {\n switch (event.type) {\n case \"clear\":\n return { state: { status: \"idle\" }, isStreaming: false };\n\n case \"resume-fallback\": {\n const accumulator = new StreamAccumulator({\n messageId: event.messageId\n });\n return {\n state: {\n status: \"observing\",\n streamId: event.streamId,\n accumulator\n },\n isStreaming: true\n };\n }\n\n case \"response\": {\n let accumulator: StreamAccumulator;\n\n // A replayed `start` chunk means the server is re-sending the stream\n // buffer from chunk 0 (resume replay). Re-initialize the accumulator\n // instead of appending into an existing one: replaying into an\n // accumulator that already holds this stream's parts would duplicate\n // them (a second `text-start` unconditionally opens a second text\n // part — #1733). Re-initializing makes replay idempotent under any\n // number of replays, including a second replay triggered by a\n // duplicate STREAM_RESUMING → ACK cycle or a reconnect.\n const isReplayedStart =\n event.replay === true &&\n (event.chunkData as { type?: string } | null | undefined)?.type ===\n \"start\";\n\n if (\n state.status === \"idle\" ||\n state.streamId !== event.streamId ||\n isReplayedStart\n ) {\n let messageId = event.messageId;\n let existingParts: UIMessage[\"parts\"] | undefined;\n let existingMetadata: Record<string, unknown> | undefined;\n\n if (event.continuation && event.currentMessages) {\n for (let i = event.currentMessages.length - 1; i >= 0; i--) {\n if (event.currentMessages[i].role === \"assistant\") {\n messageId = event.currentMessages[i].id;\n existingParts = [...event.currentMessages[i].parts];\n if (event.currentMessages[i].metadata != null) {\n existingMetadata = {\n ...(event.currentMessages[i].metadata as Record<\n string,\n unknown\n >)\n };\n }\n break;\n }\n }\n }\n\n accumulator = new StreamAccumulator({\n messageId,\n continuation: event.continuation,\n existingParts,\n existingMetadata\n });\n } else {\n accumulator = state.accumulator;\n }\n\n if (event.chunkData) {\n accumulator.applyChunk(event.chunkData as StreamChunkData);\n }\n\n let messagesUpdate: ((prev: UIMessage[]) => UIMessage[]) | undefined;\n\n if (event.done) {\n messagesUpdate = (prev) => accumulator.mergeInto(prev);\n return {\n state: { status: \"idle\" },\n messagesUpdate,\n isStreaming: false\n };\n }\n\n if (event.chunkData && !event.replay) {\n messagesUpdate = (prev) => accumulator.mergeInto(prev);\n } else if (event.replayComplete) {\n messagesUpdate = (prev) => accumulator.mergeInto(prev);\n }\n\n return {\n state: {\n status: \"observing\",\n streamId: event.streamId,\n accumulator\n },\n messagesUpdate,\n isStreaming: true\n };\n }\n }\n}\n","/**\n * Wire protocol message type constants for the cf_agent_chat_* protocol.\n *\n * These are the string values used on the wire between agent servers and\n * clients. Both @cloudflare/ai-chat (via its MessageType enum) and\n * @cloudflare/think use these values.\n */\nexport const STREAM_RESUME_NONE_REASONS = {\n /** No active, pending, or terminal stream exists for this agent. */\n IDLE: \"idle\",\n /** An active tool continuation is owned by another live connection. */\n CONTINUATION_OWNED: \"continuation-owned\"\n} as const;\n\nexport type StreamResumeNoneReason =\n (typeof STREAM_RESUME_NONE_REASONS)[keyof typeof STREAM_RESUME_NONE_REASONS];\n\nexport const CHAT_MESSAGE_TYPES = {\n CHAT_MESSAGES: \"cf_agent_chat_messages\",\n USE_CHAT_REQUEST: \"cf_agent_use_chat_request\",\n USE_CHAT_RESPONSE: \"cf_agent_use_chat_response\",\n CHAT_CLEAR: \"cf_agent_chat_clear\",\n CHAT_REQUEST_CANCEL: \"cf_agent_chat_request_cancel\",\n STREAM_RESUMING: \"cf_agent_stream_resuming\",\n STREAM_RESUME_ACK: \"cf_agent_stream_resume_ack\",\n STREAM_RESUME_REQUEST: \"cf_agent_stream_resume_request\",\n STREAM_RESUME_NONE: \"cf_agent_stream_resume_none\",\n // Server→client: a turn has been accepted but its resumable stream has not\n // started yet (queued, debouncing, waiting on MCP setup, or running async\n // work in `onChatMessage`). Sent in response to a resume request (or on\n // connect) so a reconnecting/re-mounting client keeps its expectation instead\n // of resolving its resume probe to \"no stream\" and then false-timing-out the\n // turn. Resolved by a later `STREAM_RESUMING` (stream started) or\n // `STREAM_RESUME_NONE` (turn settled without streaming). Backward-compatible —\n // clients that don't understand it ignore it. See issue #1784.\n STREAM_PENDING: \"cf_agent_stream_pending\",\n TOOL_RESULT: \"cf_agent_tool_result\",\n TOOL_APPROVAL: \"cf_agent_tool_approval\",\n MESSAGE_UPDATED: \"cf_agent_message_updated\",\n // Server→client: a durable chat turn is being recovered (interrupted by a\n // deploy/eviction or a stream-stall watchdog abort and now resuming). Sent\n // when a recovery continuation is scheduled and cleared on every terminal\n // outcome; `@cloudflare/think` also replays it on connect so a client that\n // joins mid-recovery learns it. Purely a progress hint — backward-compatible\n // (clients that don't understand it ignore it). See issue #1620.\n CHAT_RECOVERING: \"cf_agent_chat_recovering\"\n} as const;\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ws-chat-transport-CIoOBbO7.js","names":[],"sources":["../src/chat/ws-chat-transport.ts"],"sourcesContent":["/**\n * Framework-neutral WebSocket transport for AI SDK chat clients.\n *\n * Speaks the CF_AGENT protocol directly and returns AI SDK UI message chunks\n * without reconstructing an HTTP response or parsing an SSE stream.\n */\n\nimport type { ChatTransport, UIMessage, UIMessageChunk } from \"ai\";\nimport { nanoid } from \"nanoid\";\nimport { MessageType, type OutgoingMessage } from \"./wire-types\";\n\n/**\n * Short safety-net timeout for a resume probe when the server has said nothing.\n * Under normal operation the server answers a `STREAM_RESUME_REQUEST` with\n * `STREAM_RESUMING`, `STREAM_RESUME_NONE`, or `STREAM_PENDING` well before this.\n */\nconst RESUME_PROBE_TIMEOUT_MS = 5000;\n\n/**\n * Extended backstop applied once the server says a turn is pending\n * (`STREAM_PENDING`, #1784). The pre-stream window (queueing, MCP setup,\n * debounce, model latency) can exceed the short probe timeout, and the server\n * guarantees a follow-up `STREAM_RESUMING` or `STREAM_RESUME_NONE` — so we wait\n * much longer (refreshed on every keep-waiting frame) but still cap it so a\n * dropped follow-up degrades to a null resolve instead of hanging forever.\n */\nconst RESUME_PENDING_TIMEOUT_MS = 60000;\n\n/**\n * Agent-like interface for sending/receiving WebSocket messages.\n * Matches `AgentClient` from `agents/client` and the connection returned by\n * `useAgent` from `agents/react`.\n */\nexport interface AgentConnection {\n send: (data: string) => void;\n addEventListener: (\n type: string,\n listener: (event: MessageEvent) => void,\n options?: { signal?: AbortSignal }\n ) => void;\n removeEventListener: (\n type: string,\n listener: (event: MessageEvent) => void\n ) => void;\n}\n\nexport type WebSocketChatTransportOptions<\n ChatMessage extends UIMessage = UIMessage\n> = {\n /** The framework-neutral AgentClient or useAgent connection. */\n agent: AgentConnection;\n /**\n * Callback to add custom fields to the request body before sending.\n */\n prepareBody?: (options: {\n messages: ChatMessage[];\n trigger: \"submit-message\" | \"regenerate-message\";\n messageId?: string;\n }) => Promise<Record<string, unknown>> | Record<string, unknown>;\n /**\n * Optional set to track active request IDs.\n * IDs are added when a request starts and removed when it completes.\n * Used by the onAgentMessage handler to skip messages already handled by the transport.\n */\n activeRequestIds?: Set<string>;\n /**\n * Whether generic client-side abort/cancel lifecycle should cancel the\n * server turn. Explicit cancellation via cancelActiveServerTurn() always\n * sends CF_AGENT_CHAT_REQUEST_CANCEL.\n * @default false\n */\n cancelOnClientAbort?: boolean;\n};\n\n/**\n * ChatTransport that sends messages over WebSocket and returns a\n * ReadableStream<UIMessageChunk> that the AI SDK's useChat consumes directly.\n *\n * This low-level transport handles new and regenerated request streams plus\n * cancellation. Higher-level protocol coordination such as automatic reconnect\n * resume, cross-tab transcript synchronization, and client-tool continuations\n * is provided by integrations such as `useAgentChat`.\n */\nexport class WebSocketChatTransport<\n ChatMessage extends UIMessage = UIMessage\n> implements ChatTransport<ChatMessage> {\n agent: AgentConnection;\n private prepareBody?: WebSocketChatTransportOptions<ChatMessage>[\"prepareBody\"];\n private activeRequestIds?: Set<string>;\n private cancelOnClientAbort: boolean;\n\n // Pending resume resolver — set by reconnectToStream, called by\n // handleStreamResuming when onAgentMessage sees CF_AGENT_STREAM_RESUMING.\n private _resumeResolver: ((data: { id: string }) => void) | null = null;\n // Pending \"no stream\" resolver — called by handleStreamResumeNone\n // when onAgentMessage sees CF_AGENT_STREAM_RESUME_NONE.\n private _resumeNoneResolver:\n | ((data: { probeId?: string }) => boolean)\n | null = null;\n // Keep-waiting hook (#1784) — set by whichever resume path is currently\n // awaiting, called by handleStreamPending when onAgentMessage sees\n // CF_AGENT_STREAM_PENDING. Extends the path's probe timeout so a slow\n // pre-stream window (queue / MCP / model latency) does not resolve early.\n private _onStreamPending: (() => void) | null = null;\n // Retransmits the current handshake on a replacement socket without starting\n // a second AI SDK resume request. Set only while a resolver is active.\n private _retryResumeProbe: (() => void) | null = null;\n // Set when a client-side tool result/approval is expected to trigger\n // a new continuation stream. In this mode reconnectToStream() returns\n // a deferred ReadableStream immediately so AI SDK status can transition\n // to \"submitted\" before the server starts streaming.\n private _expectToolContinuation = false;\n private _abortToolContinuation: (() => boolean) | null = null;\n private _activeServerTurnId: string | null = null;\n private _cancelAttachedStream: (() => boolean) | null = null;\n // Local-only detach for a resume stream owned by an obsolete Chat/agent\n // generation. Unlike explicit cancellation, this never cancels server work.\n private _detachResumeStream: (() => boolean) | null = null;\n\n constructor(options: WebSocketChatTransportOptions<ChatMessage>) {\n this.agent = options.agent;\n this.prepareBody = options.prepareBody;\n this.activeRequestIds = options.activeRequestIds;\n this.cancelOnClientAbort = options.cancelOnClientAbort ?? false;\n }\n\n /**\n * Point the singleton transport at a new Agent connection. A pending resolver\n * belongs to the old Chat/socket generation and must settle before messages\n * from the replacement connection can be consumed (#1914 review).\n */\n setAgent(agent: AgentConnection) {\n if (this.agent === agent) return;\n this.resetResumeState();\n this.agent = agent;\n }\n\n setCancelOnClientAbort(cancelOnClientAbort: boolean) {\n this.cancelOnClientAbort = cancelOnClientAbort;\n }\n\n /**\n * Explicitly cancel the active server turn, if any.\n * This is separate from generic client-side abort/cancel lifecycle so\n * clients can detach locally without stopping server work.\n */\n cancelActiveServerTurn(): boolean {\n const requestId = this._activeServerTurnId;\n let cancelledRequest = false;\n\n if (requestId) {\n this.sendCancelFrame(requestId);\n this._cancelAttachedStream?.();\n this.clearActiveServerTurn(requestId);\n cancelledRequest = true;\n }\n\n const cancelledToolContinuation = this.abortActiveToolContinuation();\n return cancelledRequest || cancelledToolContinuation;\n }\n\n private sendCancelFrame(requestId: string) {\n try {\n this.agent.send(\n JSON.stringify({\n id: requestId,\n type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL\n })\n );\n } catch {\n // Ignore failures (e.g. agent already disconnected)\n }\n }\n\n private setActiveServerTurn(\n requestId: string,\n cancelAttachedStream: (() => boolean) | null\n ) {\n this._activeServerTurnId = requestId;\n this._cancelAttachedStream = cancelAttachedStream;\n }\n\n private clearActiveServerTurn(requestId: string) {\n if (this._activeServerTurnId === requestId) {\n this._activeServerTurnId = null;\n this._cancelAttachedStream = null;\n }\n }\n\n /**\n * Mark that the next reconnectToStream() call should attach to a\n * server-initiated tool continuation rather than a page-load resume.\n */\n expectToolContinuation() {\n this._expectToolContinuation = true;\n }\n\n /**\n * Abort the active client-side tool continuation stream, if one is attached\n * to a server request id.\n */\n abortActiveToolContinuation(): boolean {\n return this._abortToolContinuation?.() ?? false;\n }\n\n /**\n * True when the transport is waiting for a resume handshake.\n */\n isAwaitingResume(): boolean {\n return this._resumeResolver !== null || this._resumeNoneResolver !== null;\n }\n\n /**\n * Settle and detach the current handshake without interpreting it as a\n * server-idle response. Used when the owning hook/agent generation changes.\n */\n cancelPendingResume(): boolean {\n const resolveNone = this._resumeNoneResolver;\n if (!resolveNone) return false;\n return resolveNone({});\n }\n\n /**\n * Invalidate all client-side resume state for an obsolete hook/agent\n * generation without cancelling its durable server turn.\n */\n resetResumeState(): void {\n this._expectToolContinuation = false;\n this.cancelPendingResume();\n this._detachResumeStream?.();\n }\n\n /**\n * Re-send the active handshake request on the latest socket generation. This\n * preserves one AI SDK resume operation while recovering a request/reply lost\n * with the previous WebSocket.\n */\n retryPendingResume(): boolean {\n const retry = this._retryResumeProbe;\n if (!retry) return false;\n retry();\n return true;\n }\n\n /**\n * Called by onAgentMessage when it receives CF_AGENT_STREAM_RESUMING.\n * If reconnectToStream is waiting, this handles the resume handshake\n * (ACK + stream creation) and returns true. Otherwise returns false\n * so the caller can use its own fallback path.\n */\n handleStreamResuming(data: { id: string }): boolean {\n if (!this._resumeResolver) return false;\n this._resumeResolver(data);\n return true;\n }\n\n /**\n * Called by onAgentMessage when it receives CF_AGENT_STREAM_RESUME_NONE.\n * If reconnectToStream is waiting, resolves the promise with null\n * immediately (no 5-second timeout). Returns true if handled.\n */\n handleStreamResumeNone(data: { probeId?: string } = {}): boolean {\n if (!this._resumeNoneResolver) return false;\n return this._resumeNoneResolver(data);\n }\n\n /**\n * Called by onAgentMessage when it receives CF_AGENT_STREAM_PENDING (#1784):\n * the server accepted a turn but its stream has not started yet. If a resume\n * path is awaiting, extend its probe timeout (so it keeps waiting for the\n * eventual STREAM_RESUMING / STREAM_RESUME_NONE instead of resolving null\n * after the short window). Returns true if a waiting path consumed it.\n */\n handleStreamPending(): boolean {\n if (!this._onStreamPending) return false;\n this._onStreamPending();\n return true;\n }\n\n /**\n * Called by the hook's shared message handler when a server turn finishes\n * outside the currently attached transport stream, such as after local-only\n * client cleanup.\n */\n handleServerTurnCompleted(requestId: string) {\n this.clearActiveServerTurn(requestId);\n }\n\n /**\n * Register a server turn that is being rendered outside a transport-owned\n * stream, such as the hook's fallback cross-tab/resume observer path.\n */\n observeServerTurn(requestId: string) {\n this.setActiveServerTurn(requestId, null);\n }\n\n async sendMessages(options: {\n chatId: string;\n messages: ChatMessage[];\n abortSignal: AbortSignal | undefined;\n trigger: \"submit-message\" | \"regenerate-message\";\n messageId?: string;\n body?: object;\n headers?: Record<string, string> | Headers;\n metadata?: unknown;\n }): Promise<ReadableStream<UIMessageChunk>> {\n const requestId = nanoid(8);\n const abortController = new AbortController();\n let completed = false;\n let requestSent = false;\n\n // Build the request body\n let extraBody: Record<string, unknown> = {};\n if (this.prepareBody) {\n extraBody = await this.prepareBody({\n messages: options.messages,\n trigger: options.trigger,\n messageId: options.messageId\n });\n }\n if (options.body) {\n extraBody = {\n ...extraBody,\n ...(options.body as Record<string, unknown>)\n };\n }\n\n const bodyPayload = JSON.stringify({\n messages: options.messages,\n trigger: options.trigger,\n ...extraBody\n });\n\n // Track this request so the onAgentMessage handler skips it\n this.activeRequestIds?.add(requestId);\n\n // Create a ReadableStream<UIMessageChunk> that emits parsed chunks\n // as they arrive over the WebSocket\n const agent = this.agent;\n const activeIds = this.activeRequestIds;\n\n // Single cleanup helper — every terminal path (done, error, abort)\n // goes through here exactly once.\n // keepId: when true, do NOT remove requestId from activeIds. Used by\n // explicit cancellation so onAgentMessage skips in-flight chunks\n // and the server's final done:true signal until cleanup happens there.\n const finish = (\n action: () => void,\n keepId = false,\n clearServerTurn = true\n ) => {\n if (completed) return;\n completed = true;\n if (clearServerTurn) {\n this.clearActiveServerTurn(requestId);\n }\n try {\n action();\n } catch {\n // Stream may already be closed\n }\n if (!keepId) {\n activeIds?.delete(requestId);\n }\n abortController.abort();\n };\n\n const abortError = new Error(\"Aborted\");\n abortError.name = \"AbortError\";\n\n const cancelActiveRequest = () => {\n if (completed) return false;\n finish(() => streamController.error(abortError), true);\n return true;\n };\n this.setActiveServerTurn(requestId, cancelActiveRequest);\n\n // Abort handler: terminate the local stream. By default, generic AI SDK\n // abort/cancel lifecycle is local-only so durable server turns can continue\n // and be resumed. Use cancelActiveServerTurn() for explicit user/app\n // cancellation, or cancelOnClientAbort for request-lifetime semantics.\n const onAbort = () => {\n if (completed) return;\n if (this.cancelOnClientAbort) {\n if (requestSent) {\n this.sendCancelFrame(requestId);\n }\n finish(() => streamController.error(abortError), requestSent);\n } else {\n finish(() => streamController.error(abortError), false, !requestSent);\n }\n };\n\n // streamController is assigned synchronously by start(), so it is\n // always available by the time onAbort or onMessage can fire.\n let streamController!: ReadableStreamDefaultController<UIMessageChunk>;\n\n const stream = new ReadableStream<UIMessageChunk>({\n start(controller) {\n streamController = controller;\n\n const onMessage = (event: MessageEvent) => {\n try {\n const data = JSON.parse(\n event.data as string\n ) as OutgoingMessage<ChatMessage>;\n\n if (data.type !== MessageType.CF_AGENT_USE_CHAT_RESPONSE) return;\n if (data.id !== requestId) return;\n\n if (data.error) {\n finish(() =>\n controller.error(new Error(data.body || \"Stream error\"))\n );\n return;\n }\n\n // Parse the body as UIMessageChunk and enqueue\n if (data.body?.trim()) {\n try {\n const chunk = JSON.parse(data.body) as UIMessageChunk;\n controller.enqueue(chunk);\n } catch {\n // Skip malformed chunk bodies\n }\n }\n\n if (data.done) {\n finish(() => controller.close());\n }\n } catch {\n // Ignore non-JSON messages\n }\n };\n\n const onClose = () => {\n finish(() => controller.close(), false, false);\n };\n\n agent.addEventListener(\"message\", onMessage, {\n signal: abortController.signal\n });\n agent.addEventListener(\"close\", onClose, {\n signal: abortController.signal\n });\n },\n cancel() {\n onAbort();\n }\n });\n\n // Handle abort from the caller\n if (options.abortSignal) {\n options.abortSignal.addEventListener(\"abort\", onAbort, { once: true });\n if (options.abortSignal.aborted) onAbort();\n }\n\n if (completed) {\n return stream;\n }\n\n // Send the request over WebSocket\n requestSent = true;\n agent.send(\n JSON.stringify({\n id: requestId,\n init: {\n method: \"POST\",\n body: bodyPayload\n },\n type: MessageType.CF_AGENT_USE_CHAT_REQUEST\n })\n );\n\n return stream;\n }\n\n async reconnectToStream(_options: {\n chatId: string;\n }): Promise<ReadableStream<UIMessageChunk> | null> {\n // A transport has one handshake slot. Returning null for an unexpected\n // concurrent caller is safer than overwriting callbacks owned by the first\n // AI SDK request (StrictMode/manual overlap); the hook serializes its normal\n // mount, tool, public, and reconnect entry points.\n if (this.isAwaitingResume()) return null;\n\n if (this._expectToolContinuation) {\n this._expectToolContinuation = false;\n return this._createToolContinuationStream();\n }\n\n // Detect whether the server has an active stream for this chat.\n // Instead of registering another message listener (which races with the\n // hook), expose identity-owned callbacks consumed synchronously by the\n // shared handler.\n const activeIds = this.activeRequestIds;\n const probeId = nanoid(8);\n\n return new Promise<ReadableStream<UIMessageChunk> | null>((resolve) => {\n let resolved = false;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let resumeResolver: ((data: { id: string }) => void) | null = null;\n let resumeNoneResolver: ((data: { probeId?: string }) => boolean) | null =\n null;\n let onStreamPending: (() => void) | null = null;\n let retryResumeProbe: (() => void) | null = null;\n\n const clearOwnedCallbacks = () => {\n if (resumeResolver && this._resumeResolver === resumeResolver) {\n this._resumeResolver = null;\n }\n if (\n resumeNoneResolver &&\n this._resumeNoneResolver === resumeNoneResolver\n ) {\n this._resumeNoneResolver = null;\n }\n if (onStreamPending && this._onStreamPending === onStreamPending) {\n this._onStreamPending = null;\n }\n if (retryResumeProbe && this._retryResumeProbe === retryResumeProbe) {\n this._retryResumeProbe = null;\n }\n };\n\n const done = (value: ReadableStream<UIMessageChunk> | null) => {\n if (resolved) return;\n resolved = true;\n clearOwnedCallbacks();\n if (timeout) clearTimeout(timeout);\n resolve(value);\n };\n\n const armTimeout = (delay: number) => {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => done(null), delay);\n };\n\n // Keep-waiting (#1784): the server says a turn is accepted but its stream\n // has not started. Extend this operation's own timeout only.\n onStreamPending = () => {\n if (resolved) return;\n armTimeout(RESUME_PENDING_TIMEOUT_MS);\n };\n\n resumeNoneResolver = (data) => {\n if (data.probeId && data.probeId !== probeId) return false;\n done(null);\n return true;\n };\n\n resumeResolver = (data: { id: string }) => {\n const requestId = data.id;\n activeIds?.add(requestId);\n const stream = this._createResumeStream(requestId);\n\n this.agent.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_STREAM_RESUME_ACK,\n id: requestId\n })\n );\n\n done(stream);\n };\n\n // Re-arm both the request and timeout on each replacement socket. This is\n // a retransmission of this resolver's handshake, not a second Chat resume.\n retryResumeProbe = () => {\n if (resolved) return;\n armTimeout(RESUME_PROBE_TIMEOUT_MS);\n try {\n this.agent.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_STREAM_RESUME_REQUEST,\n probeId\n })\n );\n } catch {\n // The next socket open retries again; the timeout remains a backstop.\n }\n };\n\n this._onStreamPending = onStreamPending;\n this._resumeNoneResolver = resumeNoneResolver;\n this._resumeResolver = resumeResolver;\n this._retryResumeProbe = retryResumeProbe;\n retryResumeProbe();\n });\n }\n\n /**\n * Creates a deferred ReadableStream for client-side tool continuations.\n * The stream is returned immediately so AI SDK status becomes \"submitted\"\n * right after addToolOutput()/addToolApprovalResponse(), then it waits for\n * the server to announce the continuation via STREAM_RESUMING.\n */\n private _createToolContinuationStream(): ReadableStream<UIMessageChunk> {\n const agent = this.agent;\n const activeIds = this.activeRequestIds;\n const streamController = new AbortController();\n const abortError = new Error(\"Aborted\");\n abortError.name = \"AbortError\";\n let completed = false;\n let requestId: string | null = null;\n let readerController: ReadableStreamDefaultController<UIMessageChunk> | null =\n null;\n const probeId = nanoid(8);\n let onResumeRef: ((data: { id: string }) => void) | null = null;\n let onResumeNoneRef: ((data: { probeId?: string }) => boolean) | null =\n null;\n let onStreamPendingRef: (() => void) | null = null;\n let retryResumeProbeRef: (() => void) | null = null;\n let abortToolContinuationRef: (() => boolean) | null = null;\n let detachResumeStreamRef: (() => boolean) | null = null;\n\n const clearOwnedHandshake = () => {\n if (onResumeRef && this._resumeResolver === onResumeRef) {\n this._resumeResolver = null;\n }\n if (onResumeNoneRef && this._resumeNoneResolver === onResumeNoneRef) {\n this._resumeNoneResolver = null;\n }\n if (onStreamPendingRef && this._onStreamPending === onStreamPendingRef) {\n this._onStreamPending = null;\n }\n if (\n retryResumeProbeRef &&\n this._retryResumeProbe === retryResumeProbeRef\n ) {\n this._retryResumeProbe = null;\n }\n };\n\n const finish = (action: () => void, keepRequestId = false) => {\n if (completed) return;\n completed = true;\n if (this._abortToolContinuation === abortToolContinuationRef) {\n this._abortToolContinuation = null;\n }\n if (this._detachResumeStream === detachResumeStreamRef) {\n this._detachResumeStream = null;\n }\n clearOwnedHandshake();\n try {\n action();\n } catch {\n // Stream may already be closed\n }\n if (requestId && !keepRequestId) {\n activeIds?.delete(requestId);\n }\n streamController.abort();\n };\n\n const transport = this;\n\n abortToolContinuationRef = () => {\n if (completed) return false;\n\n if (requestId === null) {\n finish(() => readerController?.error(abortError));\n return true;\n }\n\n try {\n agent.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_CHAT_REQUEST_CANCEL,\n id: requestId\n })\n );\n } catch {\n // Ignore failures (e.g. agent already disconnected)\n }\n\n // Keep the ID so the shared message handler ignores in-flight chunks\n // until the server's terminal frame performs its normal cleanup.\n finish(() => readerController?.error(abortError), true);\n return true;\n };\n this._abortToolContinuation = abortToolContinuationRef;\n detachResumeStreamRef = () => {\n if (completed) return false;\n finish(() => readerController?.close());\n return true;\n };\n this._detachResumeStream = detachResumeStreamRef;\n\n return new ReadableStream<UIMessageChunk>({\n start(controller) {\n readerController = controller;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n\n const armTimeout = (delay: number) => {\n if (timeout) clearTimeout(timeout);\n timeout = setTimeout(() => finish(() => controller.close()), delay);\n };\n\n const onResumeNone = (data: { probeId?: string }) => {\n if (data.probeId && data.probeId !== probeId) return false;\n finish(() => controller.close());\n return true;\n };\n\n const onResume = (data: { id: string }) => {\n if (requestId) return;\n\n requestId = data.id;\n activeIds?.add(requestId);\n clearOwnedHandshake();\n if (timeout) clearTimeout(timeout);\n\n agent.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_STREAM_RESUME_ACK,\n id: requestId\n })\n );\n };\n\n const onStreamPending = () => {\n if (completed) return;\n armTimeout(RESUME_PENDING_TIMEOUT_MS);\n };\n\n const retryResumeProbe = () => {\n if (completed || requestId !== null) return;\n armTimeout(RESUME_PROBE_TIMEOUT_MS);\n try {\n transport.agent.send(\n JSON.stringify({\n type: MessageType.CF_AGENT_STREAM_RESUME_REQUEST,\n probeId\n })\n );\n } catch {\n // A later socket open can retry this same deferred handshake.\n }\n };\n\n onResumeRef = onResume;\n onResumeNoneRef = onResumeNone;\n onStreamPendingRef = onStreamPending;\n retryResumeProbeRef = retryResumeProbe;\n transport._resumeResolver = onResume;\n transport._resumeNoneResolver = onResumeNone;\n transport._onStreamPending = onStreamPending;\n transport._retryResumeProbe = retryResumeProbe;\n\n const onMessage = (event: MessageEvent) => {\n try {\n const data = JSON.parse(\n event.data as string\n ) as OutgoingMessage<UIMessage>;\n\n if (\n data.type !== MessageType.CF_AGENT_USE_CHAT_RESPONSE ||\n requestId == null ||\n data.id !== requestId\n ) {\n return;\n }\n\n if (data.error) {\n finish(() =>\n controller.error(new Error(data.body || \"Stream error\"))\n );\n return;\n }\n\n if (data.body?.trim()) {\n try {\n const chunk = JSON.parse(data.body) as UIMessageChunk;\n controller.enqueue(chunk);\n } catch {\n // Skip malformed chunk bodies\n }\n }\n\n if (data.done) {\n finish(() => controller.close());\n }\n } catch {\n // Ignore non-JSON messages\n }\n };\n\n const onClose = () => finish(() => controller.close());\n\n agent.addEventListener(\"message\", onMessage, {\n signal: streamController.signal\n });\n agent.addEventListener(\"close\", onClose, {\n signal: streamController.signal\n });\n\n retryResumeProbe();\n },\n cancel() {\n if (requestId && transport.cancelOnClientAbort) {\n transport.sendCancelFrame(requestId);\n finish(() => {}, true);\n } else {\n finish(() => {});\n }\n }\n });\n }\n\n /**\n * Creates a ReadableStream that receives resumed stream chunks\n * and forwards them to useChat as UIMessageChunk objects.\n */\n private _createResumeStream(\n requestId: string\n ): ReadableStream<UIMessageChunk> {\n // Read agent at resolve time (not when reconnectToStream was called)\n // so chunk listener attaches to the latest socket after _pk changes.\n const agent = this.agent;\n const activeIds = this.activeRequestIds;\n const chunkController = new AbortController();\n const abortError = new Error(\"Aborted\");\n abortError.name = \"AbortError\";\n let completed = false;\n let detachResumeStream: (() => boolean) | null = null;\n\n const finish = (\n action: () => void,\n keepId = false,\n clearServerTurn = true\n ) => {\n if (completed) return;\n completed = true;\n if (clearServerTurn) {\n this.clearActiveServerTurn(requestId);\n }\n if (this._detachResumeStream === detachResumeStream) {\n this._detachResumeStream = null;\n }\n try {\n action();\n } catch {\n // Stream may already be closed\n }\n if (!keepId) {\n activeIds?.delete(requestId);\n }\n chunkController.abort();\n };\n\n let streamController: ReadableStreamDefaultController<UIMessageChunk> | null =\n null;\n const cancelActiveRequest = () => {\n if (completed) return false;\n finish(() => streamController?.error(abortError), true);\n return true;\n };\n this.setActiveServerTurn(requestId, cancelActiveRequest);\n\n const transport = this;\n detachResumeStream = () => {\n if (completed) return false;\n finish(() => streamController?.close());\n return true;\n };\n this._detachResumeStream = detachResumeStream;\n\n return new ReadableStream<UIMessageChunk>({\n start(controller) {\n streamController = controller;\n\n const onMessage = (event: MessageEvent) => {\n try {\n const data = JSON.parse(\n event.data as string\n ) as OutgoingMessage<UIMessage>;\n\n if (data.type !== MessageType.CF_AGENT_USE_CHAT_RESPONSE) return;\n if (data.id !== requestId) return;\n\n if (data.error) {\n finish(() =>\n controller.error(new Error(data.body || \"Stream error\"))\n );\n return;\n }\n\n // Parse and enqueue the chunk\n if (data.body?.trim()) {\n try {\n const chunk = JSON.parse(data.body) as UIMessageChunk;\n controller.enqueue(chunk);\n } catch {\n // Skip malformed chunk bodies\n }\n }\n\n if (data.done) {\n finish(() => controller.close());\n }\n } catch {\n // Ignore non-JSON messages\n }\n };\n\n const onClose = () => {\n finish(() => controller.close(), false, false);\n };\n\n agent.addEventListener(\"message\", onMessage, {\n signal: chunkController.signal\n });\n agent.addEventListener(\"close\", onClose, {\n signal: chunkController.signal\n });\n },\n cancel() {\n if (transport.cancelOnClientAbort) {\n transport.sendCancelFrame(requestId);\n finish(() => {}, true);\n } else {\n finish(() => {}, false, false);\n }\n }\n });\n }\n}\n"],"mappings":"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"}
|