agents 0.14.0 → 0.14.1

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.
Files changed (66) hide show
  1. package/dist/{agent-tool-types-LInzZfLo.d.ts → agent-tool-types-BAJWu8s4.d.ts} +19 -9
  2. package/dist/agent-tool-types.d.ts +1 -1
  3. package/dist/{agent-tools-BE9xosUG.d.ts → agent-tools-0R6KEert.d.ts} +2 -2
  4. package/dist/{agent-tools-BAdX1vdI.js → agent-tools-DYrkT-Kx.js} +46 -6
  5. package/dist/agent-tools-DYrkT-Kx.js.map +1 -0
  6. package/dist/agent-tools.d.ts +1 -1
  7. package/dist/browser/ai.d.ts +1 -1
  8. package/dist/browser/ai.js +1 -1
  9. package/dist/browser/index.d.ts +1 -1
  10. package/dist/browser/index.js +1 -1
  11. package/dist/browser/tanstack-ai.d.ts +1 -1
  12. package/dist/browser/tanstack-ai.js +1 -1
  13. package/dist/chat/index.d.ts +26 -2
  14. package/dist/chat/index.js +3 -3
  15. package/dist/chat-sdk/index.d.ts +2 -2
  16. package/dist/chat-sdk/index.js +2 -2
  17. package/dist/chat-sdk/index.js.map +1 -1
  18. package/dist/{classPrivateFieldGet2-Evpt0SEr.js → classPrivateFieldGet2-D_obpP6O.js} +5 -5
  19. package/dist/{classPrivateMethodInitSpec-bG0tD96O.js → classPrivateMethodInitSpec-10iTYB7F.js} +2 -2
  20. package/dist/{client-NradHZZz.js → client-FUizKzj2.js} +94 -21
  21. package/dist/client-FUizKzj2.js.map +1 -0
  22. package/dist/client.d.ts +1 -1
  23. package/dist/{compaction-helpers-DpP_XP9J.d.ts → compaction-helpers-BEUILPss.d.ts} +1 -1
  24. package/dist/{compaction-helpers-BjT2NKRZ.js → compaction-helpers-iiKMr2TQ.js} +1 -1
  25. package/dist/{compaction-helpers-BjT2NKRZ.js.map → compaction-helpers-iiKMr2TQ.js.map} +1 -1
  26. package/dist/{do-oauth-client-provider-CPm9rK5I.d.ts → do-oauth-client-provider-D4ZwyBDu.d.ts} +21 -1
  27. package/dist/{email-1fTSJwPm.d.ts → email-CL27preh.d.ts} +1 -1
  28. package/dist/email.d.ts +2 -2
  29. package/dist/experimental/memory/session/index.d.ts +1 -1
  30. package/dist/experimental/memory/session/index.js +1 -1
  31. package/dist/experimental/memory/utils/index.d.ts +1 -1
  32. package/dist/experimental/memory/utils/index.js +2 -2
  33. package/dist/{index-Brdu5nMI.d.ts → index-RJ4OxMOe.d.ts} +1 -1
  34. package/dist/index.d.ts +6 -6
  35. package/dist/index.js +26 -9
  36. package/dist/index.js.map +1 -1
  37. package/dist/{internal_context-CcZy2Em7.d.ts → internal_context-Dg4Cgjcu.d.ts} +1 -1
  38. package/dist/internal_context.d.ts +1 -1
  39. package/dist/mcp/client.d.ts +1 -1
  40. package/dist/mcp/client.js +1 -1
  41. package/dist/mcp/do-oauth-client-provider.d.ts +1 -1
  42. package/dist/mcp/do-oauth-client-provider.js +143 -17
  43. package/dist/mcp/do-oauth-client-provider.js.map +1 -1
  44. package/dist/mcp/index.d.ts +1 -1
  45. package/dist/mcp/index.js +1 -1
  46. package/dist/observability/index.d.ts +1 -1
  47. package/dist/react.d.ts +1 -1
  48. package/dist/react.js +1 -1
  49. package/dist/{retries-ClWwxADl.d.ts → retries-CF_HKSlJ.d.ts} +1 -1
  50. package/dist/retries.d.ts +1 -1
  51. package/dist/serializable.d.ts +1 -1
  52. package/dist/{shared-CpY1FLvm.d.ts → shared-4CAYLCTO.d.ts} +1 -1
  53. package/dist/{shared-DdOn6sp4.js → shared-BIpUk4G5.js} +3 -3
  54. package/dist/{shared-DdOn6sp4.js.map → shared-BIpUk4G5.js.map} +1 -1
  55. package/dist/skills/index.js +2 -2
  56. package/dist/sub-routing.d.ts +1 -1
  57. package/dist/{tool-output-truncation-BF4AZQlw.js → tool-output-truncation-CNnnGZQ3.js} +1 -1
  58. package/dist/{tool-output-truncation-BF4AZQlw.js.map → tool-output-truncation-CNnnGZQ3.js.map} +1 -1
  59. package/dist/{types-B0GymtN_.d.ts → types-6Zo2zfoO.d.ts} +1 -1
  60. package/dist/types.d.ts +1 -1
  61. package/dist/{workflow-types-DPkuBi--.d.ts → workflow-types-SrZK_o9p.d.ts} +1 -1
  62. package/dist/workflow-types.d.ts +1 -1
  63. package/dist/workflows.d.ts +2 -2
  64. package/package.json +11 -11
  65. package/dist/agent-tools-BAdX1vdI.js.map +0 -1
  66. package/dist/client-NradHZZz.js.map +0 -1
@@ -34,4 +34,4 @@ export {
34
34
  __DO_NOT_USE_WILL_BREAK__agentContext as r,
35
35
  AgentContextStore as t
36
36
  };
37
- //# sourceMappingURL=internal_context-CcZy2Em7.d.ts.map
37
+ //# sourceMappingURL=internal_context-Dg4Cgjcu.d.ts.map
@@ -2,5 +2,5 @@ import {
2
2
  n as AgentEmail,
3
3
  r as __DO_NOT_USE_WILL_BREAK__agentContext,
4
4
  t as AgentContextStore
5
- } from "./internal_context-CcZy2Em7.js";
5
+ } from "./internal_context-Dg4Cgjcu.js";
6
6
  export { AgentContextStore, AgentEmail, __DO_NOT_USE_WILL_BREAK__agentContext };
@@ -12,7 +12,7 @@ import {
12
12
  ut as MCPClientOAuthCallbackConfig,
13
13
  vt as RegisterServerOptions,
14
14
  yt as getNamespacedData
15
- } from "../agent-tool-types-LInzZfLo.js";
15
+ } from "../agent-tool-types-BAJWu8s4.js";
16
16
  export {
17
17
  MCPClientManager,
18
18
  MCPClientManagerOptions,
@@ -1,2 +1,2 @@
1
- import { i as normalizeServerId, n as MCP_SERVER_ID_MAX_LENGTH, r as getNamespacedData, t as MCPClientManager } from "../client-NradHZZz.js";
1
+ import { i as normalizeServerId, n as MCP_SERVER_ID_MAX_LENGTH, r as getNamespacedData, t as MCPClientManager } from "../client-FUizKzj2.js";
2
2
  export { MCPClientManager, MCP_SERVER_ID_MAX_LENGTH, getNamespacedData, normalizeServerId };
@@ -2,7 +2,7 @@ import {
2
2
  n as AgentsOAuthProvider,
3
3
  r as DurableObjectOAuthClientProvider,
4
4
  t as AgentMcpOAuthProvider
5
- } from "../do-oauth-client-provider-CPm9rK5I.js";
5
+ } from "../do-oauth-client-provider-D4ZwyBDu.js";
6
6
  export {
7
7
  AgentMcpOAuthProvider,
8
8
  AgentsOAuthProvider,
@@ -1,6 +1,30 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
1
2
  import { nanoid } from "nanoid";
2
3
  //#region src/mcp/do-oauth-client-provider.ts
3
4
  const STATE_EXPIRATION_MS = 600 * 1e3;
5
+ const codeVerifierStateStorage = new AsyncLocalStorage();
6
+ function parseOAuthState(state) {
7
+ const parts = state.split(".");
8
+ if (parts.length !== 2) return;
9
+ const [nonce, serverId] = parts;
10
+ if (!nonce || !serverId) return;
11
+ return {
12
+ nonce,
13
+ serverId
14
+ };
15
+ }
16
+ function base64UrlEncode(bytes) {
17
+ let binary = "";
18
+ for (const byte of bytes) binary += String.fromCharCode(byte);
19
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
20
+ }
21
+ async function createCodeChallenge(verifier) {
22
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
23
+ return base64UrlEncode(new Uint8Array(digest));
24
+ }
25
+ function isExpired(createdAt) {
26
+ return Date.now() - createdAt > STATE_EXPIRATION_MS;
27
+ }
4
28
  var DurableObjectOAuthClientProvider = class {
5
29
  constructor(storage, clientName, baseRedirectUrl) {
6
30
  this.storage = storage;
@@ -80,12 +104,12 @@ var DurableObjectOAuthClientProvider = class {
80
104
  return state;
81
105
  }
82
106
  async checkState(state) {
83
- const parts = state.split(".");
84
- if (parts.length !== 2) return {
107
+ const parsed = parseOAuthState(state);
108
+ if (!parsed) return {
85
109
  valid: false,
86
110
  error: "Invalid state format"
87
111
  };
88
- const [nonce, serverId] = parts;
112
+ const { nonce, serverId } = parsed;
89
113
  const key = this.stateKey(nonce);
90
114
  const storedState = await this.storage.get(key);
91
115
  if (!storedState) return {
@@ -99,8 +123,10 @@ var DurableObjectOAuthClientProvider = class {
99
123
  error: "State serverId mismatch"
100
124
  };
101
125
  }
102
- if (Date.now() - storedState.createdAt > STATE_EXPIRATION_MS) {
103
- await this.storage.delete(key);
126
+ if (isExpired(storedState.createdAt)) {
127
+ const deleteKeys = [key];
128
+ if (this._clientId_) deleteKeys.push(this.stateCodeVerifierKey(this.clientId, nonce));
129
+ await this.storage.delete(deleteKeys);
104
130
  return {
105
131
  valid: false,
106
132
  error: "State expired"
@@ -112,40 +138,140 @@ var DurableObjectOAuthClientProvider = class {
112
138
  };
113
139
  }
114
140
  async consumeState(state) {
115
- const parts = state.split(".");
116
- if (parts.length !== 2) {
141
+ const parsed = parseOAuthState(state);
142
+ if (!parsed) {
117
143
  console.warn(`[OAuth] consumeState called with invalid state format`);
118
144
  return;
119
145
  }
120
- const [nonce] = parts;
121
- await this.storage.delete(this.stateKey(nonce));
146
+ await this.storage.delete(this.stateKey(parsed.nonce));
122
147
  }
123
148
  async redirectToAuthorization(authUrl) {
124
149
  this._authUrl_ = authUrl.toString();
150
+ const clientId = this._clientId_;
151
+ const serverId = this._serverId_;
152
+ if (!clientId || !serverId) return;
153
+ const state = authUrl.searchParams.get("state");
154
+ const codeChallenge = authUrl.searchParams.get("code_challenge");
155
+ if (!state || !codeChallenge) return;
156
+ const parsed = parseOAuthState(state);
157
+ if (!parsed || parsed.serverId !== serverId) return;
158
+ const challengeKey = this.challengeCodeVerifierKey(clientId, codeChallenge);
159
+ const pendingVerifier = await this.storage.get(challengeKey);
160
+ if (!pendingVerifier) return;
161
+ if (isExpired(pendingVerifier.createdAt)) {
162
+ await this.storage.delete(challengeKey);
163
+ return;
164
+ }
165
+ await this.storage.put(this.stateCodeVerifierKey(clientId, parsed.nonce), pendingVerifier);
166
+ await this.storage.delete(challengeKey);
125
167
  }
126
168
  async invalidateCredentials(scope) {
127
169
  if (!this._clientId_) return;
128
170
  const deleteKeys = [];
129
171
  if (scope === "all" || scope === "client") deleteKeys.push(this.clientInfoKey(this.clientId));
130
172
  if (scope === "all" || scope === "tokens") deleteKeys.push(this.tokenKey(this.clientId));
131
- if (scope === "all" || scope === "verifier") deleteKeys.push(this.codeVerifierKey(this.clientId));
173
+ if (scope === "all" || scope === "verifier") deleteKeys.push(...await this.codeVerifierKeys(this.clientId, { includeChallengeKeys: true }));
132
174
  if (deleteKeys.length > 0) await this.storage.delete(deleteKeys);
133
175
  }
134
176
  codeVerifierKey(clientId) {
135
177
  return `${this.keyPrefix(clientId)}/code_verifier`;
136
178
  }
179
+ stateCodeVerifierPrefix(clientId) {
180
+ return `${this.keyPrefix(clientId)}/code_verifier/`;
181
+ }
182
+ stateCodeVerifierKey(clientId, nonce) {
183
+ return `${this.stateCodeVerifierPrefix(clientId)}${nonce}`;
184
+ }
185
+ challengeCodeVerifierPrefix(clientId) {
186
+ return `${this.keyPrefix(clientId)}/code_verifier_challenge/`;
187
+ }
188
+ challengeCodeVerifierKey(clientId, codeChallenge) {
189
+ return `${this.challengeCodeVerifierPrefix(clientId)}${codeChallenge}`;
190
+ }
191
+ async codeVerifierKeys(clientId, options = {}) {
192
+ const legacyKey = this.codeVerifierKey(clientId);
193
+ const keys = [];
194
+ if (await this.storage.get(legacyKey)) keys.push(legacyKey);
195
+ const stateKeys = await this.storage.list({ prefix: this.stateCodeVerifierPrefix(clientId) });
196
+ keys.push(...stateKeys.keys());
197
+ if (options.includeChallengeKeys) {
198
+ const challengeKeys = await this.storage.list({ prefix: this.challengeCodeVerifierPrefix(clientId) });
199
+ keys.push(...challengeKeys.keys());
200
+ }
201
+ return keys;
202
+ }
137
203
  async saveCodeVerifier(verifier) {
138
- const key = this.codeVerifierKey(this.clientId);
139
- if (await this.storage.get(key)) return;
140
- await this.storage.put(key, verifier);
204
+ await this.deleteExpiredChallengeCodeVerifiers(this.clientId);
205
+ const codeChallenge = await createCodeChallenge(verifier);
206
+ const storedVerifier = {
207
+ verifier,
208
+ createdAt: Date.now()
209
+ };
210
+ await this.storage.put(this.challengeCodeVerifierKey(this.clientId, codeChallenge), storedVerifier);
211
+ }
212
+ async deleteExpiredChallengeCodeVerifiers(clientId) {
213
+ const expiredKeys = [...(await this.storage.list({ prefix: this.challengeCodeVerifierPrefix(clientId) })).entries()].filter(([, storedVerifier]) => isExpired(storedVerifier.createdAt)).map(([key]) => key);
214
+ if (expiredKeys.length > 0) await this.storage.delete(expiredKeys);
141
215
  }
142
216
  async codeVerifier() {
143
- const codeVerifier = await this.storage.get(this.codeVerifierKey(this.clientId));
144
- if (!codeVerifier) throw new Error("No code verifier found");
145
- return codeVerifier;
217
+ const context = codeVerifierStateStorage.getStore();
218
+ if (context) {
219
+ const stateVerifier = await this.codeVerifierForState(context.state);
220
+ if (stateVerifier) {
221
+ context.servedKey = stateVerifier.key;
222
+ return stateVerifier.verifier;
223
+ }
224
+ }
225
+ const legacyVerifier = await this.storage.get(this.codeVerifierKey(this.clientId));
226
+ if (legacyVerifier) {
227
+ if (context) context.servedKey = this.codeVerifierKey(this.clientId);
228
+ return legacyVerifier;
229
+ }
230
+ if (context) throw new Error("No code verifier found for OAuth state");
231
+ const pendingVerifiers = await this.storage.list({ prefix: this.stateCodeVerifierPrefix(this.clientId) });
232
+ const unexpiredPendingVerifiers = [...pendingVerifiers.entries()].filter(([, storedVerifier]) => !isExpired(storedVerifier.createdAt));
233
+ const expiredKeys = [...pendingVerifiers.entries()].filter(([, storedVerifier]) => isExpired(storedVerifier.createdAt)).map(([key]) => key);
234
+ if (expiredKeys.length > 0) await this.storage.delete(expiredKeys);
235
+ if (unexpiredPendingVerifiers.length === 1) {
236
+ const [[, storedVerifier]] = unexpiredPendingVerifiers;
237
+ return storedVerifier.verifier;
238
+ }
239
+ if (unexpiredPendingVerifiers.length > 1) throw new Error("Multiple OAuth code verifiers are pending; complete authorization with the callback state");
240
+ throw new Error("No code verifier found");
241
+ }
242
+ async codeVerifierForState(state) {
243
+ const parsed = parseOAuthState(state);
244
+ if (!parsed) throw new Error("Invalid state format");
245
+ const key = this.stateCodeVerifierKey(this.clientId, parsed.nonce);
246
+ const storedVerifier = await this.storage.get(key);
247
+ if (!storedVerifier) return;
248
+ if (isExpired(storedVerifier.createdAt)) {
249
+ await this.storage.delete(key);
250
+ throw new Error("Code verifier expired");
251
+ }
252
+ return {
253
+ key,
254
+ verifier: storedVerifier.verifier
255
+ };
256
+ }
257
+ async runWithCodeVerifierState(state, callback) {
258
+ return codeVerifierStateStorage.run({ state }, callback);
146
259
  }
147
260
  async deleteCodeVerifier() {
148
- await this.storage.delete(this.codeVerifierKey(this.clientId));
261
+ const context = codeVerifierStateStorage.getStore();
262
+ if (context?.servedKey) {
263
+ await this.storage.delete(context.servedKey);
264
+ return;
265
+ }
266
+ if (context) {
267
+ const parsed = parseOAuthState(context.state);
268
+ if (parsed) {
269
+ await this.storage.delete(this.stateCodeVerifierKey(this.clientId, parsed.nonce));
270
+ return;
271
+ }
272
+ }
273
+ const keys = await this.codeVerifierKeys(this.clientId);
274
+ if (keys.length > 0) await this.storage.delete(keys);
149
275
  }
150
276
  };
151
277
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"do-oauth-client-provider.js","names":[],"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\";\nimport { nanoid } from \"nanoid\";\n\nconst STATE_EXPIRATION_MS = 10 * 60 * 1000; // 10 minutes\n\ninterface StoredState {\n nonce: string;\n serverId: 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 deleteCodeVerifier(): Promise<void>;\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 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 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 parts = state.split(\".\");\n if (parts.length !== 2) {\n return { valid: false, error: \"Invalid state format\" };\n }\n\n const [nonce, serverId] = parts;\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 const age = Date.now() - storedState.createdAt;\n if (age > STATE_EXPIRATION_MS) {\n await this.storage.delete(key);\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 parts = state.split(\".\");\n if (parts.length !== 2) {\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 const [nonce] = parts;\n await this.storage.delete(this.stateKey(nonce));\n }\n\n async redirectToAuthorization(authUrl: URL): Promise<void> {\n this._authUrl_ = authUrl.toString();\n }\n\n async invalidateCredentials(\n scope: \"all\" | \"client\" | \"tokens\" | \"verifier\"\n ): Promise<void> {\n if (!this._clientId_) return;\n\n const deleteKeys: string[] = [];\n\n if (scope === \"all\" || scope === \"client\") {\n deleteKeys.push(this.clientInfoKey(this.clientId));\n }\n if (scope === \"all\" || scope === \"tokens\") {\n deleteKeys.push(this.tokenKey(this.clientId));\n }\n if (scope === \"all\" || scope === \"verifier\") {\n deleteKeys.push(this.codeVerifierKey(this.clientId));\n }\n\n if (deleteKeys.length > 0) {\n await this.storage.delete(deleteKeys);\n }\n }\n\n codeVerifierKey(clientId: string) {\n return `${this.keyPrefix(clientId)}/code_verifier`;\n }\n\n async saveCodeVerifier(verifier: string): Promise<void> {\n const key = this.codeVerifierKey(this.clientId);\n\n // Don't overwrite existing verifier to preserve first PKCE verifier\n const existing = await this.storage.get<string>(key);\n if (existing) {\n return;\n }\n\n await this.storage.put(key, 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 async deleteCodeVerifier(): Promise<void> {\n await this.storage.delete(this.codeVerifierKey(this.clientId));\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"do-oauth-client-provider.js","names":[],"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\";\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 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 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\"\n ): Promise<void> {\n if (!this._clientId_) return;\n\n const deleteKeys: string[] = [];\n\n if (scope === \"all\" || scope === \"client\") {\n deleteKeys.push(this.clientInfoKey(this.clientId));\n }\n if (scope === \"all\" || scope === \"tokens\") {\n deleteKeys.push(this.tokenKey(this.clientId));\n }\n if (scope === \"all\" || scope === \"verifier\") {\n deleteKeys.push(\n ...(await this.codeVerifierKeys(this.clientId, {\n includeChallengeKeys: true\n }))\n );\n }\n\n if (deleteKeys.length > 0) {\n await this.storage.delete(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":"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"}
@@ -28,7 +28,7 @@ import {
28
28
  wt as RPCServerTransportOptions,
29
29
  xt as RPCClientTransport,
30
30
  zt as WorkerTransportOptions
31
- } from "../agent-tool-types-LInzZfLo.js";
31
+ } from "../agent-tool-types-BAJWu8s4.js";
32
32
  export {
33
33
  type ClearableEventStore,
34
34
  type CreateMcpHandlerOptions,
package/dist/mcp/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "../types.js";
2
- import { c as RPC_DO_PREFIX, i as normalizeServerId, n as MCP_SERVER_ID_MAX_LENGTH, o as RPCClientTransport, s as RPCServerTransport } from "../client-NradHZZz.js";
2
+ import { c as RPC_DO_PREFIX, i as normalizeServerId, n as MCP_SERVER_ID_MAX_LENGTH, o as RPCClientTransport, s as RPCServerTransport } from "../client-FUizKzj2.js";
3
3
  import { Agent, getAgentByName, getCurrentAgent } from "../index.js";
4
4
  import { AsyncLocalStorage } from "node:async_hooks";
5
5
  import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
@@ -5,7 +5,7 @@ import {
5
5
  o as subscribe,
6
6
  r as ObservabilityEvent,
7
7
  t as ChannelEventMap
8
- } from "../index-Brdu5nMI.js";
8
+ } from "../index-RJ4OxMOe.js";
9
9
  export {
10
10
  ChannelEventMap,
11
11
  Observability,
package/dist/react.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  B as MCPServersState,
3
3
  u as AgentToolRunState
4
- } from "./agent-tool-types-LInzZfLo.js";
4
+ } from "./agent-tool-types-BAJWu8s4.js";
5
5
  import { ClientParameters } from "./serializable.js";
6
6
  import {
7
7
  AgentPromiseReturnType,
package/dist/react.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import "./types.js";
2
2
  import { camelCaseToKebabCase } from "./utils.js";
3
3
  import { createStubProxy } from "./client.js";
4
- import { n as createAgentToolEventState, t as applyAgentToolEvent } from "./agent-tools-BAdX1vdI.js";
4
+ import { n as createAgentToolEventState, t as applyAgentToolEvent } from "./agent-tools-DYrkT-Kx.js";
5
5
  import { usePartySocket } from "partysocket/react";
6
6
  import { use, useCallback, useEffect, useMemo, useRef, useState } from "react";
7
7
  //#region src/react.tsx
@@ -76,4 +76,4 @@ export {
76
76
  jitterBackoff as r,
77
77
  RetryOptions as t
78
78
  };
79
- //# sourceMappingURL=retries-ClWwxADl.d.ts.map
79
+ //# sourceMappingURL=retries-CF_HKSlJ.d.ts.map
package/dist/retries.d.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  n as isErrorRetryable,
5
5
  r as jitterBackoff,
6
6
  t as RetryOptions
7
- } from "./retries-ClWwxADl.js";
7
+ } from "./retries-CF_HKSlJ.js";
8
8
  export {
9
9
  RetryOptions,
10
10
  isErrorRetryable,
@@ -1,4 +1,4 @@
1
- import { Q as StreamingResponse } from "./agent-tool-types-LInzZfLo.js";
1
+ import { Q as StreamingResponse } from "./agent-tool-types-BAJWu8s4.js";
2
2
 
3
3
  //#region src/serializable.d.ts
4
4
  type SerializablePrimitive = undefined | null | string | number | boolean;
@@ -31,4 +31,4 @@ export {
31
31
  SEARCH_DESCRIPTION as r,
32
32
  BrowserToolsOptions as t
33
33
  };
34
- //# sourceMappingURL=shared-CpY1FLvm.d.ts.map
34
+ //# sourceMappingURL=shared-4CAYLCTO.d.ts.map
@@ -1,5 +1,5 @@
1
- import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-Evpt0SEr.js";
2
- import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-bG0tD96O.js";
1
+ import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-D_obpP6O.js";
2
+ import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-10iTYB7F.js";
3
3
  import { DynamicWorkerExecutor } from "@cloudflare/codemode";
4
4
  //#region src/browser/cdp-session.ts
5
5
  const DEFAULT_TIMEOUT_MS = 1e4;
@@ -429,4 +429,4 @@ function createBrowserToolHandlers(options) {
429
429
  //#endregion
430
430
  export { connectBrowser as a, CdpSession as i, SEARCH_DESCRIPTION as n, connectUrl as o, createBrowserToolHandlers as r, EXECUTE_DESCRIPTION as t };
431
431
 
432
- //# sourceMappingURL=shared-DdOn6sp4.js.map
432
+ //# sourceMappingURL=shared-BIpUk4G5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shared-DdOn6sp4.js","names":[],"sources":["../src/browser/cdp-session.ts","../src/browser/truncate.ts","../src/browser/shared.ts"],"sourcesContent":["interface PendingCommand {\n resolve: (result: unknown) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n method: string;\n sessionId?: string;\n startedAt: number;\n}\n\ninterface DebugEntry {\n at: string;\n type: string;\n [key: string]: unknown;\n}\n\nexport interface CdpSendOptions {\n timeoutMs?: number;\n sessionId?: string;\n}\n\nexport interface CdpAttachOptions {\n timeoutMs?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst MAX_DEBUG_ENTRIES = 400;\n\n/**\n * A CDP session over an open WebSocket. Manages command correlation,\n * timeouts, target sessions, and a debug event ring buffer.\n *\n * Used host-side (not in the sandbox) — the sandbox calls into this\n * via DynamicWorkerExecutor's ToolDispatcher RPC.\n */\nexport class CdpSession {\n #socket: WebSocket;\n #nextId = 1;\n #pending = new Map<number, PendingCommand>();\n #debugLog: DebugEntry[] = [];\n #defaultTimeoutMs: number;\n #dispose?: () => void;\n\n constructor(\n socket: WebSocket,\n defaultTimeoutMs = DEFAULT_TIMEOUT_MS,\n dispose?: () => void\n ) {\n this.#socket = socket;\n this.#defaultTimeoutMs = defaultTimeoutMs;\n this.#dispose = dispose;\n\n socket.addEventListener(\"message\", (event) => this.#handleMessage(event));\n socket.addEventListener(\"error\", () => {\n this.#rejectAll(new Error(\"CDP socket error\"));\n });\n socket.addEventListener(\"close\", () => {\n this.#rejectAll(new Error(\"CDP connection closed\"));\n });\n }\n\n send(\n method: string,\n params?: unknown,\n options: CdpSendOptions = {}\n ): Promise<unknown> {\n const id = this.#nextId++;\n const timeoutMs = options.timeoutMs ?? this.#defaultTimeoutMs;\n const sessionId =\n typeof options.sessionId === \"string\" && options.sessionId.length > 0\n ? options.sessionId\n : undefined;\n\n const domain = typeof method === \"string\" ? method.split(\".\")[0] : \"\";\n if (!sessionId && domain && ![\"Browser\", \"Target\"].includes(domain)) {\n this.#recordDebug(\"warning\", {\n id,\n method,\n reason: \"target-scoped method sent without sessionId\"\n });\n }\n\n const result = new Promise<unknown>((resolve, reject) => {\n const startedAt = performance.now();\n const timeoutId = setTimeout(() => {\n this.#pending.delete(id);\n reject(\n new Error(`CDP command timed out after ${timeoutMs}ms: ${method}`)\n );\n }, timeoutMs);\n this.#pending.set(id, {\n resolve,\n reject,\n timeoutId,\n method,\n sessionId,\n startedAt\n });\n });\n\n this.#recordDebug(\"send\", { id, method, sessionId, timeoutMs });\n this.#socket.send(JSON.stringify({ id, method, params, sessionId }));\n return result;\n }\n\n async attachToTarget(\n targetId: string,\n options: CdpAttachOptions = {}\n ): Promise<string> {\n if (typeof targetId !== \"string\" || !targetId) {\n throw new Error(\"attachToTarget requires a targetId\");\n }\n\n const result = (await this.send(\n \"Target.attachToTarget\",\n {\n targetId,\n flatten: true\n },\n { timeoutMs: options.timeoutMs }\n )) as { sessionId?: string };\n\n const sessionId = result?.sessionId ?? \"\";\n if (!sessionId) {\n throw new Error(\n `Target.attachToTarget did not return a sessionId for target ${targetId}`\n );\n }\n\n this.#recordDebug(\"attach\", { targetId, sessionId });\n return sessionId;\n }\n\n getDebugLog(limit = 50): DebugEntry[] {\n const normalized = Number.isFinite(limit)\n ? Math.max(1, Math.floor(limit))\n : 50;\n return this.#debugLog.slice(-normalized);\n }\n\n clearDebugLog(): void {\n this.#debugLog = [];\n }\n\n close(): void {\n this.#rejectAll(new Error(\"CDP session closed\"));\n try {\n this.#socket.close(1000, \"Done\");\n } catch {\n // socket may already be closed\n }\n this.#dispose?.();\n }\n\n #rejectAll(error: Error): void {\n for (const [id, pending] of this.#pending.entries()) {\n clearTimeout(pending.timeoutId);\n this.#pending.delete(id);\n pending.reject(error);\n }\n }\n\n #handleMessage(event: MessageEvent): void {\n if (typeof event.data !== \"string\") {\n return;\n }\n\n let payload: Record<string, unknown>;\n try {\n payload = JSON.parse(event.data) as Record<string, unknown>;\n } catch {\n return;\n }\n\n this.#recordDebug(\"receive\", {\n id: payload.id,\n method: payload.method,\n sessionId: payload.sessionId,\n hasError: !!payload.error\n });\n\n if (typeof payload.id !== \"number\") {\n return;\n }\n\n const pending = this.#pending.get(payload.id);\n if (!pending) {\n return;\n }\n\n clearTimeout(pending.timeoutId);\n this.#pending.delete(payload.id);\n\n if (payload.error) {\n const err = payload.error as { code?: unknown; message?: string };\n const code = err.code ?? \"unknown\";\n const message = err.message ?? \"CDP error\";\n pending.reject(\n new Error(`CDP error ${code}: ${message} for ${pending.method}`)\n );\n return;\n }\n\n pending.resolve(payload.result);\n }\n\n #recordDebug(type: string, data: Record<string, unknown>): void {\n this.#debugLog.push({\n at: new Date().toISOString(),\n type,\n ...data\n });\n if (this.#debugLog.length > MAX_DEBUG_ENTRIES) {\n this.#debugLog.splice(0, this.#debugLog.length - MAX_DEBUG_ENTRIES);\n }\n }\n}\n\n/**\n * Connect to a browser via the Browser Rendering binding (Fetcher).\n * Establishes a CDP WebSocket through the binding's fetch interface.\n */\nexport async function connectBrowser(\n browser: Fetcher,\n timeoutMs?: number\n): Promise<CdpSession> {\n const response = await browser.fetch(\n \"https://localhost/v1/devtools/browser\",\n {\n headers: { Upgrade: \"websocket\" }\n }\n );\n\n const ws = response.webSocket;\n if (!ws) {\n throw new Error(\n \"Browser Rendering binding did not return a WebSocket. \" +\n \"Ensure the 'browser' binding is configured in wrangler.jsonc.\"\n );\n }\n\n const sessionId = response.headers.get(\"cf-browser-session-id\");\n if (!sessionId) {\n throw new Error(\n \"Browser Rendering binding did not include a session ID when opening the CDP WebSocket\"\n );\n }\n\n ws.accept();\n return new CdpSession(ws, timeoutMs, () => {\n void browser.fetch(`https://localhost/v1/devtools/browser/${sessionId}`, {\n method: \"DELETE\"\n });\n });\n}\n\nconst LOCALHOST_HOSTS = new Set([\n \"localhost\",\n \"127.0.0.1\",\n \"0.0.0.0\",\n \"::1\",\n \"[::1]\"\n]);\n\n/**\n * Connect to a browser via a CDP base URL (e.g. http://localhost:9222).\n * Discovers the WebSocket debugger URL via /json/version,\n * rewrites localhost URLs to the base URL host, and opens the WebSocket.\n *\n * Useful for local development with `chrome --remote-debugging-port=9222`\n * or when connecting through a tunnel.\n */\nexport async function connectUrl(\n baseUrl: string,\n options?: { timeoutMs?: number; headers?: Record<string, string> }\n): Promise<CdpSession> {\n const endpoint = new URL(\"/json/version\", baseUrl).toString();\n const response = await fetch(endpoint, {\n headers: options?.headers\n });\n if (!response.ok) {\n throw new Error(\n `Failed to discover CDP endpoint at ${endpoint}: ${response.status}`\n );\n }\n\n const payload = (await response.json()) as {\n webSocketDebuggerUrl?: string;\n };\n if (!payload.webSocketDebuggerUrl) {\n throw new Error(\"CDP /json/version did not include webSocketDebuggerUrl\");\n }\n\n let wsUrl = payload.webSocketDebuggerUrl;\n const parsed = new URL(wsUrl);\n if (LOCALHOST_HOSTS.has(parsed.hostname)) {\n const base = new URL(baseUrl);\n parsed.hostname = base.hostname;\n parsed.port = base.port;\n parsed.protocol = base.protocol;\n } else {\n // Workers runtime requires fetch + Upgrade header for outbound WebSockets\n parsed.protocol = parsed.protocol === \"wss:\" ? \"https:\" : \"http:\";\n }\n const fetchUrl = parsed.toString();\n\n const wsResponse = await fetch(fetchUrl, {\n headers: { ...options?.headers, Upgrade: \"websocket\" }\n });\n const ws = wsResponse.webSocket;\n if (!ws) {\n throw new Error(\n `Failed to establish CDP WebSocket at ${fetchUrl} (status ${wsResponse.status})`\n );\n }\n ws.accept();\n\n return new CdpSession(ws, options?.timeoutMs);\n}\n","const CHARS_PER_TOKEN = 4;\nconst MAX_TOKENS = 6000;\nconst MAX_CHARS = CHARS_PER_TOKEN * MAX_TOKENS;\n\nexport function truncateResponse(content: unknown): string {\n const text =\n typeof content === \"string\"\n ? content\n : (JSON.stringify(content, null, 2) ?? \"null\");\n if (text.length <= MAX_CHARS) {\n return text;\n }\n\n const estimatedTokens = Math.ceil(text.length / CHARS_PER_TOKEN);\n return `${text.slice(0, MAX_CHARS)}\\n\\n--- TRUNCATED ---\\nResponse was ~${estimatedTokens.toLocaleString()} tokens (limit: ${MAX_TOKENS.toLocaleString()}). Use more specific queries to reduce response size.`;\n}\n","import type { ResolvedProvider } from \"@cloudflare/codemode\";\nimport { DynamicWorkerExecutor } from \"@cloudflare/codemode\";\nimport { CdpSession, connectBrowser, connectUrl } from \"./cdp-session\";\nimport { truncateResponse } from \"./truncate\";\n\nexport interface BrowserToolsOptions {\n /** Browser Rendering binding (Fetcher) — used in production */\n browser?: Fetcher;\n /** Optional CDP base URL override (e.g. http://localhost:9222) */\n cdpUrl?: string;\n /** Headers to send with CDP URL discovery requests (e.g. Access headers) */\n cdpHeaders?: Record<string, string>;\n /** Loader binding for sandboxed code execution */\n loader: WorkerLoader;\n /** Execution timeout in milliseconds (default: 30000) */\n timeout?: number;\n}\n\ninterface RawCdpCommand {\n name: string;\n description?: string;\n}\n\ninterface RawCdpEvent {\n name: string;\n description?: string;\n}\n\ninterface RawCdpType {\n id: string;\n description?: string;\n}\n\n/** Raw CDP protocol domain from `/json/protocol` */\ninterface RawCdpDomain {\n domain: string;\n description?: string;\n commands?: RawCdpCommand[];\n events?: RawCdpEvent[];\n types?: RawCdpType[];\n}\n\ninterface SearchableCdpSpec {\n domains: Array<{\n name: string;\n description?: string;\n commands: Array<{ name: string; method: string; description?: string }>;\n events: Array<{ name: string; event: string; description?: string }>;\n types: Array<{ id: string; name: string; description?: string }>;\n }>;\n}\n\nconst specCache = new Map<\n string,\n { spec: SearchableCdpSpec; cachedAt: number }\n>();\n\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\nexport const SEARCH_DESCRIPTION = `Search the Chrome DevTools Protocol spec using JavaScript code.\n\nAvailable in your code:\n\ndeclare const spec: {\n get(): Promise<{\n domains: Array<{\n name: string;\n description?: string;\n commands: Array<{ name: string; method: string; description?: string }>;\n events: Array<{ name: string; event: string; description?: string }>;\n types: Array<{ id: string; name: string; description?: string }>;\n }>;\n }>;\n};\n\nWrite an async arrow function in JavaScript. Do NOT use TypeScript syntax.\n\nExample:\nasync () => {\n const s = await spec.get();\n return s.domains\n .find(d => d.name === \"Network\")\n .commands.filter(c => c.description?.toLowerCase().includes(\"intercept\"))\n .map(c => ({ method: c.method, description: c.description }));\n}`;\n\nfunction normalizeCdpSpec(spec: {\n domains?: RawCdpDomain[];\n}): SearchableCdpSpec {\n return {\n domains: (spec.domains ?? []).map((domain) => ({\n name: domain.domain,\n description: domain.description,\n commands: (domain.commands ?? []).map((command) => ({\n name: command.name,\n method: `${domain.domain}.${command.name}`,\n description: command.description\n })),\n events: (domain.events ?? []).map((event) => ({\n name: event.name,\n event: `${domain.domain}.${event.name}`,\n description: event.description\n })),\n types: (domain.types ?? []).map((type) => ({\n id: type.id,\n name: `${domain.domain}.${type.id}`,\n description: type.description\n }))\n }))\n };\n}\n\nfunction getSpecCacheKey(\n source: string,\n headers?: Record<string, string>\n): string {\n const headerEntries = Object.entries(headers ?? {}).sort(([a], [b]) =>\n a.localeCompare(b)\n );\n return `${source}:${JSON.stringify(headerEntries)}`;\n}\n\nasync function getCachedSpec(\n key: string,\n load: () => Promise<{ domains?: RawCdpDomain[] }>\n): Promise<SearchableCdpSpec> {\n const cached = specCache.get(key);\n if (cached && Date.now() - cached.cachedAt < CACHE_TTL_MS) {\n return cached.spec;\n }\n\n const spec = normalizeCdpSpec(await load());\n specCache.set(key, { spec, cachedAt: Date.now() });\n return spec;\n}\n\nasync function fetchCdpSpecFromUrl(\n cdpBaseUrl: string,\n headers?: Record<string, string>\n): Promise<SearchableCdpSpec> {\n const endpoint = new URL(\"/json/protocol\", cdpBaseUrl).toString();\n\n return getCachedSpec(getSpecCacheKey(endpoint, headers), async () => {\n const response = await fetch(endpoint, { headers });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch CDP spec from ${endpoint}: ${response.status}`\n );\n }\n\n return (await response.json()) as { domains?: RawCdpDomain[] };\n });\n}\n\nasync function fetchCdpSpecFromBrowser(\n browser: Fetcher\n): Promise<SearchableCdpSpec> {\n return getCachedSpec(\"browser-binding\", async () => {\n const createResponse = await browser.fetch(\n \"https://localhost/v1/devtools/browser\",\n {\n method: \"POST\"\n }\n );\n\n if (!createResponse.ok) {\n throw new Error(\n \"Failed to create Browser Rendering session for protocol fetch: \" +\n `${createResponse.status}`\n );\n }\n\n const payload = (await createResponse.json()) as { sessionId?: string };\n const sessionId = payload.sessionId;\n if (!sessionId) {\n throw new Error(\n \"Browser Rendering session response did not include a sessionId\"\n );\n }\n\n try {\n const response = await browser.fetch(\n `https://localhost/v1/devtools/browser/${sessionId}/json/protocol`\n );\n\n if (!response.ok) {\n throw new Error(\n \"Failed to fetch CDP spec from Browser Rendering: \" +\n `${response.status}`\n );\n }\n\n return (await response.json()) as { domains?: RawCdpDomain[] };\n } finally {\n try {\n await browser.fetch(\n `https://localhost/v1/devtools/browser/${sessionId}`,\n {\n method: \"DELETE\"\n }\n );\n } catch {\n // Cleanup failure should not mask the original result or error\n }\n }\n });\n}\n\nexport const EXECUTE_DESCRIPTION = `Execute CDP commands against a live browser session using JavaScript code.\n\nAvailable in your code:\n\ndeclare const cdp: {\n send(method: string, params?: unknown, options?: {\n timeoutMs?: number;\n sessionId?: string;\n }): Promise<unknown>;\n attachToTarget(targetId: string, options?: {\n timeoutMs?: number;\n }): Promise<string>;\n getDebugLog(limit?: number): Promise<unknown[]>;\n clearDebugLog(): Promise<void>;\n};\n\nWrite an async arrow function in JavaScript. Do NOT use TypeScript syntax.\n\nFor page-scoped commands such as Page.*, Runtime.*, and DOM.*, first create or select a target, call cdp.attachToTarget(targetId), and pass the returned sessionId in command options.\n\nExample:\nasync () => {\n return await cdp.send(\"Browser.getVersion\");\n}\n\nPage example:\nasync () => {\n const { targetId } = await cdp.send(\"Target.createTarget\", {\n url: \"about:blank\"\n });\n const sessionId = await cdp.attachToTarget(targetId);\n await cdp.send(\"Page.enable\", {}, { sessionId });\n await cdp.send(\n \"Page.navigate\",\n { url: \"https://example.com\" },\n { sessionId }\n );\n const { result } = await cdp.send(\n \"Runtime.evaluate\",\n { expression: \"document.title\" },\n { sessionId }\n );\n return result.value;\n}`;\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport interface ToolResult {\n text: string;\n isError?: boolean;\n}\n\nlet didWarnExperimental = false;\n\nexport function createBrowserToolHandlers(options: BrowserToolsOptions) {\n if (!didWarnExperimental) {\n didWarnExperimental = true;\n console.warn(\n \"[agents/browser] Browser tools are experimental and may change in a future release.\"\n );\n }\n const executor = new DynamicWorkerExecutor({\n loader: options.loader,\n timeout: options.timeout\n });\n\n async function search(code: string): Promise<ToolResult> {\n try {\n let specSource: SearchableCdpSpec;\n\n if (options.cdpUrl) {\n specSource = await fetchCdpSpecFromUrl(\n options.cdpUrl,\n options.cdpHeaders\n );\n } else if (options.browser) {\n specSource = await fetchCdpSpecFromBrowser(options.browser);\n } else {\n return {\n text: \"Either 'browser' (Fetcher binding) or 'cdpUrl' must be provided\",\n isError: true\n };\n }\n\n const providers: ResolvedProvider[] = [\n {\n name: \"spec\",\n fns: { get: async () => specSource }\n }\n ];\n const result = await executor.execute(code, providers);\n if (result.error) {\n return { text: result.error, isError: true };\n }\n return { text: truncateResponse(result.result) };\n } catch (error) {\n return { text: formatError(error), isError: true };\n }\n }\n\n async function execute(code: string): Promise<ToolResult> {\n let session: CdpSession | undefined;\n try {\n if (options.cdpUrl) {\n session = await connectUrl(options.cdpUrl, {\n timeoutMs: options.timeout,\n headers: options.cdpHeaders\n });\n } else if (options.browser) {\n session = await connectBrowser(options.browser, options.timeout);\n } else {\n return {\n text: \"Either 'browser' (Fetcher binding) or 'cdpUrl' must be provided\",\n isError: true\n };\n }\n\n const providers: ResolvedProvider[] = [\n {\n name: \"cdp\",\n fns: {\n send: async (method: unknown, params: unknown, opts: unknown) =>\n session!.send(\n method as string,\n params,\n opts as { timeoutMs?: number; sessionId?: string }\n ),\n attachToTarget: async (targetId: unknown, opts: unknown) =>\n session!.attachToTarget(\n targetId as string,\n opts as { timeoutMs?: number }\n ),\n getDebugLog: async (limit: unknown) =>\n session!.getDebugLog(limit as number | undefined),\n clearDebugLog: async () => session!.clearDebugLog()\n }\n }\n ];\n\n const result = await executor.execute(code, providers);\n if (result.error) {\n return { text: result.error, isError: true };\n }\n return { text: truncateResponse(result.result) };\n } catch (error) {\n return { text: formatError(error), isError: true };\n } finally {\n session?.close();\n }\n }\n\n return { search, execute };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"shared-BIpUk4G5.js","names":[],"sources":["../src/browser/cdp-session.ts","../src/browser/truncate.ts","../src/browser/shared.ts"],"sourcesContent":["interface PendingCommand {\n resolve: (result: unknown) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n method: string;\n sessionId?: string;\n startedAt: number;\n}\n\ninterface DebugEntry {\n at: string;\n type: string;\n [key: string]: unknown;\n}\n\nexport interface CdpSendOptions {\n timeoutMs?: number;\n sessionId?: string;\n}\n\nexport interface CdpAttachOptions {\n timeoutMs?: number;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst MAX_DEBUG_ENTRIES = 400;\n\n/**\n * A CDP session over an open WebSocket. Manages command correlation,\n * timeouts, target sessions, and a debug event ring buffer.\n *\n * Used host-side (not in the sandbox) — the sandbox calls into this\n * via DynamicWorkerExecutor's ToolDispatcher RPC.\n */\nexport class CdpSession {\n #socket: WebSocket;\n #nextId = 1;\n #pending = new Map<number, PendingCommand>();\n #debugLog: DebugEntry[] = [];\n #defaultTimeoutMs: number;\n #dispose?: () => void;\n\n constructor(\n socket: WebSocket,\n defaultTimeoutMs = DEFAULT_TIMEOUT_MS,\n dispose?: () => void\n ) {\n this.#socket = socket;\n this.#defaultTimeoutMs = defaultTimeoutMs;\n this.#dispose = dispose;\n\n socket.addEventListener(\"message\", (event) => this.#handleMessage(event));\n socket.addEventListener(\"error\", () => {\n this.#rejectAll(new Error(\"CDP socket error\"));\n });\n socket.addEventListener(\"close\", () => {\n this.#rejectAll(new Error(\"CDP connection closed\"));\n });\n }\n\n send(\n method: string,\n params?: unknown,\n options: CdpSendOptions = {}\n ): Promise<unknown> {\n const id = this.#nextId++;\n const timeoutMs = options.timeoutMs ?? this.#defaultTimeoutMs;\n const sessionId =\n typeof options.sessionId === \"string\" && options.sessionId.length > 0\n ? options.sessionId\n : undefined;\n\n const domain = typeof method === \"string\" ? method.split(\".\")[0] : \"\";\n if (!sessionId && domain && ![\"Browser\", \"Target\"].includes(domain)) {\n this.#recordDebug(\"warning\", {\n id,\n method,\n reason: \"target-scoped method sent without sessionId\"\n });\n }\n\n const result = new Promise<unknown>((resolve, reject) => {\n const startedAt = performance.now();\n const timeoutId = setTimeout(() => {\n this.#pending.delete(id);\n reject(\n new Error(`CDP command timed out after ${timeoutMs}ms: ${method}`)\n );\n }, timeoutMs);\n this.#pending.set(id, {\n resolve,\n reject,\n timeoutId,\n method,\n sessionId,\n startedAt\n });\n });\n\n this.#recordDebug(\"send\", { id, method, sessionId, timeoutMs });\n this.#socket.send(JSON.stringify({ id, method, params, sessionId }));\n return result;\n }\n\n async attachToTarget(\n targetId: string,\n options: CdpAttachOptions = {}\n ): Promise<string> {\n if (typeof targetId !== \"string\" || !targetId) {\n throw new Error(\"attachToTarget requires a targetId\");\n }\n\n const result = (await this.send(\n \"Target.attachToTarget\",\n {\n targetId,\n flatten: true\n },\n { timeoutMs: options.timeoutMs }\n )) as { sessionId?: string };\n\n const sessionId = result?.sessionId ?? \"\";\n if (!sessionId) {\n throw new Error(\n `Target.attachToTarget did not return a sessionId for target ${targetId}`\n );\n }\n\n this.#recordDebug(\"attach\", { targetId, sessionId });\n return sessionId;\n }\n\n getDebugLog(limit = 50): DebugEntry[] {\n const normalized = Number.isFinite(limit)\n ? Math.max(1, Math.floor(limit))\n : 50;\n return this.#debugLog.slice(-normalized);\n }\n\n clearDebugLog(): void {\n this.#debugLog = [];\n }\n\n close(): void {\n this.#rejectAll(new Error(\"CDP session closed\"));\n try {\n this.#socket.close(1000, \"Done\");\n } catch {\n // socket may already be closed\n }\n this.#dispose?.();\n }\n\n #rejectAll(error: Error): void {\n for (const [id, pending] of this.#pending.entries()) {\n clearTimeout(pending.timeoutId);\n this.#pending.delete(id);\n pending.reject(error);\n }\n }\n\n #handleMessage(event: MessageEvent): void {\n if (typeof event.data !== \"string\") {\n return;\n }\n\n let payload: Record<string, unknown>;\n try {\n payload = JSON.parse(event.data) as Record<string, unknown>;\n } catch {\n return;\n }\n\n this.#recordDebug(\"receive\", {\n id: payload.id,\n method: payload.method,\n sessionId: payload.sessionId,\n hasError: !!payload.error\n });\n\n if (typeof payload.id !== \"number\") {\n return;\n }\n\n const pending = this.#pending.get(payload.id);\n if (!pending) {\n return;\n }\n\n clearTimeout(pending.timeoutId);\n this.#pending.delete(payload.id);\n\n if (payload.error) {\n const err = payload.error as { code?: unknown; message?: string };\n const code = err.code ?? \"unknown\";\n const message = err.message ?? \"CDP error\";\n pending.reject(\n new Error(`CDP error ${code}: ${message} for ${pending.method}`)\n );\n return;\n }\n\n pending.resolve(payload.result);\n }\n\n #recordDebug(type: string, data: Record<string, unknown>): void {\n this.#debugLog.push({\n at: new Date().toISOString(),\n type,\n ...data\n });\n if (this.#debugLog.length > MAX_DEBUG_ENTRIES) {\n this.#debugLog.splice(0, this.#debugLog.length - MAX_DEBUG_ENTRIES);\n }\n }\n}\n\n/**\n * Connect to a browser via the Browser Rendering binding (Fetcher).\n * Establishes a CDP WebSocket through the binding's fetch interface.\n */\nexport async function connectBrowser(\n browser: Fetcher,\n timeoutMs?: number\n): Promise<CdpSession> {\n const response = await browser.fetch(\n \"https://localhost/v1/devtools/browser\",\n {\n headers: { Upgrade: \"websocket\" }\n }\n );\n\n const ws = response.webSocket;\n if (!ws) {\n throw new Error(\n \"Browser Rendering binding did not return a WebSocket. \" +\n \"Ensure the 'browser' binding is configured in wrangler.jsonc.\"\n );\n }\n\n const sessionId = response.headers.get(\"cf-browser-session-id\");\n if (!sessionId) {\n throw new Error(\n \"Browser Rendering binding did not include a session ID when opening the CDP WebSocket\"\n );\n }\n\n ws.accept();\n return new CdpSession(ws, timeoutMs, () => {\n void browser.fetch(`https://localhost/v1/devtools/browser/${sessionId}`, {\n method: \"DELETE\"\n });\n });\n}\n\nconst LOCALHOST_HOSTS = new Set([\n \"localhost\",\n \"127.0.0.1\",\n \"0.0.0.0\",\n \"::1\",\n \"[::1]\"\n]);\n\n/**\n * Connect to a browser via a CDP base URL (e.g. http://localhost:9222).\n * Discovers the WebSocket debugger URL via /json/version,\n * rewrites localhost URLs to the base URL host, and opens the WebSocket.\n *\n * Useful for local development with `chrome --remote-debugging-port=9222`\n * or when connecting through a tunnel.\n */\nexport async function connectUrl(\n baseUrl: string,\n options?: { timeoutMs?: number; headers?: Record<string, string> }\n): Promise<CdpSession> {\n const endpoint = new URL(\"/json/version\", baseUrl).toString();\n const response = await fetch(endpoint, {\n headers: options?.headers\n });\n if (!response.ok) {\n throw new Error(\n `Failed to discover CDP endpoint at ${endpoint}: ${response.status}`\n );\n }\n\n const payload = (await response.json()) as {\n webSocketDebuggerUrl?: string;\n };\n if (!payload.webSocketDebuggerUrl) {\n throw new Error(\"CDP /json/version did not include webSocketDebuggerUrl\");\n }\n\n let wsUrl = payload.webSocketDebuggerUrl;\n const parsed = new URL(wsUrl);\n if (LOCALHOST_HOSTS.has(parsed.hostname)) {\n const base = new URL(baseUrl);\n parsed.hostname = base.hostname;\n parsed.port = base.port;\n parsed.protocol = base.protocol;\n } else {\n // Workers runtime requires fetch + Upgrade header for outbound WebSockets\n parsed.protocol = parsed.protocol === \"wss:\" ? \"https:\" : \"http:\";\n }\n const fetchUrl = parsed.toString();\n\n const wsResponse = await fetch(fetchUrl, {\n headers: { ...options?.headers, Upgrade: \"websocket\" }\n });\n const ws = wsResponse.webSocket;\n if (!ws) {\n throw new Error(\n `Failed to establish CDP WebSocket at ${fetchUrl} (status ${wsResponse.status})`\n );\n }\n ws.accept();\n\n return new CdpSession(ws, options?.timeoutMs);\n}\n","const CHARS_PER_TOKEN = 4;\nconst MAX_TOKENS = 6000;\nconst MAX_CHARS = CHARS_PER_TOKEN * MAX_TOKENS;\n\nexport function truncateResponse(content: unknown): string {\n const text =\n typeof content === \"string\"\n ? content\n : (JSON.stringify(content, null, 2) ?? \"null\");\n if (text.length <= MAX_CHARS) {\n return text;\n }\n\n const estimatedTokens = Math.ceil(text.length / CHARS_PER_TOKEN);\n return `${text.slice(0, MAX_CHARS)}\\n\\n--- TRUNCATED ---\\nResponse was ~${estimatedTokens.toLocaleString()} tokens (limit: ${MAX_TOKENS.toLocaleString()}). Use more specific queries to reduce response size.`;\n}\n","import type { ResolvedProvider } from \"@cloudflare/codemode\";\nimport { DynamicWorkerExecutor } from \"@cloudflare/codemode\";\nimport { CdpSession, connectBrowser, connectUrl } from \"./cdp-session\";\nimport { truncateResponse } from \"./truncate\";\n\nexport interface BrowserToolsOptions {\n /** Browser Rendering binding (Fetcher) — used in production */\n browser?: Fetcher;\n /** Optional CDP base URL override (e.g. http://localhost:9222) */\n cdpUrl?: string;\n /** Headers to send with CDP URL discovery requests (e.g. Access headers) */\n cdpHeaders?: Record<string, string>;\n /** Loader binding for sandboxed code execution */\n loader: WorkerLoader;\n /** Execution timeout in milliseconds (default: 30000) */\n timeout?: number;\n}\n\ninterface RawCdpCommand {\n name: string;\n description?: string;\n}\n\ninterface RawCdpEvent {\n name: string;\n description?: string;\n}\n\ninterface RawCdpType {\n id: string;\n description?: string;\n}\n\n/** Raw CDP protocol domain from `/json/protocol` */\ninterface RawCdpDomain {\n domain: string;\n description?: string;\n commands?: RawCdpCommand[];\n events?: RawCdpEvent[];\n types?: RawCdpType[];\n}\n\ninterface SearchableCdpSpec {\n domains: Array<{\n name: string;\n description?: string;\n commands: Array<{ name: string; method: string; description?: string }>;\n events: Array<{ name: string; event: string; description?: string }>;\n types: Array<{ id: string; name: string; description?: string }>;\n }>;\n}\n\nconst specCache = new Map<\n string,\n { spec: SearchableCdpSpec; cachedAt: number }\n>();\n\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\nexport const SEARCH_DESCRIPTION = `Search the Chrome DevTools Protocol spec using JavaScript code.\n\nAvailable in your code:\n\ndeclare const spec: {\n get(): Promise<{\n domains: Array<{\n name: string;\n description?: string;\n commands: Array<{ name: string; method: string; description?: string }>;\n events: Array<{ name: string; event: string; description?: string }>;\n types: Array<{ id: string; name: string; description?: string }>;\n }>;\n }>;\n};\n\nWrite an async arrow function in JavaScript. Do NOT use TypeScript syntax.\n\nExample:\nasync () => {\n const s = await spec.get();\n return s.domains\n .find(d => d.name === \"Network\")\n .commands.filter(c => c.description?.toLowerCase().includes(\"intercept\"))\n .map(c => ({ method: c.method, description: c.description }));\n}`;\n\nfunction normalizeCdpSpec(spec: {\n domains?: RawCdpDomain[];\n}): SearchableCdpSpec {\n return {\n domains: (spec.domains ?? []).map((domain) => ({\n name: domain.domain,\n description: domain.description,\n commands: (domain.commands ?? []).map((command) => ({\n name: command.name,\n method: `${domain.domain}.${command.name}`,\n description: command.description\n })),\n events: (domain.events ?? []).map((event) => ({\n name: event.name,\n event: `${domain.domain}.${event.name}`,\n description: event.description\n })),\n types: (domain.types ?? []).map((type) => ({\n id: type.id,\n name: `${domain.domain}.${type.id}`,\n description: type.description\n }))\n }))\n };\n}\n\nfunction getSpecCacheKey(\n source: string,\n headers?: Record<string, string>\n): string {\n const headerEntries = Object.entries(headers ?? {}).sort(([a], [b]) =>\n a.localeCompare(b)\n );\n return `${source}:${JSON.stringify(headerEntries)}`;\n}\n\nasync function getCachedSpec(\n key: string,\n load: () => Promise<{ domains?: RawCdpDomain[] }>\n): Promise<SearchableCdpSpec> {\n const cached = specCache.get(key);\n if (cached && Date.now() - cached.cachedAt < CACHE_TTL_MS) {\n return cached.spec;\n }\n\n const spec = normalizeCdpSpec(await load());\n specCache.set(key, { spec, cachedAt: Date.now() });\n return spec;\n}\n\nasync function fetchCdpSpecFromUrl(\n cdpBaseUrl: string,\n headers?: Record<string, string>\n): Promise<SearchableCdpSpec> {\n const endpoint = new URL(\"/json/protocol\", cdpBaseUrl).toString();\n\n return getCachedSpec(getSpecCacheKey(endpoint, headers), async () => {\n const response = await fetch(endpoint, { headers });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch CDP spec from ${endpoint}: ${response.status}`\n );\n }\n\n return (await response.json()) as { domains?: RawCdpDomain[] };\n });\n}\n\nasync function fetchCdpSpecFromBrowser(\n browser: Fetcher\n): Promise<SearchableCdpSpec> {\n return getCachedSpec(\"browser-binding\", async () => {\n const createResponse = await browser.fetch(\n \"https://localhost/v1/devtools/browser\",\n {\n method: \"POST\"\n }\n );\n\n if (!createResponse.ok) {\n throw new Error(\n \"Failed to create Browser Rendering session for protocol fetch: \" +\n `${createResponse.status}`\n );\n }\n\n const payload = (await createResponse.json()) as { sessionId?: string };\n const sessionId = payload.sessionId;\n if (!sessionId) {\n throw new Error(\n \"Browser Rendering session response did not include a sessionId\"\n );\n }\n\n try {\n const response = await browser.fetch(\n `https://localhost/v1/devtools/browser/${sessionId}/json/protocol`\n );\n\n if (!response.ok) {\n throw new Error(\n \"Failed to fetch CDP spec from Browser Rendering: \" +\n `${response.status}`\n );\n }\n\n return (await response.json()) as { domains?: RawCdpDomain[] };\n } finally {\n try {\n await browser.fetch(\n `https://localhost/v1/devtools/browser/${sessionId}`,\n {\n method: \"DELETE\"\n }\n );\n } catch {\n // Cleanup failure should not mask the original result or error\n }\n }\n });\n}\n\nexport const EXECUTE_DESCRIPTION = `Execute CDP commands against a live browser session using JavaScript code.\n\nAvailable in your code:\n\ndeclare const cdp: {\n send(method: string, params?: unknown, options?: {\n timeoutMs?: number;\n sessionId?: string;\n }): Promise<unknown>;\n attachToTarget(targetId: string, options?: {\n timeoutMs?: number;\n }): Promise<string>;\n getDebugLog(limit?: number): Promise<unknown[]>;\n clearDebugLog(): Promise<void>;\n};\n\nWrite an async arrow function in JavaScript. Do NOT use TypeScript syntax.\n\nFor page-scoped commands such as Page.*, Runtime.*, and DOM.*, first create or select a target, call cdp.attachToTarget(targetId), and pass the returned sessionId in command options.\n\nExample:\nasync () => {\n return await cdp.send(\"Browser.getVersion\");\n}\n\nPage example:\nasync () => {\n const { targetId } = await cdp.send(\"Target.createTarget\", {\n url: \"about:blank\"\n });\n const sessionId = await cdp.attachToTarget(targetId);\n await cdp.send(\"Page.enable\", {}, { sessionId });\n await cdp.send(\n \"Page.navigate\",\n { url: \"https://example.com\" },\n { sessionId }\n );\n const { result } = await cdp.send(\n \"Runtime.evaluate\",\n { expression: \"document.title\" },\n { sessionId }\n );\n return result.value;\n}`;\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport interface ToolResult {\n text: string;\n isError?: boolean;\n}\n\nlet didWarnExperimental = false;\n\nexport function createBrowserToolHandlers(options: BrowserToolsOptions) {\n if (!didWarnExperimental) {\n didWarnExperimental = true;\n console.warn(\n \"[agents/browser] Browser tools are experimental and may change in a future release.\"\n );\n }\n const executor = new DynamicWorkerExecutor({\n loader: options.loader,\n timeout: options.timeout\n });\n\n async function search(code: string): Promise<ToolResult> {\n try {\n let specSource: SearchableCdpSpec;\n\n if (options.cdpUrl) {\n specSource = await fetchCdpSpecFromUrl(\n options.cdpUrl,\n options.cdpHeaders\n );\n } else if (options.browser) {\n specSource = await fetchCdpSpecFromBrowser(options.browser);\n } else {\n return {\n text: \"Either 'browser' (Fetcher binding) or 'cdpUrl' must be provided\",\n isError: true\n };\n }\n\n const providers: ResolvedProvider[] = [\n {\n name: \"spec\",\n fns: { get: async () => specSource }\n }\n ];\n const result = await executor.execute(code, providers);\n if (result.error) {\n return { text: result.error, isError: true };\n }\n return { text: truncateResponse(result.result) };\n } catch (error) {\n return { text: formatError(error), isError: true };\n }\n }\n\n async function execute(code: string): Promise<ToolResult> {\n let session: CdpSession | undefined;\n try {\n if (options.cdpUrl) {\n session = await connectUrl(options.cdpUrl, {\n timeoutMs: options.timeout,\n headers: options.cdpHeaders\n });\n } else if (options.browser) {\n session = await connectBrowser(options.browser, options.timeout);\n } else {\n return {\n text: \"Either 'browser' (Fetcher binding) or 'cdpUrl' must be provided\",\n isError: true\n };\n }\n\n const providers: ResolvedProvider[] = [\n {\n name: \"cdp\",\n fns: {\n send: async (method: unknown, params: unknown, opts: unknown) =>\n session!.send(\n method as string,\n params,\n opts as { timeoutMs?: number; sessionId?: string }\n ),\n attachToTarget: async (targetId: unknown, opts: unknown) =>\n session!.attachToTarget(\n targetId as string,\n opts as { timeoutMs?: number }\n ),\n getDebugLog: async (limit: unknown) =>\n session!.getDebugLog(limit as number | undefined),\n clearDebugLog: async () => session!.clearDebugLog()\n }\n }\n ];\n\n const result = await executor.execute(code, providers);\n if (result.error) {\n return { text: result.error, isError: true };\n }\n return { text: truncateResponse(result.result) };\n } catch (error) {\n return { text: formatError(error), isError: true };\n } finally {\n session?.close();\n }\n }\n\n return { search, execute };\n}\n"],"mappings":";;;;AAwBA,MAAM,qBAAqB;AAC3B,MAAM,oBAAoB;;;;;;;;;;;;;;;AAS1B,IAAa,aAAb,MAAwB;CAQtB,YACE,QACA,mBAAmB,oBACnB,SACA;;;4CAVQ,CAAA;6DACC,IAAI,IAA4B,CAAA;8CACjB,CAAC,CAAA;;;EASzB,uBAAA,SAAA,MAAe,MAAA;EACf,uBAAA,mBAAA,MAAyB,gBAAA;EACzB,uBAAA,UAAA,MAAgB,OAAA;EAEhB,OAAO,iBAAiB,YAAY,UAAA,kBAAA,mBAAU,MAAA,cAAA,EAAA,KAAA,MAAoB,KAAK,CAAC;EACxE,OAAO,iBAAiB,eAAe;GACrC,kBAAA,mBAAA,MAAA,UAAA,EAAA,KAAA,sBAAgB,IAAI,MAAM,kBAAkB,CAAC;EAC/C,CAAC;EACD,OAAO,iBAAiB,eAAe;GACrC,kBAAA,mBAAA,MAAA,UAAA,EAAA,KAAA,sBAAgB,IAAI,MAAM,uBAAuB,CAAC;EACpD,CAAC;CACH;CAEA,KACE,QACA,QACA,UAA0B,CAAC,GACT;;EAClB,MAAM,MAAA,uBAAA,SAAK,OAAA,eAAA,uBAAA,SAAA,IAAA,GAAA,gBAAA,gBAAA,aAAA,GAAA;EACX,MAAM,YAAY,QAAQ,aAAA,uBAAA,mBAAa,IAAA;EACvC,MAAM,YACJ,OAAO,QAAQ,cAAc,YAAY,QAAQ,UAAU,SAAS,IAChE,QAAQ,YACR,KAAA;EAEN,MAAM,SAAS,OAAO,WAAW,WAAW,OAAO,MAAM,GAAG,EAAE,KAAK;EACnE,IAAI,CAAC,aAAa,UAAU,CAAC,CAAC,WAAW,QAAQ,EAAE,SAAS,MAAM,GAChE,kBAAA,mBAAA,MAAA,YAAA,EAAA,KAAA,MAAkB,WAAW;GAC3B;GACA;GACA,QAAQ;EACV,CAAC;EAGH,MAAM,SAAS,IAAI,SAAkB,SAAS,WAAW;GACvD,MAAM,YAAY,YAAY,IAAI;GAClC,MAAM,YAAY,iBAAiB;IACjC,uBAAA,UAAA,IAAA,EAAc,OAAO,EAAE;IACvB,uBACE,IAAI,MAAM,+BAA+B,UAAU,MAAM,QAAQ,CACnE;GACF,GAAG,SAAS;GACZ,uBAAA,UAAA,IAAA,EAAc,IAAI,IAAI;IACpB;IACA;IACA;IACA;IACA;IACA;GACF,CAAC;EACH,CAAC;EAED,kBAAA,mBAAA,MAAA,YAAA,EAAA,KAAA,MAAkB,QAAQ;GAAE;GAAI;GAAQ;GAAW;EAAU,CAAC;EAC9D,uBAAA,SAAA,IAAA,EAAa,KAAK,KAAK,UAAU;GAAE;GAAI;GAAQ;GAAQ;EAAU,CAAC,CAAC;EACnE,OAAO;CACT;CAEA,MAAM,eACJ,UACA,UAA4B,CAAC,GACZ;EACjB,IAAI,OAAO,aAAa,YAAY,CAAC,UACnC,MAAM,IAAI,MAAM,oCAAoC;EAYtD,MAAM,aAAY,MATI,KAAK,KACzB,yBACA;GACE;GACA,SAAS;EACX,GACA,EAAE,WAAW,QAAQ,UAAU,CACjC,IAE0B,aAAa;EACvC,IAAI,CAAC,WACH,MAAM,IAAI,MACR,+DAA+D,UACjE;EAGF,kBAAA,mBAAA,MAAA,YAAA,EAAA,KAAA,MAAkB,UAAU;GAAE;GAAU;EAAU,CAAC;EACnD,OAAO;CACT;CAEA,YAAY,QAAQ,IAAkB;EACpC,MAAM,aAAa,OAAO,SAAS,KAAK,IACpC,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,CAAC,IAC7B;EACJ,OAAA,uBAAA,WAAO,IAAA,EAAe,MAAM,CAAC,UAAU;CACzC;CAEA,gBAAsB;EACpB,uBAAA,WAAA,MAAiB,CAAC,CAAA;CACpB;CAEA,QAAc;EACZ,kBAAA,mBAAA,MAAA,UAAA,EAAA,KAAA,sBAAgB,IAAI,MAAM,oBAAoB,CAAC;EAC/C,IAAI;GACF,uBAAA,SAAA,IAAA,EAAa,MAAM,KAAM,MAAM;EACjC,QAAQ,CAER;EACA,uBAAA,UAAA,IAAA,GAAA,KAAA,IAAgB;CAClB;AAgEF;AA9DE,SAAA,WAAW,OAAoB;CAC7B,KAAK,MAAM,CAAC,IAAI,YAAA,uBAAA,UAAY,IAAA,EAAc,QAAQ,GAAG;EACnD,aAAa,QAAQ,SAAS;EAC9B,uBAAA,UAAA,IAAA,EAAc,OAAO,EAAE;EACvB,QAAQ,OAAO,KAAK;CACtB;AACF;AAEA,SAAA,eAAe,OAA2B;CACxC,IAAI,OAAO,MAAM,SAAS,UACxB;CAGF,IAAI;CACJ,IAAI;EACF,UAAU,KAAK,MAAM,MAAM,IAAI;CACjC,QAAQ;EACN;CACF;CAEA,kBAAA,mBAAA,MAAA,YAAA,EAAA,KAAA,MAAkB,WAAW;EAC3B,IAAI,QAAQ;EACZ,QAAQ,QAAQ;EAChB,WAAW,QAAQ;EACnB,UAAU,CAAC,CAAC,QAAQ;CACtB,CAAC;CAED,IAAI,OAAO,QAAQ,OAAO,UACxB;CAGF,MAAM,UAAA,uBAAA,UAAU,IAAA,EAAc,IAAI,QAAQ,EAAE;CAC5C,IAAI,CAAC,SACH;CAGF,aAAa,QAAQ,SAAS;CAC9B,uBAAA,UAAA,IAAA,EAAc,OAAO,QAAQ,EAAE;CAE/B,IAAI,QAAQ,OAAO;EACjB,MAAM,MAAM,QAAQ;EACpB,MAAM,OAAO,IAAI,QAAQ;EACzB,MAAM,UAAU,IAAI,WAAW;EAC/B,QAAQ,uBACN,IAAI,MAAM,aAAa,KAAK,IAAI,QAAQ,OAAO,QAAQ,QAAQ,CACjE;EACA;CACF;CAEA,QAAQ,QAAQ,QAAQ,MAAM;AAChC;AAEA,SAAA,aAAa,MAAc,MAAqC;CAC9D,uBAAA,WAAA,IAAA,EAAe,KAAK;EAClB,qBAAI,IAAI,KAAK,GAAE,YAAY;EAC3B;EACA,GAAG;CACL,CAAC;CACD,IAAA,uBAAA,WAAI,IAAA,EAAe,SAAS,mBAC1B,uBAAA,WAAA,IAAA,EAAe,OAAO,GAAA,uBAAA,WAAG,IAAA,EAAe,SAAS,iBAAiB;AAEtE;;;;;AAOF,eAAsB,eACpB,SACA,WACqB;CACrB,MAAM,WAAW,MAAM,QAAQ,MAC7B,yCACA,EACE,SAAS,EAAE,SAAS,YAAY,EAClC,CACF;CAEA,MAAM,KAAK,SAAS;CACpB,IAAI,CAAC,IACH,MAAM,IAAI,MACR,qHAEF;CAGF,MAAM,YAAY,SAAS,QAAQ,IAAI,uBAAuB;CAC9D,IAAI,CAAC,WACH,MAAM,IAAI,MACR,uFACF;CAGF,GAAG,OAAO;CACV,OAAO,IAAI,WAAW,IAAI,iBAAiB;EACzC,QAAa,MAAM,yCAAyC,aAAa,EACvE,QAAQ,SACV,CAAC;CACH,CAAC;AACH;AAEA,MAAM,kBAAkB,IAAI,IAAI;CAC9B;CACA;CACA;CACA;CACA;AACF,CAAC;;;;;;;;;AAUD,eAAsB,WACpB,SACA,SACqB;CACrB,MAAM,WAAW,IAAI,IAAI,iBAAiB,OAAO,EAAE,SAAS;CAC5D,MAAM,WAAW,MAAM,MAAM,UAAU,EACrC,SAAS,SAAS,QACpB,CAAC;CACD,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MACR,sCAAsC,SAAS,IAAI,SAAS,QAC9D;CAGF,MAAM,UAAW,MAAM,SAAS,KAAK;CAGrC,IAAI,CAAC,QAAQ,sBACX,MAAM,IAAI,MAAM,wDAAwD;CAG1E,IAAI,QAAQ,QAAQ;CACpB,MAAM,SAAS,IAAI,IAAI,KAAK;CAC5B,IAAI,gBAAgB,IAAI,OAAO,QAAQ,GAAG;EACxC,MAAM,OAAO,IAAI,IAAI,OAAO;EAC5B,OAAO,WAAW,KAAK;EACvB,OAAO,OAAO,KAAK;EACnB,OAAO,WAAW,KAAK;CACzB,OAEE,OAAO,WAAW,OAAO,aAAa,SAAS,WAAW;CAE5D,MAAM,WAAW,OAAO,SAAS;CAEjC,MAAM,aAAa,MAAM,MAAM,UAAU,EACvC,SAAS;EAAE,GAAG,SAAS;EAAS,SAAS;CAAY,EACvD,CAAC;CACD,MAAM,KAAK,WAAW;CACtB,IAAI,CAAC,IACH,MAAM,IAAI,MACR,wCAAwC,SAAS,WAAW,WAAW,OAAO,EAChF;CAEF,GAAG,OAAO;CAEV,OAAO,IAAI,WAAW,IAAI,SAAS,SAAS;AAC9C;;;AC7TA,MAAM,kBAAkB;AACxB,MAAM,aAAa;AACnB,MAAM,YAAY,kBAAkB;AAEpC,SAAgB,iBAAiB,SAA0B;CACzD,MAAM,OACJ,OAAO,YAAY,WACf,UACC,KAAK,UAAU,SAAS,MAAM,CAAC,KAAK;CAC3C,IAAI,KAAK,UAAU,WACjB,OAAO;CAGT,MAAM,kBAAkB,KAAK,KAAK,KAAK,SAAS,eAAe;CAC/D,OAAO,GAAG,KAAK,MAAM,GAAG,SAAS,EAAE,uCAAuC,gBAAgB,eAAe,EAAE,kBAAkB,WAAW,eAAe,EAAE;AAC3J;;;ACqCA,MAAM,4BAAY,IAAI,IAGpB;AAEF,MAAM,eAAe,MAAS;AAE9B,MAAa,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BlC,SAAS,iBAAiB,MAEJ;CACpB,OAAO,EACL,UAAU,KAAK,WAAW,CAAC,GAAG,KAAK,YAAY;EAC7C,MAAM,OAAO;EACb,aAAa,OAAO;EACpB,WAAW,OAAO,YAAY,CAAC,GAAG,KAAK,aAAa;GAClD,MAAM,QAAQ;GACd,QAAQ,GAAG,OAAO,OAAO,GAAG,QAAQ;GACpC,aAAa,QAAQ;EACvB,EAAE;EACF,SAAS,OAAO,UAAU,CAAC,GAAG,KAAK,WAAW;GAC5C,MAAM,MAAM;GACZ,OAAO,GAAG,OAAO,OAAO,GAAG,MAAM;GACjC,aAAa,MAAM;EACrB,EAAE;EACF,QAAQ,OAAO,SAAS,CAAC,GAAG,KAAK,UAAU;GACzC,IAAI,KAAK;GACT,MAAM,GAAG,OAAO,OAAO,GAAG,KAAK;GAC/B,aAAa,KAAK;EACpB,EAAE;CACJ,EAAE,EACJ;AACF;AAEA,SAAS,gBACP,QACA,SACQ;CACR,MAAM,gBAAgB,OAAO,QAAQ,WAAW,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,OAC9D,EAAE,cAAc,CAAC,CACnB;CACA,OAAO,GAAG,OAAO,GAAG,KAAK,UAAU,aAAa;AAClD;AAEA,eAAe,cACb,KACA,MAC4B;CAC5B,MAAM,SAAS,UAAU,IAAI,GAAG;CAChC,IAAI,UAAU,KAAK,IAAI,IAAI,OAAO,WAAW,cAC3C,OAAO,OAAO;CAGhB,MAAM,OAAO,iBAAiB,MAAM,KAAK,CAAC;CAC1C,UAAU,IAAI,KAAK;EAAE;EAAM,UAAU,KAAK,IAAI;CAAE,CAAC;CACjD,OAAO;AACT;AAEA,eAAe,oBACb,YACA,SAC4B;CAC5B,MAAM,WAAW,IAAI,IAAI,kBAAkB,UAAU,EAAE,SAAS;CAEhE,OAAO,cAAc,gBAAgB,UAAU,OAAO,GAAG,YAAY;EACnE,MAAM,WAAW,MAAM,MAAM,UAAU,EAAE,QAAQ,CAAC;EAElD,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MACR,iCAAiC,SAAS,IAAI,SAAS,QACzD;EAGF,OAAQ,MAAM,SAAS,KAAK;CAC9B,CAAC;AACH;AAEA,eAAe,wBACb,SAC4B;CAC5B,OAAO,cAAc,mBAAmB,YAAY;EAClD,MAAM,iBAAiB,MAAM,QAAQ,MACnC,yCACA,EACE,QAAQ,OACV,CACF;EAEA,IAAI,CAAC,eAAe,IAClB,MAAM,IAAI,MACR,kEACK,eAAe,QACtB;EAIF,MAAM,aAAY,MADK,eAAe,KAAK,GACjB;EAC1B,IAAI,CAAC,WACH,MAAM,IAAI,MACR,gEACF;EAGF,IAAI;GACF,MAAM,WAAW,MAAM,QAAQ,MAC7B,yCAAyC,UAAU,eACrD;GAEA,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MACR,oDACK,SAAS,QAChB;GAGF,OAAQ,MAAM,SAAS,KAAK;EAC9B,UAAU;GACR,IAAI;IACF,MAAM,QAAQ,MACZ,yCAAyC,aACzC,EACE,QAAQ,SACV,CACF;GACF,QAAQ,CAER;EACF;CACF,CAAC;AACH;AAEA,MAAa,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CnC,SAAS,YAAY,OAAwB;CAC3C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAOA,IAAI,sBAAsB;AAE1B,SAAgB,0BAA0B,SAA8B;CACtE,IAAI,CAAC,qBAAqB;EACxB,sBAAsB;EACtB,QAAQ,KACN,qFACF;CACF;CACA,MAAM,WAAW,IAAI,sBAAsB;EACzC,QAAQ,QAAQ;EAChB,SAAS,QAAQ;CACnB,CAAC;CAED,eAAe,OAAO,MAAmC;EACvD,IAAI;GACF,IAAI;GAEJ,IAAI,QAAQ,QACV,aAAa,MAAM,oBACjB,QAAQ,QACR,QAAQ,UACV;QACK,IAAI,QAAQ,SACjB,aAAa,MAAM,wBAAwB,QAAQ,OAAO;QAE1D,OAAO;IACL,MAAM;IACN,SAAS;GACX;GASF,MAAM,SAAS,MAAM,SAAS,QAAQ,MAAM,CAL1C;IACE,MAAM;IACN,KAAK,EAAE,KAAK,YAAY,WAAW;GACrC,CAEkD,CAAC;GACrD,IAAI,OAAO,OACT,OAAO;IAAE,MAAM,OAAO;IAAO,SAAS;GAAK;GAE7C,OAAO,EAAE,MAAM,iBAAiB,OAAO,MAAM,EAAE;EACjD,SAAS,OAAO;GACd,OAAO;IAAE,MAAM,YAAY,KAAK;IAAG,SAAS;GAAK;EACnD;CACF;CAEA,eAAe,QAAQ,MAAmC;EACxD,IAAI;EACJ,IAAI;GACF,IAAI,QAAQ,QACV,UAAU,MAAM,WAAW,QAAQ,QAAQ;IACzC,WAAW,QAAQ;IACnB,SAAS,QAAQ;GACnB,CAAC;QACI,IAAI,QAAQ,SACjB,UAAU,MAAM,eAAe,QAAQ,SAAS,QAAQ,OAAO;QAE/D,OAAO;IACL,MAAM;IACN,SAAS;GACX;GAyBF,MAAM,SAAS,MAAM,SAAS,QAAQ,MAAM,CArB1C;IACE,MAAM;IACN,KAAK;KACH,MAAM,OAAO,QAAiB,QAAiB,SAC7C,QAAS,KACP,QACA,QACA,IACF;KACF,gBAAgB,OAAO,UAAmB,SACxC,QAAS,eACP,UACA,IACF;KACF,aAAa,OAAO,UAClB,QAAS,YAAY,KAA2B;KAClD,eAAe,YAAY,QAAS,cAAc;IACpD;GACF,CAGkD,CAAC;GACrD,IAAI,OAAO,OACT,OAAO;IAAE,MAAM,OAAO;IAAO,SAAS;GAAK;GAE7C,OAAO,EAAE,MAAM,iBAAiB,OAAO,MAAM,EAAE;EACjD,SAAS,OAAO;GACd,OAAO;IAAE,MAAM,YAAY,KAAK;IAAG,SAAS;GAAK;EACnD,UAAU;GACR,SAAS,MAAM;EACjB;CACF;CAEA,OAAO;EAAE;EAAQ;CAAQ;AAC3B"}
@@ -1,5 +1,5 @@
1
- import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "../classPrivateFieldGet2-Evpt0SEr.js";
2
- import { t as _classPrivateMethodInitSpec } from "../classPrivateMethodInitSpec-bG0tD96O.js";
1
+ import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "../classPrivateFieldGet2-D_obpP6O.js";
2
+ import { t as _classPrivateMethodInitSpec } from "../classPrivateMethodInitSpec-10iTYB7F.js";
3
3
  import { tool } from "ai";
4
4
  import { RpcTarget } from "cloudflare:workers";
5
5
  import { z } from "zod";
@@ -4,7 +4,7 @@ import {
4
4
  Kt as getSubAgentByName,
5
5
  Wt as SUB_PREFIX,
6
6
  qt as parseSubAgentPath
7
- } from "./agent-tool-types-LInzZfLo.js";
7
+ } from "./agent-tool-types-BAJWu8s4.js";
8
8
  export {
9
9
  SUB_PREFIX,
10
10
  SubAgentPathMatch,
@@ -95,4 +95,4 @@ function stringifyForLength(value) {
95
95
  //#endregion
96
96
  export { truncateToolOutput as t };
97
97
 
98
- //# sourceMappingURL=tool-output-truncation-BF4AZQlw.js.map
98
+ //# sourceMappingURL=tool-output-truncation-CNnnGZQ3.js.map