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.
Files changed (137) hide show
  1. package/README.md +1 -0
  2. package/dist/{agent-tool-types-CzGGB-20.d.ts → agent-routing-CnkaHb-v.d.ts} +2921 -3057
  3. package/dist/agent-routing.d.ts +14 -0
  4. package/dist/agent-routing.js +187 -0
  5. package/dist/agent-routing.js.map +1 -0
  6. package/dist/agent-tool-types.d.ts +26 -26
  7. package/dist/{agent-tools-zR2d5uij.d.ts → agent-tools-C0XJqWzB.d.ts} +7 -7
  8. package/dist/agent-tools.d.ts +21 -21
  9. package/dist/agent-tools.js +2 -1
  10. package/dist/agent-tools.js.map +1 -1
  11. package/dist/browser/ai.js +2 -1
  12. package/dist/browser/ai.js.map +1 -1
  13. package/dist/capability-BjSKYpzg.js +42 -0
  14. package/dist/capability-BjSKYpzg.js.map +1 -0
  15. package/dist/capability-runner-CvHGZqUu.d.ts +150 -0
  16. package/dist/chat/index.d.ts +22 -15
  17. package/dist/chat/index.js +4 -4
  18. package/dist/chat/index.js.map +1 -1
  19. package/dist/chat/react.d.ts +14 -1
  20. package/dist/chat/react.js +82 -52
  21. package/dist/chat/react.js.map +1 -1
  22. package/dist/chat/transport.js +1 -1
  23. package/dist/chat-sdk/index.d.ts +4 -4
  24. package/dist/chat-sdk/index.js +1 -1
  25. package/dist/{client-zqKcsyFa.js → client-jagG8a9_.js} +129 -37
  26. package/dist/client-jagG8a9_.js.map +1 -0
  27. package/dist/client.d.ts +1 -1
  28. package/dist/client.js +1 -1
  29. package/dist/{cloudflare-BduZwmYK.js → cloudflare-Dzvc7V2N.js} +10 -3
  30. package/dist/{cloudflare-BduZwmYK.js.map → cloudflare-Dzvc7V2N.js.map} +1 -1
  31. package/dist/current-agent-CuMErtly.d.ts +283 -0
  32. package/dist/current-agent-DhoDkSnH.js +51 -0
  33. package/dist/current-agent-DhoDkSnH.js.map +1 -0
  34. package/dist/diagnostics-CaBjfz4J.js +41 -0
  35. package/dist/diagnostics-CaBjfz4J.js.map +1 -0
  36. package/dist/{do-oauth-client-provider-VTZj2VtM.d.ts → do-oauth-client-provider-Tmf1vgKz.d.ts} +2 -2
  37. package/dist/durable-object-lifecycle-D6nNQJJd.js +862 -0
  38. package/dist/durable-object-lifecycle-D6nNQJJd.js.map +1 -0
  39. package/dist/{email-CL27preh.d.ts → email-7TatiTnl.d.ts} +38 -9
  40. package/dist/email-send.d.ts +15 -0
  41. package/dist/email-send.js +32 -0
  42. package/dist/email-send.js.map +1 -0
  43. package/dist/email.d.ts +14 -10
  44. package/dist/email.js.map +1 -1
  45. package/dist/experimental/memory/session/index.d.ts +3 -2
  46. package/dist/experimental/memory/session/index.js +15 -10
  47. package/dist/experimental/memory/session/index.js.map +1 -1
  48. package/dist/{handler-stateless-C_bo-Ytq.d.ts → handler-stateless-DxYpJ_XF.d.ts} +3 -3
  49. package/dist/{handler-stateless-CIkKPETH.js → handler-stateless-VvrWSAVA.js} +5 -5
  50. package/dist/handler-stateless-VvrWSAVA.js.map +1 -0
  51. package/dist/{index-BRnybD6X.d.ts → index-DcSAZKsB.d.ts} +19 -31
  52. package/dist/index.d.ts +98 -95
  53. package/dist/index.js +10 -7234
  54. package/dist/internal_context-BlxFEWfn.d.ts +19 -0
  55. package/dist/internal_context.d.ts +10 -4
  56. package/dist/internal_context.js +1 -10
  57. package/dist/{client-invoker-BNSZxAkv.d.ts → invoker-CG0_p_Wq.d.ts} +2 -2
  58. package/dist/{client-invoker-VNZ7X0nn.js → invoker-CHMnoxIA.js} +2 -2
  59. package/dist/invoker-CHMnoxIA.js.map +1 -0
  60. package/dist/lifecycle/index.d.ts +48 -0
  61. package/dist/lifecycle/index.js +4 -0
  62. package/dist/mcp/{do-oauth-client-provider.d.ts → client/do-oauth-client-provider.d.ts} +1 -1
  63. package/dist/mcp/{do-oauth-client-provider.js → client/do-oauth-client-provider.js} +1 -1
  64. package/dist/mcp/client/do-oauth-client-provider.js.map +1 -0
  65. package/dist/mcp/client/index.d.ts +42 -0
  66. package/dist/mcp/{client.js → client/index.js} +1 -1
  67. package/dist/mcp/{x402.d.ts → client/x402.d.ts} +2 -2
  68. package/dist/mcp/{x402.js → client/x402.js} +2 -2
  69. package/dist/mcp/client/x402.js.map +1 -0
  70. package/dist/mcp/index.d.ts +36 -36
  71. package/dist/mcp/index.js +14 -16
  72. package/dist/mcp/index.js.map +1 -1
  73. package/dist/mcp/{server.d.ts → server/index.d.ts} +1 -1
  74. package/dist/mcp/{server.js → server/index.js} +1 -1
  75. package/dist/observability/ai/index.js +50 -35
  76. package/dist/observability/ai/index.js.map +1 -1
  77. package/dist/observability/index.d.ts +4 -4
  78. package/dist/observability/index.js +3 -50
  79. package/dist/observability/index.js.map +1 -1
  80. package/dist/{protocol-Dqc2MQxo.js → protocol-B0nh6KNf.js} +19 -21
  81. package/dist/protocol-B0nh6KNf.js.map +1 -0
  82. package/dist/react.d.ts +4 -4
  83. package/dist/react.js +1 -1
  84. package/dist/schedule.d.ts +25 -94
  85. package/dist/schedule.js +1 -98
  86. package/dist/schedule.js.map +1 -1
  87. package/dist/scheduler-CR9RHGos.js +857 -0
  88. package/dist/scheduler-CR9RHGos.js.map +1 -0
  89. package/dist/scheduler-DQoTGoAW.d.ts +224 -0
  90. package/dist/schedules/index.d.ts +22 -0
  91. package/dist/schedules/index.js +2 -0
  92. package/dist/schedules/parser.d.ts +79 -0
  93. package/dist/schedules/parser.js +103 -0
  94. package/dist/schedules/parser.js.map +1 -0
  95. package/dist/serializable.d.ts +1 -1
  96. package/dist/sql-error-CPY-GXyI.d.ts +12 -0
  97. package/dist/sql-error.d.ts +2 -0
  98. package/dist/sql-error.js +16 -0
  99. package/dist/sql-error.js.map +1 -0
  100. package/dist/src-5W6JNKVb.js +6613 -0
  101. package/dist/src-5W6JNKVb.js.map +1 -0
  102. package/dist/sub-routing.d.ts +12 -12
  103. package/dist/workflow-types.d.ts +25 -25
  104. package/dist/workflows.d.ts +22 -22
  105. package/dist/workflows.js +2 -1
  106. package/dist/workflows.js.map +1 -1
  107. package/dist/{ws-chat-transport-CIoOBbO7.js → ws-chat-transport-rWwta645.js} +152 -15
  108. package/dist/ws-chat-transport-rWwta645.js.map +1 -0
  109. package/docs/agent-class.md +28 -86
  110. package/docs/chat-agents.md +13 -12
  111. package/docs/durable-execution.md +1 -1
  112. package/docs/http-websockets.md +1 -11
  113. package/docs/human-in-the-loop.md +1 -1
  114. package/docs/index.md +1 -0
  115. package/docs/lifecycle.md +323 -0
  116. package/docs/long-running-agents.md +2 -4
  117. package/docs/mcp-client.md +55 -0
  118. package/docs/observability.md +11 -11
  119. package/docs/resumable-streaming.md +1 -1
  120. package/docs/scheduling.md +175 -15
  121. package/docs/server-driven-messages.md +1 -1
  122. package/docs/sub-agents.md +1 -1
  123. package/package.json +30 -21
  124. package/dist/cli/index.d.ts +0 -1
  125. package/dist/cli/index.js +0 -26
  126. package/dist/cli/index.js.map +0 -1
  127. package/dist/client-invoker-VNZ7X0nn.js.map +0 -1
  128. package/dist/client-zqKcsyFa.js.map +0 -1
  129. package/dist/handler-stateless-CIkKPETH.js.map +0 -1
  130. package/dist/index.js.map +0 -1
  131. package/dist/internal_context-Dg4Cgjcu.d.ts +0 -37
  132. package/dist/internal_context.js.map +0 -1
  133. package/dist/mcp/client.d.ts +0 -42
  134. package/dist/mcp/do-oauth-client-provider.js.map +0 -1
  135. package/dist/mcp/x402.js.map +0 -1
  136. package/dist/protocol-Dqc2MQxo.js.map +0 -1
  137. package/dist/ws-chat-transport-CIoOBbO7.js.map +0 -1
@@ -0,0 +1,14 @@
1
+ import {
2
+ a as routeAgentRequest,
3
+ i as getAgentByName,
4
+ n as AgentOptions,
5
+ r as RoutingRetryOptions,
6
+ t as AgentGetOptions
7
+ } from "./agent-routing-CnkaHb-v.js";
8
+ export {
9
+ AgentGetOptions,
10
+ AgentOptions,
11
+ RoutingRetryOptions,
12
+ getAgentByName,
13
+ routeAgentRequest
14
+ };
@@ -0,0 +1,187 @@
1
+ import { camelCaseToKebabCase } from "./utils.js";
2
+ //#region src/agent-routing.ts
3
+ const namespaceMapCache = /* @__PURE__ */ new WeakMap();
4
+ const bindingNameCache = /* @__PURE__ */ new WeakMap();
5
+ const DEFAULT_ROUTING_RETRY_OPTIONS = {
6
+ maxAttempts: 3,
7
+ baseDelayMs: 100,
8
+ maxDelayMs: 800
9
+ };
10
+ function durableObjectGetOptions(options) {
11
+ return options?.locationHint ? { locationHint: options.locationHint } : void 0;
12
+ }
13
+ function validatePositiveInteger(value, name) {
14
+ if (!Number.isFinite(value) || value < 1) throw new Error(`${name} must be >= 1`);
15
+ if (!Number.isInteger(value)) throw new Error(`${name} must be an integer`);
16
+ }
17
+ function validatePositiveNumber(value, name) {
18
+ if (!Number.isFinite(value) || value <= 0) throw new Error(`${name} must be > 0`);
19
+ }
20
+ function resolveRoutingRetryOptions(options) {
21
+ if (options === false) return null;
22
+ const resolved = {
23
+ maxAttempts: options?.maxAttempts ?? DEFAULT_ROUTING_RETRY_OPTIONS.maxAttempts,
24
+ baseDelayMs: options?.baseDelayMs ?? DEFAULT_ROUTING_RETRY_OPTIONS.baseDelayMs,
25
+ maxDelayMs: options?.maxDelayMs ?? DEFAULT_ROUTING_RETRY_OPTIONS.maxDelayMs,
26
+ onRetry: options?.onRetry
27
+ };
28
+ validatePositiveInteger(resolved.maxAttempts, "routingRetry.maxAttempts");
29
+ validatePositiveNumber(resolved.baseDelayMs, "routingRetry.baseDelayMs");
30
+ validatePositiveNumber(resolved.maxDelayMs, "routingRetry.maxDelayMs");
31
+ if (resolved.baseDelayMs > resolved.maxDelayMs) throw new Error("routingRetry.baseDelayMs must be <= maxDelayMs");
32
+ return resolved;
33
+ }
34
+ function isRetryableDurableObjectError(error) {
35
+ if (typeof error !== "object" || error === null) return false;
36
+ const typed = error;
37
+ return typed.retryable === true && typed.overloaded !== true;
38
+ }
39
+ function routingRetryDelayMs(attempt, options) {
40
+ const upperBoundMs = Math.min(options.maxDelayMs, options.baseDelayMs * 2 ** (attempt - 1));
41
+ return Math.floor(Math.random() * upperBoundMs);
42
+ }
43
+ async function retryDurableObjectOperation(operation, context, retryOptions) {
44
+ const resolved = resolveRoutingRetryOptions(retryOptions);
45
+ if (!resolved) return await operation();
46
+ let attempt = 1;
47
+ while (true) try {
48
+ return await operation();
49
+ } catch (error) {
50
+ const nextAttempt = attempt + 1;
51
+ if (nextAttempt > resolved.maxAttempts || !isRetryableDurableObjectError(error)) throw error;
52
+ const delayMs = routingRetryDelayMs(attempt, resolved);
53
+ try {
54
+ await resolved.onRetry?.({
55
+ error,
56
+ attempt,
57
+ maxAttempts: resolved.maxAttempts,
58
+ delayMs,
59
+ name: context.name,
60
+ className: context.className
61
+ });
62
+ } catch (callbackError) {
63
+ console.warn("Durable Object routing retry callback failed:", callbackError);
64
+ }
65
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
66
+ attempt = nextAttempt;
67
+ }
68
+ }
69
+ function encodeLifecycleProps(props) {
70
+ const bytes = new TextEncoder().encode(JSON.stringify(props));
71
+ let binary = "";
72
+ for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
73
+ return btoa(binary);
74
+ }
75
+ function mutableRequest(request) {
76
+ return new Request(request);
77
+ }
78
+ function cloneRequestForFetch(request) {
79
+ return request.clone();
80
+ }
81
+ function resolveCorsHeaders(cors) {
82
+ if (cors === true) return {
83
+ "Access-Control-Allow-Origin": "*",
84
+ "Access-Control-Allow-Methods": "GET, POST, HEAD, OPTIONS",
85
+ "Access-Control-Allow-Headers": "*",
86
+ "Access-Control-Max-Age": "86400"
87
+ };
88
+ if (cors && typeof cors === "object") {
89
+ const headers = new Headers(cors);
90
+ const record = {};
91
+ headers.forEach((value, key) => {
92
+ record[key] = value;
93
+ });
94
+ return record;
95
+ }
96
+ return null;
97
+ }
98
+ /**
99
+ * Route `/agents/:binding/:name` HTTP and WebSocket requests to a named
100
+ * Durable Object. The target may extend `Agent` or compose `Lifecycle`
101
+ * directly into a plain `DurableObject`.
102
+ *
103
+ * @param request - Incoming Worker request.
104
+ * @param env - Worker environment containing Durable Object bindings.
105
+ * @param options - Routing options.
106
+ * @returns The matched response, or `null` when the path does not match.
107
+ */
108
+ async function routeAgentRequest(request, env, options) {
109
+ const environment = env;
110
+ if (!namespaceMapCache.has(environment)) {
111
+ const namespaceMap = {};
112
+ const bindingNames = {};
113
+ for (const [key, value] of Object.entries(environment)) if (value && typeof value === "object" && "idFromName" in value && typeof value.idFromName === "function") {
114
+ const kebab = camelCaseToKebabCase(key);
115
+ namespaceMap[kebab] = value;
116
+ bindingNames[kebab] = key;
117
+ }
118
+ namespaceMapCache.set(environment, namespaceMap);
119
+ bindingNameCache.set(environment, bindingNames);
120
+ }
121
+ const map = namespaceMapCache.get(environment);
122
+ const bindingNames = bindingNameCache.get(environment);
123
+ const prefixParts = (options?.prefix || "agents").split("/");
124
+ const parts = new URL(request.url).pathname.split("/").filter(Boolean);
125
+ if (!prefixParts.every((part, index) => parts[index] === part) || parts.length < prefixParts.length + 2) return null;
126
+ const namespaceName = parts[prefixParts.length];
127
+ const name = parts[prefixParts.length + 1];
128
+ if (!name || !namespaceName) return null;
129
+ const boundNamespace = map[namespaceName];
130
+ if (!boundNamespace) {
131
+ console.error(`The URL ${request.url} with namespace "${namespaceName}" and name "${name}" does not match any Durable Object binding.`);
132
+ return new Response("Invalid request", { status: 400 });
133
+ }
134
+ const corsHeaders = resolveCorsHeaders(options?.cors);
135
+ const isWebSocket = request.headers.get("Upgrade")?.toLowerCase() === "websocket";
136
+ const withCorsHeaders = (response) => {
137
+ if (!corsHeaders || isWebSocket) return response;
138
+ const nextResponse = new Response(response.body, response);
139
+ for (const [key, value] of Object.entries(corsHeaders)) nextResponse.headers.set(key, value);
140
+ return nextResponse;
141
+ };
142
+ if (request.method === "OPTIONS" && corsHeaders) return new Response(null, { headers: corsHeaders });
143
+ const namespace = options?.jurisdiction ? boundNamespace.jurisdiction(options.jurisdiction) : boundNamespace;
144
+ const id = namespace.idFromName(name);
145
+ const getOptions = durableObjectGetOptions(options);
146
+ request = mutableRequest(request);
147
+ const className = bindingNames[namespaceName];
148
+ const route = {
149
+ className,
150
+ name
151
+ };
152
+ if (isWebSocket) {
153
+ const requestOrResponse = await options?.onBeforeConnect?.(request, route);
154
+ if (requestOrResponse instanceof Request) request = mutableRequest(requestOrResponse);
155
+ else if (requestOrResponse instanceof Response) return requestOrResponse;
156
+ } else {
157
+ const requestOrResponse = await options?.onBeforeRequest?.(request, route);
158
+ if (requestOrResponse instanceof Request) request = mutableRequest(requestOrResponse);
159
+ else if (requestOrResponse instanceof Response) return withCorsHeaders(requestOrResponse);
160
+ }
161
+ if (options?.props !== void 0) request.headers.set("x-agents-lifecycle-props", encodeLifecycleProps(options.props));
162
+ const response = await retryDurableObjectOperation(() => namespace.get(id, getOptions).fetch(cloneRequestForFetch(request)), {
163
+ name,
164
+ className
165
+ }, options?.routingRetry);
166
+ return isWebSocket ? response : withCorsHeaders(response);
167
+ }
168
+ /**
169
+ * Get a named Agent stub after its lifecycle startup has completed.
170
+ *
171
+ * @param namespace - Agent Durable Object namespace.
172
+ * @param name - Agent instance name.
173
+ * @param options - Placement, startup properties, and retry options.
174
+ * @returns The initialized Agent stub.
175
+ */
176
+ async function getAgentByName(namespace, name, options) {
177
+ const target = options?.jurisdiction ? namespace.jurisdiction(options.jurisdiction) : namespace;
178
+ const id = target.idFromName(name);
179
+ const stub = target.get(id, durableObjectGetOptions(options));
180
+ const lifecycleStub = stub;
181
+ await retryDurableObjectOperation(() => lifecycleStub.__unsafe_ensureInitialized(options?.props), { name }, options?.routingRetry);
182
+ return stub;
183
+ }
184
+ //#endregion
185
+ export { getAgentByName, routeAgentRequest };
186
+
187
+ //# sourceMappingURL=agent-routing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-routing.js","names":[],"sources":["../src/agent-routing.ts"],"sourcesContent":["import type { Agent } from \"./index\";\nimport { camelCaseToKebabCase } from \"./utils\";\n\nconst namespaceMapCache = new WeakMap<\n object,\n Record<string, DurableObjectNamespace>\n>();\nconst bindingNameCache = new WeakMap<object, Record<string, string>>();\n\nconst DEFAULT_ROUTING_RETRY_OPTIONS = {\n maxAttempts: 3,\n baseDelayMs: 100,\n maxDelayMs: 800\n};\n\ninterface RoutingRetryEvent {\n error: unknown;\n attempt: number;\n maxAttempts: number;\n delayMs: number;\n name: string;\n className?: string;\n}\n\n/** Retry policy for Agent routing infrastructure failures. */\nexport interface RoutingRetryOptions {\n /** Max number of attempts, including the first. Default: 3. */\n maxAttempts?: number;\n /** Base delay in milliseconds for exponential backoff. Default: 100. */\n baseDelayMs?: number;\n /** Maximum delay in milliseconds. Default: 800. */\n maxDelayMs?: number;\n /** Optional callback invoked before each retry delay. */\n onRetry?: (event: RoutingRetryEvent) => void | Promise<void>;\n}\n\ninterface AgentRouteMatch<Env = Cloudflare.Env> {\n /** The Durable Object environment binding name. */\n className: Extract<keyof Env, string>;\n /** The named Durable Object instance extracted from the URL. */\n name: string;\n}\n\ninterface AgentRouteOptions<\n Env = Cloudflare.Env,\n Props extends Record<string, unknown> = Record<string, unknown>\n> {\n /** URL prefix before the binding and instance name. Default: `agents`. */\n prefix?: string;\n jurisdiction?: DurableObjectJurisdiction;\n locationHint?: DurableObjectLocationHint;\n /** Properties supplied before lifecycle startup. */\n props?: Props;\n /**\n * Whether to enable CORS for matched routes.\n *\n * When `true`, uses default permissive CORS headers:\n * - Access-Control-Allow-Origin: *\n * - Access-Control-Allow-Methods: GET, POST, HEAD, OPTIONS\n * - Access-Control-Allow-Headers: *\n * - Access-Control-Max-Age: 86400\n *\n * For credentialed requests, pass explicit headers with a specific origin.\n * When set to a `HeadersInit` value, uses those as the CORS headers instead.\n * CORS preflight requests are handled automatically for matched routes.\n */\n cors?: boolean | HeadersInit;\n /**\n * Retry transient Durable Object infrastructure errors thrown while routing.\n * Enabled by default; pass `false` to disable.\n */\n routingRetry?: false | RoutingRetryOptions;\n onBeforeConnect?: (\n request: Request,\n route: AgentRouteMatch<Env>\n ) => Response | Request | void | Promise<Response | Request | void>;\n onBeforeRequest?: (\n request: Request,\n route: AgentRouteMatch<Env>\n ) =>\n | Response\n | Request\n | void\n | Promise<Response | Request | undefined | void>;\n}\n\n/** Configuration options for {@link routeAgentRequest}. */\nexport type AgentOptions<Env> = AgentRouteOptions<Env>;\n\n/** Options for resolving and starting a named Agent. */\nexport type AgentGetOptions<\n Env,\n Props extends Record<string, unknown> = Record<string, unknown>\n> = Pick<\n AgentRouteOptions<Env, Props>,\n \"jurisdiction\" | \"locationHint\" | \"props\" | \"routingRetry\"\n>;\n\ninterface ResolvedRoutingRetryOptions extends Required<\n Omit<RoutingRetryOptions, \"onRetry\">\n> {\n onRetry?: RoutingRetryOptions[\"onRetry\"];\n}\n\ninterface RoutingRetryContext {\n name: string;\n className?: string;\n}\n\nfunction durableObjectGetOptions(\n options: { locationHint?: DurableObjectLocationHint } | undefined\n) {\n return options?.locationHint\n ? { locationHint: options.locationHint }\n : undefined;\n}\n\nfunction validatePositiveInteger(value: number, name: string): void {\n if (!Number.isFinite(value) || value < 1) {\n throw new Error(`${name} must be >= 1`);\n }\n if (!Number.isInteger(value)) {\n throw new Error(`${name} must be an integer`);\n }\n}\n\nfunction validatePositiveNumber(value: number, name: string): void {\n if (!Number.isFinite(value) || value <= 0) {\n throw new Error(`${name} must be > 0`);\n }\n}\n\nfunction resolveRoutingRetryOptions(\n options: false | RoutingRetryOptions | undefined\n): ResolvedRoutingRetryOptions | null {\n if (options === false) return null;\n\n const resolved = {\n maxAttempts:\n options?.maxAttempts ?? DEFAULT_ROUTING_RETRY_OPTIONS.maxAttempts,\n baseDelayMs:\n options?.baseDelayMs ?? DEFAULT_ROUTING_RETRY_OPTIONS.baseDelayMs,\n maxDelayMs: options?.maxDelayMs ?? DEFAULT_ROUTING_RETRY_OPTIONS.maxDelayMs,\n onRetry: options?.onRetry\n };\n\n validatePositiveInteger(resolved.maxAttempts, \"routingRetry.maxAttempts\");\n validatePositiveNumber(resolved.baseDelayMs, \"routingRetry.baseDelayMs\");\n validatePositiveNumber(resolved.maxDelayMs, \"routingRetry.maxDelayMs\");\n if (resolved.baseDelayMs > resolved.maxDelayMs) {\n throw new Error(\"routingRetry.baseDelayMs must be <= maxDelayMs\");\n }\n\n return resolved;\n}\n\nfunction isRetryableDurableObjectError(error: unknown): boolean {\n if (typeof error !== \"object\" || error === null) return false;\n // SAFETY: Cloudflare's retryable and overloaded error flags are optional\n // runtime properties not represented on the base Error type.\n const typed = error as { retryable?: boolean; overloaded?: boolean };\n return typed.retryable === true && typed.overloaded !== true;\n}\n\nfunction routingRetryDelayMs(\n attempt: number,\n options: ResolvedRoutingRetryOptions\n): number {\n const upperBoundMs = Math.min(\n options.maxDelayMs,\n options.baseDelayMs * 2 ** (attempt - 1)\n );\n return Math.floor(Math.random() * upperBoundMs);\n}\n\nasync function retryDurableObjectOperation<T>(\n operation: () => Promise<T>,\n context: RoutingRetryContext,\n retryOptions: false | RoutingRetryOptions | undefined\n): Promise<T> {\n const resolved = resolveRoutingRetryOptions(retryOptions);\n if (!resolved) return await operation();\n\n let attempt = 1;\n while (true) {\n try {\n return await operation();\n } catch (error) {\n const nextAttempt = attempt + 1;\n if (\n nextAttempt > resolved.maxAttempts ||\n !isRetryableDurableObjectError(error)\n ) {\n throw error;\n }\n\n const delayMs = routingRetryDelayMs(attempt, resolved);\n try {\n await resolved.onRetry?.({\n error,\n attempt,\n maxAttempts: resolved.maxAttempts,\n delayMs,\n name: context.name,\n className: context.className\n });\n } catch (callbackError) {\n console.warn(\n \"Durable Object routing retry callback failed:\",\n callbackError\n );\n }\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n attempt = nextAttempt;\n }\n }\n}\n\nfunction encodeLifecycleProps(props: unknown): string {\n const bytes = new TextEncoder().encode(JSON.stringify(props));\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n}\n\nfunction mutableRequest(request: Request): Request {\n return new Request(request);\n}\n\nfunction cloneRequestForFetch(request: Request): Request {\n // SAFETY: Workers Types v5 preserves an unconstrained `cf` generic from\n // clone(). Cloning does not change the runtime Request representation.\n return request.clone() as Request;\n}\n\nfunction resolveCorsHeaders(\n cors: boolean | HeadersInit | undefined\n): Record<string, string> | null {\n if (cors === true) {\n return {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, HEAD, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"*\",\n \"Access-Control-Max-Age\": \"86400\"\n };\n }\n if (cors && typeof cors === \"object\") {\n const headers = new Headers(cors);\n const record: Record<string, string> = {};\n headers.forEach((value, key) => {\n record[key] = value;\n });\n return record;\n }\n return null;\n}\n\n/**\n * Route `/agents/:binding/:name` HTTP and WebSocket requests to a named\n * Durable Object. The target may extend `Agent` or compose `Lifecycle`\n * directly into a plain `DurableObject`.\n *\n * @param request - Incoming Worker request.\n * @param env - Worker environment containing Durable Object bindings.\n * @param options - Routing options.\n * @returns The matched response, or `null` when the path does not match.\n */\nexport async function routeAgentRequest<Env>(\n request: Request,\n env: Env,\n options?: AgentOptions<Env>\n): Promise<Response | null> {\n // SAFETY: Worker environments are object records. The unconstrained Env\n // generic is retained for compatibility with the previously published API.\n const environment = env as object;\n if (!namespaceMapCache.has(environment)) {\n const namespaceMap: Record<string, DurableObjectNamespace> = {};\n const bindingNames: Record<string, string> = {};\n for (const [key, value] of Object.entries(environment)) {\n if (\n value &&\n typeof value === \"object\" &&\n \"idFromName\" in value &&\n typeof value.idFromName === \"function\"\n ) {\n const kebab = camelCaseToKebabCase(key);\n // SAFETY: The structural idFromName check above identifies a Durable\n // Object namespace at the Worker environment boundary.\n namespaceMap[kebab] = value as DurableObjectNamespace;\n bindingNames[kebab] = key;\n }\n }\n namespaceMapCache.set(environment, namespaceMap);\n bindingNameCache.set(environment, bindingNames);\n }\n\n const map = namespaceMapCache.get(environment) as Record<\n string,\n DurableObjectNamespace\n >;\n const bindingNames = bindingNameCache.get(environment) as Record<\n string,\n string\n >;\n const prefixParts = (options?.prefix || \"agents\").split(\"/\");\n const parts = new URL(request.url).pathname.split(\"/\").filter(Boolean);\n const prefixMatches = prefixParts.every(\n (part, index) => parts[index] === part\n );\n if (!prefixMatches || parts.length < prefixParts.length + 2) return null;\n\n const namespaceName = parts[prefixParts.length];\n const name = parts[prefixParts.length + 1];\n if (!name || !namespaceName) return null;\n\n const boundNamespace = map[namespaceName];\n if (!boundNamespace) {\n console.error(\n `The URL ${request.url} with namespace \"${namespaceName}\" and name \"${name}\" does not match any Durable Object binding.`\n );\n return new Response(\"Invalid request\", { status: 400 });\n }\n\n const corsHeaders = resolveCorsHeaders(options?.cors);\n const isWebSocket =\n request.headers.get(\"Upgrade\")?.toLowerCase() === \"websocket\";\n const withCorsHeaders = (response: Response): Response => {\n if (!corsHeaders || isWebSocket) return response;\n const nextResponse = new Response(response.body, response);\n for (const [key, value] of Object.entries(corsHeaders)) {\n nextResponse.headers.set(key, value);\n }\n return nextResponse;\n };\n\n if (request.method === \"OPTIONS\" && corsHeaders) {\n return new Response(null, { headers: corsHeaders });\n }\n\n const namespace = options?.jurisdiction\n ? boundNamespace.jurisdiction(options.jurisdiction)\n : boundNamespace;\n const id = namespace.idFromName(name);\n const getOptions = durableObjectGetOptions(options);\n request = mutableRequest(request);\n\n // SAFETY: binding names come directly from Object.entries(env), so they are\n // string keys of Env.\n const className = bindingNames[namespaceName] as Extract<keyof Env, string>;\n const route: AgentRouteMatch<Env> = { className, name };\n\n if (isWebSocket) {\n const requestOrResponse = await options?.onBeforeConnect?.(request, route);\n if (requestOrResponse instanceof Request) {\n request = mutableRequest(requestOrResponse);\n } else if (requestOrResponse instanceof Response) {\n return requestOrResponse;\n }\n } else {\n const requestOrResponse = await options?.onBeforeRequest?.(request, route);\n if (requestOrResponse instanceof Request) {\n request = mutableRequest(requestOrResponse);\n } else if (requestOrResponse instanceof Response) {\n return withCorsHeaders(requestOrResponse);\n }\n }\n\n if (options?.props !== undefined) {\n request.headers.set(\n \"x-agents-lifecycle-props\",\n encodeLifecycleProps(options.props)\n );\n }\n\n const response = await retryDurableObjectOperation(\n () => namespace.get(id, getOptions).fetch(cloneRequestForFetch(request)),\n { name, className },\n options?.routingRetry\n );\n return isWebSocket ? response : withCorsHeaders(response);\n}\n\n/**\n * Get a named Agent stub after its lifecycle startup has completed.\n *\n * @param namespace - Agent Durable Object namespace.\n * @param name - Agent instance name.\n * @param options - Placement, startup properties, and retry options.\n * @returns The initialized Agent stub.\n */\nexport async function getAgentByName<\n Env extends Cloudflare.Env = Cloudflare.Env,\n T extends Agent<Env> = Agent<Env>,\n Props extends Record<string, unknown> = Record<string, unknown>\n>(\n namespace: DurableObjectNamespace<T>,\n name: string,\n options?: AgentGetOptions<Env, Props>\n): Promise<DurableObjectStub<T>> {\n const target = options?.jurisdiction\n ? namespace.jurisdiction(options.jurisdiction)\n : namespace;\n const id = target.idFromName(name);\n const stub = target.get(id, durableObjectGetOptions(options));\n\n // SAFETY: Agent exposes this internal initializer specifically for native\n // RPC calls, which bypass the lifecycle-installed fetch handler.\n const lifecycleStub = stub as unknown as {\n __unsafe_ensureInitialized(props?: Props): Promise<void>;\n };\n await retryDurableObjectOperation(\n () => lifecycleStub.__unsafe_ensureInitialized(options?.props),\n { name },\n options?.routingRetry\n );\n\n return stub;\n}\n"],"mappings":"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"}
@@ -1,30 +1,30 @@
1
1
  import {
2
- C as DetachedRunAgentToolResult,
3
- S as DetachedAgentToolConfig,
4
- T as RunAgentToolResult,
5
- _ as AgentToolRunState,
6
- a as AgentToolEvent,
7
- b as AgentToolTerminalStatus,
8
- c as AgentToolFailure,
9
- d as AgentToolMilestone,
10
- f as AgentToolProgress,
11
- g as AgentToolRunPart,
12
- h as AgentToolRunInspection,
13
- i as AgentToolDisplayMetadata,
14
- l as AgentToolInterruptedReason,
15
- m as AgentToolRunInfo,
16
- n as AGENT_TOOL_PROGRESS_PART,
17
- o as AgentToolEventMessage,
18
- p as AgentToolProgressSnapshot,
19
- r as AgentToolChildAdapter,
20
- s as AgentToolEventState,
21
- t as AGENT_TOOL_MILESTONE_PART,
22
- u as AgentToolLifecycleResult,
23
- v as AgentToolRunStatus,
24
- w as RunAgentToolOptions,
25
- x as ChatCapableAgentClass,
26
- y as AgentToolStoredChunk
27
- } from "./agent-tool-types-CzGGB-20.js";
2
+ $ as AgentToolRunPart,
3
+ B as AgentToolChildAdapter,
4
+ G as AgentToolFailure,
5
+ H as AgentToolEvent,
6
+ J as AgentToolMilestone,
7
+ K as AgentToolInterruptedReason,
8
+ Q as AgentToolRunInspection,
9
+ R as AGENT_TOOL_MILESTONE_PART,
10
+ U as AgentToolEventMessage,
11
+ V as AgentToolDisplayMetadata,
12
+ W as AgentToolEventState,
13
+ X as AgentToolProgressSnapshot,
14
+ Y as AgentToolProgress,
15
+ Z as AgentToolRunInfo,
16
+ at as DetachedAgentToolConfig,
17
+ ct as RunAgentToolResult,
18
+ et as AgentToolRunState,
19
+ it as ChatCapableAgentClass,
20
+ nt as AgentToolStoredChunk,
21
+ ot as DetachedRunAgentToolResult,
22
+ q as AgentToolLifecycleResult,
23
+ rt as AgentToolTerminalStatus,
24
+ st as RunAgentToolOptions,
25
+ tt as AgentToolRunStatus,
26
+ z as AGENT_TOOL_PROGRESS_PART
27
+ } from "./agent-routing-CnkaHb-v.js";
28
28
  export {
29
29
  AGENT_TOOL_MILESTONE_PART,
30
30
  AGENT_TOOL_PROGRESS_PART,
@@ -1,10 +1,10 @@
1
1
  import {
2
- f as AgentToolProgress,
3
- g as AgentToolRunPart,
4
- o as AgentToolEventMessage,
5
- s as AgentToolEventState,
6
- y as AgentToolStoredChunk
7
- } from "./agent-tool-types-CzGGB-20.js";
2
+ $ as AgentToolRunPart,
3
+ U as AgentToolEventMessage,
4
+ W as AgentToolEventState,
5
+ Y as AgentToolProgress,
6
+ nt as AgentToolStoredChunk
7
+ } from "./agent-routing-CnkaHb-v.js";
8
8
 
9
9
  //#region src/chat/agent-tools.d.ts
10
10
  type AgentToolProgressEmitResult = "emitted" | "coalesced" | "inactive";
@@ -130,4 +130,4 @@ export {
130
130
  interceptAgentToolBroadcast as s,
131
131
  AgentToolBroadcastHooks as t
132
132
  };
133
- //# sourceMappingURL=agent-tools-zR2d5uij.d.ts.map
133
+ //# sourceMappingURL=agent-tools-C0XJqWzB.d.ts.map
@@ -1,25 +1,25 @@
1
1
  import {
2
- C as DetachedRunAgentToolResult,
3
- S as DetachedAgentToolConfig,
4
- T as RunAgentToolResult,
5
- _ as AgentToolRunState,
6
- a as AgentToolEvent,
7
- b as AgentToolTerminalStatus,
8
- c as AgentToolFailure,
9
- g as AgentToolRunPart,
10
- h as AgentToolRunInspection,
11
- i as AgentToolDisplayMetadata,
12
- l as AgentToolInterruptedReason,
13
- m as AgentToolRunInfo,
14
- o as AgentToolEventMessage,
15
- r as AgentToolChildAdapter,
16
- s as AgentToolEventState,
17
- u as AgentToolLifecycleResult,
18
- v as AgentToolRunStatus,
19
- w as RunAgentToolOptions,
20
- x as ChatCapableAgentClass,
21
- y as AgentToolStoredChunk
22
- } from "./agent-tool-types-CzGGB-20.js";
2
+ $ as AgentToolRunPart,
3
+ B as AgentToolChildAdapter,
4
+ G as AgentToolFailure,
5
+ H as AgentToolEvent,
6
+ K as AgentToolInterruptedReason,
7
+ Q as AgentToolRunInspection,
8
+ U as AgentToolEventMessage,
9
+ V as AgentToolDisplayMetadata,
10
+ W as AgentToolEventState,
11
+ Z as AgentToolRunInfo,
12
+ at as DetachedAgentToolConfig,
13
+ ct as RunAgentToolResult,
14
+ et as AgentToolRunState,
15
+ it as ChatCapableAgentClass,
16
+ nt as AgentToolStoredChunk,
17
+ ot as DetachedRunAgentToolResult,
18
+ q as AgentToolLifecycleResult,
19
+ rt as AgentToolTerminalStatus,
20
+ st as RunAgentToolOptions,
21
+ tt as AgentToolRunStatus
22
+ } from "./agent-routing-CnkaHb-v.js";
23
23
  import { FlexibleSchema, InferSchema, Tool } from "ai";
24
24
 
25
25
  //#region src/agent-tools.d.ts
@@ -1,4 +1,5 @@
1
- import { __DO_NOT_USE_WILL_BREAK__agentContext } from "./internal_context.js";
1
+ import { t as __DO_NOT_USE_WILL_BREAK__agentContext } from "./current-agent-DhoDkSnH.js";
2
+ import "./internal_context.js";
2
3
  import { asSchema, tool } from "ai";
3
4
  //#region src/agent-tools.ts
4
5
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"agent-tools.js","names":["agentContext","createTool"],"sources":["../src/agent-tools.ts"],"sourcesContent":["import {\n asSchema,\n tool,\n type FlexibleSchema,\n type InferSchema,\n type Tool\n} from \"ai\";\nimport { __DO_NOT_USE_WILL_BREAK__agentContext as agentContext } from \"./internal_context\";\nimport type {\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult,\n AgentToolDisplayMetadata,\n AgentToolFailure\n} from \"./agent-tool-types\";\n\ntype ParseSchema<Output = unknown> = {\n parse(value: unknown): Output;\n};\n\ntype AgentToolOutputSchema<Output> =\n | FlexibleSchema<Output>\n | ParseSchema<Output>;\n\ntype AgentToolFactoryOptions<Output = unknown, Input = unknown> = {\n description: string;\n inputSchema: FlexibleSchema<Input>;\n outputSchema?: AgentToolOutputSchema<Output>;\n displayName?: string;\n icon?: string;\n display?: AgentToolDisplayMetadata;\n};\n\n// Capture the concrete schema type so the overload below can derive its input\n// with InferSchema. AgentToolFactoryOptions remains available for callers that\n// explicitly supply agentTool<Input, Output>() type arguments.\ntype InferredAgentToolFactoryOptions<\n InputSchema extends FlexibleSchema,\n Output\n> = Omit<AgentToolFactoryOptions<Output>, \"inputSchema\"> & {\n inputSchema: InputSchema;\n};\n\ntype ToolExecutionOptions = {\n toolCallId?: string;\n abortSignal?: AbortSignal;\n};\n\ntype AgentToolRunner = {\n runAgentTool<Input, Output>(\n cls: ChatCapableAgentClass,\n options: RunAgentToolOptions<Input>\n ): Promise<RunAgentToolResult<Output>>;\n};\n\n/**\n * Preserve the existing Zod-style `.parse()` output-schema contract while\n * extending validation to the other formats supported by AI SDK FlexibleSchema.\n */\nasync function validateOutput<Output>(\n schema: AgentToolOutputSchema<Output>,\n value: unknown\n): Promise<Output> {\n if (\n typeof schema === \"object\" &&\n schema !== null &&\n \"parse\" in schema &&\n typeof schema.parse === \"function\"\n ) {\n return schema.parse(value);\n }\n\n const validate = asSchema(schema as FlexibleSchema<Output>).validate;\n if (!validate) {\n throw new Error(\"agentTool outputSchema must provide runtime validation\");\n }\n\n const result = await validate(value);\n if (!result.success) throw result.error;\n return result.value;\n}\n\nfunction currentAgentToolRunner(): AgentToolRunner {\n const agent = agentContext.getStore()?.agent;\n if (\n agent === null ||\n typeof agent !== \"object\" ||\n typeof (agent as { runAgentTool?: unknown }).runAgentTool !== \"function\"\n ) {\n throw new Error(\n \"agentTool() can only run inside an Agent turn. Use it from getTools() on an Agent subclass.\"\n );\n }\n return agent as AgentToolRunner;\n}\n\nfunction failure(\n status: AgentToolFailure[\"status\"],\n error: string,\n retryable: boolean,\n extra?: Pick<AgentToolFailure, \"reason\" | \"childStillRunning\">\n): AgentToolFailure {\n return {\n ok: false,\n status,\n error,\n retryable,\n ...(extra?.reason !== undefined ? { reason: extra.reason } : {}),\n ...(extra?.childStillRunning !== undefined\n ? { childStillRunning: extra.childStillRunning }\n : {})\n };\n}\n\n/**\n * Create an AI SDK tool that dispatches a chat-capable sub-agent through\n * `Agent.runAgentTool`.\n */\nexport function agentTool<InputSchema extends FlexibleSchema, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: InferredAgentToolFactoryOptions<InputSchema, Output>\n): Tool<InferSchema<InputSchema>, string | Output | AgentToolFailure>;\n// Preserve existing callers that explicitly provide agentTool<Input, Output>().\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output, Input>\n): Tool<Input, string | Output | AgentToolFailure>;\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output, Input>\n): Tool<Input, string | Output | AgentToolFailure> {\n const createTool = tool as unknown as <I, O>(config: {\n description: string;\n inputSchema: unknown;\n execute: (input: I, options?: ToolExecutionOptions) => Promise<O>;\n }) => Tool<I, O>;\n\n return createTool<Input, string | Output | AgentToolFailure>({\n description: options.description,\n inputSchema: options.inputSchema,\n execute: async (input: Input, executeOptions?: ToolExecutionOptions) => {\n const display: AgentToolDisplayMetadata | undefined =\n options.displayName || options.icon || options.display\n ? {\n ...options.display,\n ...(options.displayName ? { name: options.displayName } : {}),\n ...(options.icon ? { icon: options.icon } : {})\n }\n : undefined;\n\n // Derive a STABLE runId from the tool call id (#1630). A tool call's id is\n // preserved in the transcript, so when a parent turn is re-run by chat\n // recovery after a deploy / eviction, the same `agentTool()` call resolves\n // to the same runId — turning the re-issue into a duplicate that\n // `runAgentTool` re-attaches to the still-running child, instead of a\n // fresh `nanoid` that spawns a brand-new child and re-runs already-\n // completed work (\"the agent went all the way back\"). Falls back to a\n // fresh id only when there is no tool call id (rare; preserves prior\n // behavior).\n const runId = executeOptions?.toolCallId\n ? `agent-tool:${executeOptions.toolCallId}`\n : undefined;\n\n const result = await currentAgentToolRunner().runAgentTool<Input, Output>(\n cls,\n {\n input,\n runId,\n parentToolCallId: executeOptions?.toolCallId,\n signal: executeOptions?.abortSignal,\n display\n }\n );\n\n if (result.status === \"completed\") {\n if (options.outputSchema) {\n if (result.output === undefined) {\n return failure(\n \"error\",\n \"agent tool completed without structured output required by outputSchema\",\n false\n );\n }\n return validateOutput(options.outputSchema, result.output);\n }\n return result.summary ?? \"\";\n }\n\n if (result.status === \"aborted\") {\n // Intentional cancellation (parent/user stopped the run) — not retryable.\n return failure(\n \"aborted\",\n result.error ?? \"agent tool run was cancelled\",\n false\n );\n }\n if (result.status === \"interrupted\") {\n // The child was reset/superseded by a deploy or parent recovery before\n // it reached a logical outcome. Re-dispatching the run can succeed, so\n // surface it as retryable rather than a terminal failure the parent\n // would report to the user as final. `retryable` is intentionally COARSE\n // (always true for `interrupted`); callers that want to distinguish a\n // self-healing child from an exhausted one branch on `reason` /\n // `childStillRunning` instead.\n return failure(\n \"interrupted\",\n result.error ??\n \"agent tool run was interrupted before it finished; it can be retried\",\n true,\n { reason: result.reason, childStillRunning: result.childStillRunning }\n );\n }\n return failure(\"error\", result.error ?? \"agent tool run failed\", false);\n }\n });\n}\n\nexport type { AgentToolFactoryOptions };\nexport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolFailure,\n AgentToolInterruptedReason,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunPart,\n AgentToolRunState,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n AgentToolTerminalStatus,\n ChatCapableAgentClass,\n DetachedAgentToolConfig,\n DetachedRunAgentToolResult,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n"],"mappings":";;;;;;;AA2DA,eAAe,eACb,QACA,OACiB;CACjB,IACE,OAAO,WAAW,YAClB,WAAW,QACX,WAAW,UACX,OAAO,OAAO,UAAU,YAExB,OAAO,OAAO,MAAM,KAAK;CAG3B,MAAM,WAAW,SAAS,MAAgC,CAAC,CAAC;CAC5D,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,wDAAwD;CAG1E,MAAM,SAAS,MAAM,SAAS,KAAK;CACnC,IAAI,CAAC,OAAO,SAAS,MAAM,OAAO;CAClC,OAAO,OAAO;AAChB;AAEA,SAAS,yBAA0C;CACjD,MAAM,QAAQA,sCAAa,SAAS,CAAC,EAAE;CACvC,IACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAqC,iBAAiB,YAE9D,MAAM,IAAI,MACR,6FACF;CAEF,OAAO;AACT;AAEA,SAAS,QACP,QACA,OACA,WACA,OACkB;CAClB,OAAO;EACL,IAAI;EACJ;EACA;EACA;EACA,GAAI,OAAO,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;EAC9D,GAAI,OAAO,sBAAsB,KAAA,IAC7B,EAAE,mBAAmB,MAAM,kBAAkB,IAC7C,CAAC;CACP;AACF;AAeA,SAAgB,UACd,KACA,SACiD;CAOjD,OAAOC,KAAsD;EAC3D,aAAa,QAAQ;EACrB,aAAa,QAAQ;EACrB,SAAS,OAAO,OAAc,mBAA0C;GACtE,MAAM,UACJ,QAAQ,eAAe,QAAQ,QAAQ,QAAQ,UAC3C;IACE,GAAG,QAAQ;IACX,GAAI,QAAQ,cAAc,EAAE,MAAM,QAAQ,YAAY,IAAI,CAAC;IAC3D,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;GAC/C,IACA,KAAA;GAWN,MAAM,QAAQ,gBAAgB,aAC1B,cAAc,eAAe,eAC7B,KAAA;GAEJ,MAAM,SAAS,MAAM,uBAAuB,CAAC,CAAC,aAC5C,KACA;IACE;IACA;IACA,kBAAkB,gBAAgB;IAClC,QAAQ,gBAAgB;IACxB;GACF,CACF;GAEA,IAAI,OAAO,WAAW,aAAa;IACjC,IAAI,QAAQ,cAAc;KACxB,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,QACL,SACA,2EACA,KACF;KAEF,OAAO,eAAe,QAAQ,cAAc,OAAO,MAAM;IAC3D;IACA,OAAO,OAAO,WAAW;GAC3B;GAEA,IAAI,OAAO,WAAW,WAEpB,OAAO,QACL,WACA,OAAO,SAAS,gCAChB,KACF;GAEF,IAAI,OAAO,WAAW,eAQpB,OAAO,QACL,eACA,OAAO,SACL,wEACF,MACA;IAAE,QAAQ,OAAO;IAAQ,mBAAmB,OAAO;GAAkB,CACvE;GAEF,OAAO,QAAQ,SAAS,OAAO,SAAS,yBAAyB,KAAK;EACxE;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"agent-tools.js","names":["agentContext","createTool"],"sources":["../src/agent-tools.ts"],"sourcesContent":["import {\n asSchema,\n tool,\n type FlexibleSchema,\n type InferSchema,\n type Tool\n} from \"ai\";\nimport { __DO_NOT_USE_WILL_BREAK__agentContext as agentContext } from \"./internal_context\";\nimport type {\n ChatCapableAgentClass,\n RunAgentToolOptions,\n RunAgentToolResult,\n AgentToolDisplayMetadata,\n AgentToolFailure\n} from \"./agent-tool-types\";\n\ntype ParseSchema<Output = unknown> = {\n parse(value: unknown): Output;\n};\n\ntype AgentToolOutputSchema<Output> =\n | FlexibleSchema<Output>\n | ParseSchema<Output>;\n\ntype AgentToolFactoryOptions<Output = unknown, Input = unknown> = {\n description: string;\n inputSchema: FlexibleSchema<Input>;\n outputSchema?: AgentToolOutputSchema<Output>;\n displayName?: string;\n icon?: string;\n display?: AgentToolDisplayMetadata;\n};\n\n// Capture the concrete schema type so the overload below can derive its input\n// with InferSchema. AgentToolFactoryOptions remains available for callers that\n// explicitly supply agentTool<Input, Output>() type arguments.\ntype InferredAgentToolFactoryOptions<\n InputSchema extends FlexibleSchema,\n Output\n> = Omit<AgentToolFactoryOptions<Output>, \"inputSchema\"> & {\n inputSchema: InputSchema;\n};\n\ntype ToolExecutionOptions = {\n toolCallId?: string;\n abortSignal?: AbortSignal;\n};\n\ntype AgentToolRunner = {\n runAgentTool<Input, Output>(\n cls: ChatCapableAgentClass,\n options: RunAgentToolOptions<Input>\n ): Promise<RunAgentToolResult<Output>>;\n};\n\n/**\n * Preserve the existing Zod-style `.parse()` output-schema contract while\n * extending validation to the other formats supported by AI SDK FlexibleSchema.\n */\nasync function validateOutput<Output>(\n schema: AgentToolOutputSchema<Output>,\n value: unknown\n): Promise<Output> {\n if (\n typeof schema === \"object\" &&\n schema !== null &&\n \"parse\" in schema &&\n typeof schema.parse === \"function\"\n ) {\n return schema.parse(value);\n }\n\n const validate = asSchema(schema as FlexibleSchema<Output>).validate;\n if (!validate) {\n throw new Error(\"agentTool outputSchema must provide runtime validation\");\n }\n\n const result = await validate(value);\n if (!result.success) throw result.error;\n return result.value;\n}\n\nfunction currentAgentToolRunner(): AgentToolRunner {\n const agent = agentContext.getStore()?.agent;\n if (\n agent === null ||\n typeof agent !== \"object\" ||\n typeof (agent as { runAgentTool?: unknown }).runAgentTool !== \"function\"\n ) {\n throw new Error(\n \"agentTool() can only run inside an Agent turn. Use it from getTools() on an Agent subclass.\"\n );\n }\n return agent as AgentToolRunner;\n}\n\nfunction failure(\n status: AgentToolFailure[\"status\"],\n error: string,\n retryable: boolean,\n extra?: Pick<AgentToolFailure, \"reason\" | \"childStillRunning\">\n): AgentToolFailure {\n return {\n ok: false,\n status,\n error,\n retryable,\n ...(extra?.reason !== undefined ? { reason: extra.reason } : {}),\n ...(extra?.childStillRunning !== undefined\n ? { childStillRunning: extra.childStillRunning }\n : {})\n };\n}\n\n/**\n * Create an AI SDK tool that dispatches a chat-capable sub-agent through\n * `Agent.runAgentTool`.\n */\nexport function agentTool<InputSchema extends FlexibleSchema, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: InferredAgentToolFactoryOptions<InputSchema, Output>\n): Tool<InferSchema<InputSchema>, string | Output | AgentToolFailure>;\n// Preserve existing callers that explicitly provide agentTool<Input, Output>().\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output, Input>\n): Tool<Input, string | Output | AgentToolFailure>;\nexport function agentTool<Input = unknown, Output = unknown>(\n cls: ChatCapableAgentClass,\n options: AgentToolFactoryOptions<Output, Input>\n): Tool<Input, string | Output | AgentToolFailure> {\n const createTool = tool as unknown as <I, O>(config: {\n description: string;\n inputSchema: unknown;\n execute: (input: I, options?: ToolExecutionOptions) => Promise<O>;\n }) => Tool<I, O>;\n\n return createTool<Input, string | Output | AgentToolFailure>({\n description: options.description,\n inputSchema: options.inputSchema,\n execute: async (input: Input, executeOptions?: ToolExecutionOptions) => {\n const display: AgentToolDisplayMetadata | undefined =\n options.displayName || options.icon || options.display\n ? {\n ...options.display,\n ...(options.displayName ? { name: options.displayName } : {}),\n ...(options.icon ? { icon: options.icon } : {})\n }\n : undefined;\n\n // Derive a STABLE runId from the tool call id (#1630). A tool call's id is\n // preserved in the transcript, so when a parent turn is re-run by chat\n // recovery after a deploy / eviction, the same `agentTool()` call resolves\n // to the same runId — turning the re-issue into a duplicate that\n // `runAgentTool` re-attaches to the still-running child, instead of a\n // fresh `nanoid` that spawns a brand-new child and re-runs already-\n // completed work (\"the agent went all the way back\"). Falls back to a\n // fresh id only when there is no tool call id (rare; preserves prior\n // behavior).\n const runId = executeOptions?.toolCallId\n ? `agent-tool:${executeOptions.toolCallId}`\n : undefined;\n\n const result = await currentAgentToolRunner().runAgentTool<Input, Output>(\n cls,\n {\n input,\n runId,\n parentToolCallId: executeOptions?.toolCallId,\n signal: executeOptions?.abortSignal,\n display\n }\n );\n\n if (result.status === \"completed\") {\n if (options.outputSchema) {\n if (result.output === undefined) {\n return failure(\n \"error\",\n \"agent tool completed without structured output required by outputSchema\",\n false\n );\n }\n return validateOutput(options.outputSchema, result.output);\n }\n return result.summary ?? \"\";\n }\n\n if (result.status === \"aborted\") {\n // Intentional cancellation (parent/user stopped the run) — not retryable.\n return failure(\n \"aborted\",\n result.error ?? \"agent tool run was cancelled\",\n false\n );\n }\n if (result.status === \"interrupted\") {\n // The child was reset/superseded by a deploy or parent recovery before\n // it reached a logical outcome. Re-dispatching the run can succeed, so\n // surface it as retryable rather than a terminal failure the parent\n // would report to the user as final. `retryable` is intentionally COARSE\n // (always true for `interrupted`); callers that want to distinguish a\n // self-healing child from an exhausted one branch on `reason` /\n // `childStillRunning` instead.\n return failure(\n \"interrupted\",\n result.error ??\n \"agent tool run was interrupted before it finished; it can be retried\",\n true,\n { reason: result.reason, childStillRunning: result.childStillRunning }\n );\n }\n return failure(\"error\", result.error ?? \"agent tool run failed\", false);\n }\n });\n}\n\nexport type { AgentToolFactoryOptions };\nexport type {\n AgentToolChildAdapter,\n AgentToolDisplayMetadata,\n AgentToolEvent,\n AgentToolEventMessage,\n AgentToolEventState,\n AgentToolFailure,\n AgentToolInterruptedReason,\n AgentToolLifecycleResult,\n AgentToolRunInfo,\n AgentToolRunInspection,\n AgentToolRunPart,\n AgentToolRunState,\n AgentToolRunStatus,\n AgentToolStoredChunk,\n AgentToolTerminalStatus,\n ChatCapableAgentClass,\n DetachedAgentToolConfig,\n DetachedRunAgentToolResult,\n RunAgentToolOptions,\n RunAgentToolResult\n} from \"./agent-tool-types\";\n"],"mappings":";;;;;;;;AA2DA,eAAe,eACb,QACA,OACiB;CACjB,IACE,OAAO,WAAW,YAClB,WAAW,QACX,WAAW,UACX,OAAO,OAAO,UAAU,YAExB,OAAO,OAAO,MAAM,KAAK;CAG3B,MAAM,WAAW,SAAS,MAAgC,CAAC,CAAC;CAC5D,IAAI,CAAC,UACH,MAAM,IAAI,MAAM,wDAAwD;CAG1E,MAAM,SAAS,MAAM,SAAS,KAAK;CACnC,IAAI,CAAC,OAAO,SAAS,MAAM,OAAO;CAClC,OAAO,OAAO;AAChB;AAEA,SAAS,yBAA0C;CACjD,MAAM,QAAQA,sCAAa,SAAS,CAAC,EAAE;CACvC,IACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAqC,iBAAiB,YAE9D,MAAM,IAAI,MACR,6FACF;CAEF,OAAO;AACT;AAEA,SAAS,QACP,QACA,OACA,WACA,OACkB;CAClB,OAAO;EACL,IAAI;EACJ;EACA;EACA;EACA,GAAI,OAAO,WAAW,KAAA,IAAY,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;EAC9D,GAAI,OAAO,sBAAsB,KAAA,IAC7B,EAAE,mBAAmB,MAAM,kBAAkB,IAC7C,CAAC;CACP;AACF;AAeA,SAAgB,UACd,KACA,SACiD;CAOjD,OAAOC,KAAsD;EAC3D,aAAa,QAAQ;EACrB,aAAa,QAAQ;EACrB,SAAS,OAAO,OAAc,mBAA0C;GACtE,MAAM,UACJ,QAAQ,eAAe,QAAQ,QAAQ,QAAQ,UAC3C;IACE,GAAG,QAAQ;IACX,GAAI,QAAQ,cAAc,EAAE,MAAM,QAAQ,YAAY,IAAI,CAAC;IAC3D,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;GAC/C,IACA,KAAA;GAWN,MAAM,QAAQ,gBAAgB,aAC1B,cAAc,eAAe,eAC7B,KAAA;GAEJ,MAAM,SAAS,MAAM,uBAAuB,CAAC,CAAC,aAC5C,KACA;IACE;IACA;IACA,kBAAkB,gBAAgB;IAClC,QAAQ,gBAAgB;IACxB;GACF,CACF;GAEA,IAAI,OAAO,WAAW,aAAa;IACjC,IAAI,QAAQ,cAAc;KACxB,IAAI,OAAO,WAAW,KAAA,GACpB,OAAO,QACL,SACA,2EACA,KACF;KAEF,OAAO,eAAe,QAAQ,cAAc,OAAO,MAAM;IAC3D;IACA,OAAO,OAAO,WAAW;GAC3B;GAEA,IAAI,OAAO,WAAW,WAEpB,OAAO,QACL,WACA,OAAO,SAAS,gCAChB,KACF;GAEF,IAAI,OAAO,WAAW,eAQpB,OAAO,QACL,eACA,OAAO,SACL,wEACF,MACA;IAAE,QAAQ,OAAO;IAAQ,mBAAmB,OAAO;GAAkB,CACvE;GAEF,OAAO,QAAQ,SAAS,OAAO,SAAS,yBAAyB,KAAK;EACxE;CACF,CAAC;AACH"}
@@ -1,4 +1,5 @@
1
- import { __DO_NOT_USE_WILL_BREAK__agentContext } from "../internal_context.js";
1
+ import { t as __DO_NOT_USE_WILL_BREAK__agentContext } from "../current-agent-DhoDkSnH.js";
2
+ import "../internal_context.js";
2
3
  import { c as browserLinks, d as browserScrape, i as DurableBrowserSessionStore, l as browserMarkdown, o as browserContent, s as browserExtract, t as BrowserConnector } from "../connector-CptFKzRh.js";
3
4
  import { tool } from "ai";
4
5
  import { z } from "zod";
@@ -1 +1 @@
1
- {"version":3,"file":"ai.js","names":["agentContext"],"sources":["../../src/browser/ai.ts"],"sourcesContent":["import { tool, type JSONValue, type ToolSet } from \"ai\";\nimport { z } from \"zod\";\nimport {\n createCodemodeRuntime,\n DynamicWorkerExecutor,\n truncateResult,\n type CodemodeRuntimeHandle\n} from \"@cloudflare/codemode\";\nimport { __DO_NOT_USE_WILL_BREAK__agentContext as agentContext } from \"../internal_context\";\nimport type { BrowserBinding } from \"./browser-run\";\nimport {\n browserContent,\n browserExtract,\n browserLinks,\n browserMarkdown,\n browserScrape,\n type QuickActionBinding,\n type QuickActionCommonOptions,\n type QuickActionPage\n} from \"./quick-actions\";\nimport {\n BrowserConnector,\n type BrowserConnectorOptions,\n type BrowserConnectorSessionOptions\n} from \"./connector\";\nimport {\n DurableBrowserSessionStore,\n type BrowserSessionStore\n} from \"./session-manager\";\n\nexport interface CreateBrowserToolsOptions {\n /**\n * Durable Object state. The codemode runtime that backs the browser tool\n * lives in a facet of this DO, and browser session ids are stored in its\n * storage — so the tool must be created from inside a Durable Object\n * (e.g. an Agent).\n *\n * Optional: when omitted, it is resolved from the current Agent via\n * `getCurrentAgent()`, so inside an Agent method you can just pass `browser`\n * and `loader`. Pass it explicitly outside an Agent context.\n *\n * The worker must export the `CodemodeRuntime` class (the\n * `@cloudflare/codemode/vite` plugin does this automatically, or add\n * `export { CodemodeRuntime } from \"@cloudflare/codemode\"` to your entry).\n */\n ctx?: DurableObjectState;\n\n /**\n * WorkerLoader binding for sandboxed code execution.\n *\n * Requires `\"worker_loaders\": [{ \"binding\": \"LOADER\" }]` in wrangler.jsonc.\n */\n loader: WorkerLoader;\n\n /**\n * Browser Rendering binding (Fetcher).\n *\n * This is the primary way to connect — works both locally in\n * `wrangler dev` and when deployed to Cloudflare Workers.\n *\n * Requires `\"browser\": { \"binding\": \"BROWSER\" }` in wrangler.jsonc.\n */\n browser?: BrowserBinding;\n\n /**\n * Optional CDP base URL override (e.g. `http://localhost:9222`).\n *\n * Use when connecting to a manually managed Chrome instance or\n * a remote CDP endpoint behind a tunnel.\n */\n cdpUrl?: string;\n\n /**\n * Headers to send with CDP URL discovery requests.\n * Useful when the CDP endpoint requires authentication\n * (e.g. Cloudflare Access headers).\n */\n cdpHeaders?: Record<string, string>;\n\n /**\n * Browser session lifecycle (binding-backed only). Defaults to one fresh\n * session per codemode execution (`one-shot`).\n */\n session?: BrowserConnectorSessionOptions;\n\n /**\n * Durable store for Browser Run session ids. Defaults to a\n * {@link DurableBrowserSessionStore} over `ctx.storage`.\n */\n store?: BrowserSessionStore;\n\n /**\n * Sandbox execution timeout in milliseconds. Defaults to 30000 (30s).\n * Also used as the per-CDP-command timeout.\n */\n timeout?: number;\n\n /**\n * Codemode runtime name — the durable identity of the tool's executions\n * and snippets. Defaults to `\"browser\"`.\n */\n name?: string;\n\n /**\n * Also expose stateless {@link createQuickActionTools | Quick Action} tools\n * (`browser_markdown`, `browser_extract`, …) alongside the durable\n * `browser_execute` tool.\n *\n * Enabled by default whenever a Browser Run `browser` binding is available\n * (they share it), except when `session.browser` selects Kitesurf because\n * the binding RPC cannot select that engine. Pass `true` or an object to\n * explicitly add Chromium Quick Actions alongside Kitesurf, or `false` to\n * disable them. The Quick Action binding defaults to `browser`; override it via\n * `quickActions.browser`. When only `cdpUrl` is set (no binding), the\n * defaults are skipped silently — pass `quickActions: { browser }` to force\n * them.\n */\n quickActions?:\n | boolean\n | {\n browser?: QuickActionBinding;\n actions?: QuickActionToolName[];\n maxChars?: number;\n options?: QuickActionCommonOptions;\n };\n}\n\n/**\n * The browser tool's moving parts, for hosts that need more than the tools:\n *\n * - `runtime` — the codemode runtime handle (approve/reject paused runs,\n * `expirePaused`, audit via `executions()`, snippets).\n * - `connector` — host-side session helpers: `sessionInfo()`,\n * `closeSession()`, and `sweep()` for a recurring cleanup task.\n * - `tools` — what `createBrowserTools` returns.\n */\nexport interface BrowserRuntime {\n runtime: CodemodeRuntimeHandle;\n connector: BrowserConnector;\n tools: ToolSet;\n}\n\nlet didWarnExperimental = false;\nlet didDebugQuickActionSkip = false;\n\ninterface BrowserScreenshotOutput {\n type: \"browser_screenshot\";\n mediaType: string;\n data: string;\n}\n\nfunction browserScreenshotOutput(\n value: unknown\n): BrowserScreenshotOutput | null {\n const outer =\n typeof value === \"object\" && value !== null\n ? (value as Record<string, unknown>)\n : null;\n const result =\n outer && typeof outer.result === \"object\" && outer.result !== null\n ? (outer.result as Record<string, unknown>)\n : outer;\n if (\n result?.type !== \"browser_screenshot\" ||\n typeof result.mediaType !== \"string\" ||\n typeof result.data !== \"string\"\n ) {\n return null;\n }\n return result as unknown as BrowserScreenshotOutput;\n}\n\nconst BASE64_REDACTION_THRESHOLD = 4096;\nconst MAX_REDACTION_DEPTH = 20;\nconst MAX_REDACTION_NODES = 10_000;\n\nfunction base64Details(\n value: string,\n minimumLength = BASE64_REDACTION_THRESHOLD\n): {\n mediaType?: string;\n chars: number;\n bytes: number;\n} | null {\n if (value.length < minimumLength) return null;\n\n const dataUrl =\n /^data:([^;,]+)(?:;[^;,]*)*;base64,([A-Za-z0-9+/]*={0,2})$/i.exec(value);\n const encoded = dataUrl?.[2] ?? value;\n if (encoded.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) {\n return null;\n }\n\n const padding = encoded.endsWith(\"==\") ? 2 : encoded.endsWith(\"=\") ? 1 : 0;\n return {\n mediaType: dataUrl?.[1],\n chars: encoded.length,\n bytes: (encoded.length / 4) * 3 - padding\n };\n}\n\nfunction base64Redaction(\n value: string,\n mediaType?: string,\n minimumLength?: number\n): string {\n const details = base64Details(value, minimumLength);\n if (!details) return value;\n const type = mediaType ?? details.mediaType;\n return `[base64${type ? ` ${type}` : \"\"} data omitted: ${details.chars.toLocaleString()} chars, approximately ${details.bytes.toLocaleString()} bytes]`;\n}\n\nfunction redactBase64Payloads(value: unknown): unknown {\n const ancestors = new WeakSet<object>();\n let nodes = 0;\n\n function visit(current: unknown, depth: number): unknown {\n if (depth > MAX_REDACTION_DEPTH) return \"[nested value omitted]\";\n if (++nodes > MAX_REDACTION_NODES) return \"[remaining values omitted]\";\n if (typeof current === \"string\") return base64Redaction(current);\n if (typeof current !== \"object\" || current === null) return current;\n // Binary values cross the sandbox boundary as Uint8Array/ArrayBuffer —\n // walking them would rebuild them as index-keyed plain objects. The same\n // is true of Date/Map/Set, whose own enumerable entries are empty.\n if (\n current instanceof ArrayBuffer ||\n ArrayBuffer.isView(current) ||\n current instanceof Date ||\n current instanceof Map ||\n current instanceof Set\n ) {\n return current;\n }\n if (ancestors.has(current)) return \"[circular reference omitted]\";\n\n ancestors.add(current);\n try {\n if (Array.isArray(current)) {\n return current.map((entry) => visit(entry, depth + 1));\n }\n\n const record = current as Record<string, unknown>;\n const screenshot =\n record.type === \"browser_screenshot\" &&\n typeof record.mediaType === \"string\";\n return Object.fromEntries(\n Object.entries(record).map(([key, entry]) => [\n key,\n screenshot && key === \"data\" && typeof entry === \"string\"\n ? base64Redaction(entry, record.mediaType as string, 0)\n : visit(entry, depth + 1)\n ])\n );\n } finally {\n ancestors.delete(current);\n }\n }\n\n return visit(value, 0);\n}\n\nfunction transformBrowserResult(value: unknown): unknown {\n // Keep canonical screenshot output intact for UIMessage persistence and the\n // chat renderer. Other results are redacted before truncation so a nested\n // binary payload cannot become a large serialized preview.\n return browserScreenshotOutput(value)\n ? value\n : truncateResult(redactBase64Payloads(value));\n}\n\nfunction browserExecuteModelOutput(\n output: unknown\n): { type: \"text\"; value: string } | { type: \"json\"; value: JSONValue } {\n const screenshot = browserScreenshotOutput(output);\n if (screenshot) {\n const approximateBytes = Math.floor((screenshot.data.length * 3) / 4);\n return {\n type: \"text\",\n value: `Screenshot captured successfully (${screenshot.mediaType}, approximately ${approximateBytes.toLocaleString()} bytes); the image is kept for the UI and omitted here.`\n };\n }\n\n const redacted = redactBase64Payloads(output);\n try {\n const serialized = JSON.stringify(redacted);\n return {\n type: \"json\",\n value:\n serialized === undefined ? null : (JSON.parse(serialized) as JSONValue)\n };\n } catch {\n return {\n type: \"text\",\n value:\n \"Browser execution completed, but its result could not be serialized for model context.\"\n };\n }\n}\n\n/**\n * The Durable Object state to build the runtime in: the explicit `ctx` if\n * given, otherwise the current Agent's `ctx` (via `getCurrentAgent()`), so\n * `createBrowserRuntime` can be called from an Agent method without threading\n * `this.ctx` through.\n */\nfunction resolveCtx(\n options: CreateBrowserToolsOptions\n): DurableObjectState | undefined {\n if (options.ctx) return options.ctx;\n const agent = agentContext.getStore()?.agent as\n | { ctx?: DurableObjectState }\n | undefined;\n return agent?.ctx;\n}\n\nfunction connectorOptions(\n options: CreateBrowserToolsOptions,\n ctx: DurableObjectState\n): BrowserConnectorOptions {\n if (options.cdpUrl) {\n return {\n cdpUrl: options.cdpUrl,\n cdpHeaders: options.cdpHeaders,\n timeout: options.timeout\n };\n }\n if (!options.browser) {\n throw new Error(\n \"Either 'browser' (Fetcher binding) or 'cdpUrl' must be provided\"\n );\n }\n return {\n browser: options.browser,\n store: options.store ?? new DurableBrowserSessionStore(ctx.storage),\n session: options.session,\n timeout: options.timeout\n };\n}\n\n/**\n * Create the browser codemode runtime: the `browser_execute` tool plus the\n * runtime handle and connector for host-side wiring (approvals, session info,\n * sweeps).\n *\n * @example\n * ```ts\n * export class MyAgent extends Agent<Env> {\n * get browser() {\n * return createBrowserRuntime({\n * ctx: this.ctx,\n * browser: this.env.BROWSER,\n * loader: this.env.LOADER,\n * session: { mode: \"dynamic\" }\n * });\n * }\n *\n * @callable()\n * async closeBrowserSession() {\n * await this.browser.connector.closeSession();\n * }\n * }\n * ```\n */\nexport function createBrowserRuntime(\n options: CreateBrowserToolsOptions\n): BrowserRuntime {\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\n const ctx = resolveCtx(options);\n if (!ctx) {\n throw new Error(\n \"createBrowserRuntime requires a Durable Object 'ctx' — pass it explicitly, or call from within an Agent so it can be resolved via getCurrentAgent()\"\n );\n }\n\n const connector = new BrowserConnector(ctx, connectorOptions(options, ctx));\n const runtime = createCodemodeRuntime({\n ctx,\n executor: new DynamicWorkerExecutor({\n loader: options.loader,\n timeout: options.timeout\n }),\n connectors: [connector],\n name: options.name ?? \"browser\",\n transformResult: transformBrowserResult\n });\n\n // `connectorOptions` drops `session` when a custom endpoint is used, so the\n // connector is plain Chromium there whatever the session options say.\n const isKitesurf = !options.cdpUrl && options.session?.browser === \"kitesurf\";\n const browserExecute = runtime.tool({\n connectorHints: {\n cdp: isKitesurf\n ? 'Kitesurf one-shot Browser CDP. Call codemode.describe(\"cdp\") for connector types and Kitesurf execution rules. codemode.search indexes connector methods and snippets, not underlying CDP commands. Complete the task in one execution and do not pause. Return screenshots as { type: \"browser_screenshot\", mediaType: \"image/png\", data: screenshot.data }.'\n : \"Browser CDP. Return screenshots as { type: 'browser_screenshot', mediaType: 'image/png', data: screenshot.data }; the UI keeps the image while the model receives a compact summary.\"\n }\n });\n const tools: ToolSet = {\n browser_execute: {\n ...browserExecute,\n toModelOutput: ({ output }: { output: unknown }) =>\n browserExecuteModelOutput(output)\n }\n };\n\n // Quick Actions ride the same `browser` binding, so they are on by default\n // for Chromium. The binding RPC cannot select Kitesurf, so selecting\n // Kitesurf disables the defaults rather than silently adding Chromium tools.\n // Callers can still request a mixed-engine toolset explicitly.\n const enableQuickActions =\n options.quickActions !== false &&\n (!isKitesurf || options.quickActions !== undefined);\n // `env.BROWSER` satisfies both the CDP `BrowserBinding` (fetch) and the\n // `QuickActionBinding` (quickAction) surfaces; our narrower option type only\n // sees the former, so reuse it here unless an explicit binding wins.\n if (enableQuickActions) {\n const qa =\n typeof options.quickActions === \"object\" ? options.quickActions : {};\n const quickActionBrowser =\n qa.browser ??\n (options.browser as unknown as QuickActionBinding | undefined);\n if (quickActionBrowser) {\n Object.assign(\n tools,\n createQuickActionTools({\n browser: quickActionBrowser,\n actions: qa.actions,\n maxChars: qa.maxChars,\n options: qa.options\n })\n );\n } else if (options.quickActions) {\n // Explicitly requested but no binding to back them.\n throw new Error(\n \"quickActions requires a Browser Run binding — set 'browser' (env.BROWSER) or 'quickActions.browser'\"\n );\n } else if (!didDebugQuickActionSkip) {\n // Defaulted on, but only `cdpUrl` is set: there is no binding to call\n // Quick Actions through, so they are skipped. Surface it once so a user\n // expecting `browser_markdown` et al. isn't left wondering.\n didDebugQuickActionSkip = true;\n console.debug(\n \"[agents/browser] Quick Action tools skipped — no Browser Run binding (only 'cdpUrl' is set). Pass 'browser' or 'quickActions.browser' to enable them.\"\n );\n }\n }\n\n return { runtime, connector, tools };\n}\n\n/**\n * Create AI SDK tools for browser automation via CDP code mode.\n *\n * Returns a `ToolSet` with a single durable `browser_execute` tool backed by\n * a codemode runtime: the model writes TypeScript against the `cdp` connector\n * (`cdp.send`, `cdp.attachToTarget`, `cdp.spec`, …), executions are recorded\n * for abort-and-replay, and browser sessions survive pauses.\n *\n * @example\n * ```ts\n * import { createBrowserTools } from \"agents/browser/ai\";\n * import { generateText } from \"ai\";\n *\n * // inside a Durable Object / Agent:\n * const browserTools = createBrowserTools({\n * ctx: this.ctx,\n * browser: this.env.BROWSER,\n * loader: this.env.LOADER,\n * });\n *\n * const result = await generateText({\n * model,\n * tools: { ...browserTools, ...otherTools },\n * messages,\n * });\n * ```\n */\nexport function createBrowserTools(\n options: CreateBrowserToolsOptions\n): ToolSet {\n return createBrowserRuntime(options).tools;\n}\n\n/** A Quick Action exposed as an AI SDK tool. */\nexport type QuickActionToolName =\n | \"markdown\"\n | \"extract\"\n | \"links\"\n | \"scrape\"\n | \"content\";\n\nexport interface CreateQuickActionToolsOptions {\n /**\n * Browser Run binding with Quick Actions support (`env.BROWSER`). Requires a\n * Worker `compatibility_date` of `2026-03-24`+ and `remote: true` for local\n * `wrangler dev`.\n */\n browser: QuickActionBinding;\n\n /**\n * Which tools to expose. Defaults to the text-returning, model-friendly set\n * (`markdown`, `extract`, `links`, `scrape`). `content` (raw HTML) is opt-in\n * since it is large and rarely what a model wants.\n */\n actions?: QuickActionToolName[];\n\n /**\n * Bound every result to roughly this many characters before returning it to\n * the model, to protect the context window, preserving each result's shape:\n * text (markdown/content) is truncated to a string, oversized arrays\n * (links/scrape) are trimmed but stay arrays, and only an opaque oversized\n * object degrades to a truncated-preview summary. Set to `0` to disable.\n * Defaults to 50000.\n */\n maxChars?: number;\n\n /**\n * Common Browser Run options merged into every request — e.g. `cookies`,\n * `authenticate`, or `setExtraHTTPHeaders` for authenticated pages, and\n * `gotoOptions` / `viewport` for JavaScript-heavy pages. The model only ever\n * supplies the page (`url`/`html`) and action-specific fields; these\n * host-supplied options are never exposed to it.\n */\n options?: QuickActionCommonOptions;\n}\n\nconst DEFAULT_QUICK_ACTION_TOOLS: QuickActionToolName[] = [\n \"markdown\",\n \"extract\",\n \"links\",\n \"scrape\"\n];\n\nconst DEFAULT_QUICK_ACTION_MAX_CHARS = 50_000;\n\nconst pageInputSchema = z\n .object({\n url: z.string().url().optional().describe(\"URL of the page to load\"),\n html: z\n .string()\n .optional()\n .describe(\"Raw HTML to render instead of loading a URL\")\n })\n .refine((value) => Boolean(value.url) || Boolean(value.html), {\n message: \"Provide either 'url' or 'html'\"\n });\n\nfunction toPage(\n input: { url?: string; html?: string },\n options?: QuickActionCommonOptions\n): QuickActionPage {\n const page = input.url ? { url: input.url } : { html: input.html as string };\n return { ...options, ...page } as QuickActionPage;\n}\n\nfunction truncate(text: string, maxChars: number): string {\n if (maxChars <= 0 || text.length <= maxChars) return text;\n return `${text.slice(0, maxChars)}\\n\\n[truncated ${text.length - maxChars} characters]`;\n}\n\n/**\n * Keep a tool result within a rough character budget so a single browse cannot\n * blow the model's context window — while preserving the result's shape so the\n * model sees a consistent type across calls:\n *\n * - strings (markdown/content) are truncated to a string;\n * - arrays (links/scrape) are trimmed from the end but stay arrays;\n * - only an opaque oversized object (e.g. a sprawling `extract`) degrades to a\n * `{ truncated, note, preview }` summary, since it cannot be trimmed safely.\n */\nfunction boundResult(value: unknown, maxChars: number): unknown {\n if (maxChars <= 0) return value;\n if (typeof value === \"string\") return truncate(value, maxChars);\n let json: string;\n try {\n json = JSON.stringify(value);\n } catch {\n return value;\n }\n if (json.length <= maxChars) return value;\n if (Array.isArray(value)) {\n const trimmed = boundArray(value, maxChars);\n // If even the first element overflows the budget, `trimmed` is empty —\n // returning `[]` would read as \"no results\" rather than \"too large\", so\n // fall through to the explicit truncated-preview summary instead.\n if (trimmed.length > 0) return trimmed;\n }\n return {\n truncated: true,\n note: `Result is too large (${json.length} characters); narrow the request.`,\n preview: `${json.slice(0, maxChars)}…`\n };\n}\n\n/**\n * Take as many leading items as fit within `maxChars` (measured against their\n * JSON length), returning a trimmed array of the same element type. Silent by\n * design: the model gets fewer, valid items rather than a reshaped result.\n */\nfunction boundArray(value: unknown[], maxChars: number): unknown[] {\n const out: unknown[] = [];\n let size = 2; // the enclosing \"[]\"\n for (const item of value) {\n const itemSize = JSON.stringify(item).length + 1; // + a separating comma\n if (size + itemSize > maxChars) break;\n out.push(item);\n size += itemSize;\n }\n return out;\n}\n\n/**\n * Create AI SDK tools for Browser Run [Quick Actions](https://developers.cloudflare.com/browser-run/quick-actions/):\n * stateless one-shot browsing (read a page as Markdown, extract structured\n * data with AI, list links, scrape elements). Unlike `createBrowserTools`,\n * these need only the `browser` binding — no Durable Object, loader, or\n * sandbox — so they work from any Worker.\n *\n * @example\n * ```ts\n * import { createQuickActionTools } from \"agents/browser/ai\";\n *\n * const tools = createQuickActionTools({ browser: this.env.BROWSER });\n * const result = await generateText({ model, tools, messages });\n * ```\n */\nexport function createQuickActionTools(\n options: CreateQuickActionToolsOptions\n): ToolSet {\n const { browser } = options;\n const requestOptions = options.options;\n const enabled = new Set(options.actions ?? DEFAULT_QUICK_ACTION_TOOLS);\n const maxChars = options.maxChars ?? DEFAULT_QUICK_ACTION_MAX_CHARS;\n const tools: ToolSet = {};\n\n if (enabled.has(\"markdown\")) {\n tools.browser_markdown = tool({\n description:\n \"Load a web page (or render raw HTML) and return its content as Markdown. Best for reading articles, docs, or any page as text.\",\n inputSchema: pageInputSchema,\n execute: async (input) =>\n boundResult(\n await browserMarkdown(browser, toPage(input, requestOptions)),\n maxChars\n )\n });\n }\n\n if (enabled.has(\"extract\")) {\n tools.browser_extract = tool({\n description:\n \"Extract structured data from a web page using AI. Describe what you want in 'prompt'. Passing a JSON Schema in 'schema' is strongly recommended — without one the extractor often fails to produce JSON.\",\n inputSchema: z\n .object({\n url: z.string().url().optional().describe(\"URL of the page to load\"),\n html: z\n .string()\n .optional()\n .describe(\"Raw HTML to render instead of loading a URL\"),\n prompt: z\n .string()\n .optional()\n .describe(\"What to extract, in natural language\"),\n schema: z\n .record(z.string(), z.unknown(), {\n error: \"Schema must be a JSON object\"\n })\n .optional()\n .describe(\"Optional JSON Schema describing the desired output\")\n })\n .refine((value) => Boolean(value.url) || Boolean(value.html), {\n message: \"Provide either 'url' or 'html'\"\n })\n .refine((value) => Boolean(value.prompt) || Boolean(value.schema), {\n message: \"Provide either 'prompt' or 'schema'\"\n }),\n execute: async (input) =>\n boundResult(\n await browserExtract(browser, {\n ...toPage(input, requestOptions),\n prompt: input.prompt,\n response_format: input.schema\n ? { type: \"json_schema\", json_schema: input.schema }\n : undefined\n }),\n maxChars\n )\n });\n }\n\n if (enabled.has(\"links\")) {\n tools.browser_links = tool({\n description:\n \"Return every link found on a web page (including ones not visible). Useful for discovering pages to follow.\",\n inputSchema: pageInputSchema,\n execute: async (input) =>\n boundResult(\n await browserLinks(browser, toPage(input, requestOptions)),\n maxChars\n )\n });\n }\n\n if (enabled.has(\"scrape\")) {\n tools.browser_scrape = tool({\n description:\n \"Scrape specific elements from a web page by CSS selector. Returns the matched elements' text, HTML, and attributes.\",\n inputSchema: z\n .object({\n url: z.string().url().optional().describe(\"URL of the page to load\"),\n html: z\n .string()\n .optional()\n .describe(\"Raw HTML to render instead of loading a URL\"),\n selectors: z\n .array(z.string())\n .min(1)\n .describe(\"CSS selectors to extract\")\n })\n .refine((value) => Boolean(value.url) || Boolean(value.html), {\n message: \"Provide either 'url' or 'html'\"\n }),\n execute: async (input) =>\n boundResult(\n await browserScrape(browser, {\n ...toPage(input, requestOptions),\n elements: input.selectors.map((selector) => ({ selector }))\n }),\n maxChars\n )\n });\n }\n\n if (enabled.has(\"content\")) {\n tools.browser_content = tool({\n description:\n \"Load a web page and return its fully rendered HTML (after JavaScript runs). Prefer 'browser_markdown' unless you need the raw HTML.\",\n inputSchema: pageInputSchema,\n execute: async (input) =>\n boundResult(\n await browserContent(browser, toPage(input, requestOptions)),\n maxChars\n )\n });\n }\n\n return tools;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ai.js","names":["agentContext"],"sources":["../../src/browser/ai.ts"],"sourcesContent":["import { tool, type JSONValue, type ToolSet } from \"ai\";\nimport { z } from \"zod\";\nimport {\n createCodemodeRuntime,\n DynamicWorkerExecutor,\n truncateResult,\n type CodemodeRuntimeHandle\n} from \"@cloudflare/codemode\";\nimport { __DO_NOT_USE_WILL_BREAK__agentContext as agentContext } from \"../internal_context\";\nimport type { BrowserBinding } from \"./browser-run\";\nimport {\n browserContent,\n browserExtract,\n browserLinks,\n browserMarkdown,\n browserScrape,\n type QuickActionBinding,\n type QuickActionCommonOptions,\n type QuickActionPage\n} from \"./quick-actions\";\nimport {\n BrowserConnector,\n type BrowserConnectorOptions,\n type BrowserConnectorSessionOptions\n} from \"./connector\";\nimport {\n DurableBrowserSessionStore,\n type BrowserSessionStore\n} from \"./session-manager\";\n\nexport interface CreateBrowserToolsOptions {\n /**\n * Durable Object state. The codemode runtime that backs the browser tool\n * lives in a facet of this DO, and browser session ids are stored in its\n * storage — so the tool must be created from inside a Durable Object\n * (e.g. an Agent).\n *\n * Optional: when omitted, it is resolved from the current Agent via\n * `getCurrentAgent()`, so inside an Agent method you can just pass `browser`\n * and `loader`. Pass it explicitly outside an Agent context.\n *\n * The worker must export the `CodemodeRuntime` class (the\n * `@cloudflare/codemode/vite` plugin does this automatically, or add\n * `export { CodemodeRuntime } from \"@cloudflare/codemode\"` to your entry).\n */\n ctx?: DurableObjectState;\n\n /**\n * WorkerLoader binding for sandboxed code execution.\n *\n * Requires `\"worker_loaders\": [{ \"binding\": \"LOADER\" }]` in wrangler.jsonc.\n */\n loader: WorkerLoader;\n\n /**\n * Browser Rendering binding (Fetcher).\n *\n * This is the primary way to connect — works both locally in\n * `wrangler dev` and when deployed to Cloudflare Workers.\n *\n * Requires `\"browser\": { \"binding\": \"BROWSER\" }` in wrangler.jsonc.\n */\n browser?: BrowserBinding;\n\n /**\n * Optional CDP base URL override (e.g. `http://localhost:9222`).\n *\n * Use when connecting to a manually managed Chrome instance or\n * a remote CDP endpoint behind a tunnel.\n */\n cdpUrl?: string;\n\n /**\n * Headers to send with CDP URL discovery requests.\n * Useful when the CDP endpoint requires authentication\n * (e.g. Cloudflare Access headers).\n */\n cdpHeaders?: Record<string, string>;\n\n /**\n * Browser session lifecycle (binding-backed only). Defaults to one fresh\n * session per codemode execution (`one-shot`).\n */\n session?: BrowserConnectorSessionOptions;\n\n /**\n * Durable store for Browser Run session ids. Defaults to a\n * {@link DurableBrowserSessionStore} over `ctx.storage`.\n */\n store?: BrowserSessionStore;\n\n /**\n * Sandbox execution timeout in milliseconds. Defaults to 30000 (30s).\n * Also used as the per-CDP-command timeout.\n */\n timeout?: number;\n\n /**\n * Codemode runtime name — the durable identity of the tool's executions\n * and snippets. Defaults to `\"browser\"`.\n */\n name?: string;\n\n /**\n * Also expose stateless {@link createQuickActionTools | Quick Action} tools\n * (`browser_markdown`, `browser_extract`, …) alongside the durable\n * `browser_execute` tool.\n *\n * Enabled by default whenever a Browser Run `browser` binding is available\n * (they share it), except when `session.browser` selects Kitesurf because\n * the binding RPC cannot select that engine. Pass `true` or an object to\n * explicitly add Chromium Quick Actions alongside Kitesurf, or `false` to\n * disable them. The Quick Action binding defaults to `browser`; override it via\n * `quickActions.browser`. When only `cdpUrl` is set (no binding), the\n * defaults are skipped silently — pass `quickActions: { browser }` to force\n * them.\n */\n quickActions?:\n | boolean\n | {\n browser?: QuickActionBinding;\n actions?: QuickActionToolName[];\n maxChars?: number;\n options?: QuickActionCommonOptions;\n };\n}\n\n/**\n * The browser tool's moving parts, for hosts that need more than the tools:\n *\n * - `runtime` — the codemode runtime handle (approve/reject paused runs,\n * `expirePaused`, audit via `executions()`, snippets).\n * - `connector` — host-side session helpers: `sessionInfo()`,\n * `closeSession()`, and `sweep()` for a recurring cleanup task.\n * - `tools` — what `createBrowserTools` returns.\n */\nexport interface BrowserRuntime {\n runtime: CodemodeRuntimeHandle;\n connector: BrowserConnector;\n tools: ToolSet;\n}\n\nlet didWarnExperimental = false;\nlet didDebugQuickActionSkip = false;\n\ninterface BrowserScreenshotOutput {\n type: \"browser_screenshot\";\n mediaType: string;\n data: string;\n}\n\nfunction browserScreenshotOutput(\n value: unknown\n): BrowserScreenshotOutput | null {\n const outer =\n typeof value === \"object\" && value !== null\n ? (value as Record<string, unknown>)\n : null;\n const result =\n outer && typeof outer.result === \"object\" && outer.result !== null\n ? (outer.result as Record<string, unknown>)\n : outer;\n if (\n result?.type !== \"browser_screenshot\" ||\n typeof result.mediaType !== \"string\" ||\n typeof result.data !== \"string\"\n ) {\n return null;\n }\n return result as unknown as BrowserScreenshotOutput;\n}\n\nconst BASE64_REDACTION_THRESHOLD = 4096;\nconst MAX_REDACTION_DEPTH = 20;\nconst MAX_REDACTION_NODES = 10_000;\n\nfunction base64Details(\n value: string,\n minimumLength = BASE64_REDACTION_THRESHOLD\n): {\n mediaType?: string;\n chars: number;\n bytes: number;\n} | null {\n if (value.length < minimumLength) return null;\n\n const dataUrl =\n /^data:([^;,]+)(?:;[^;,]*)*;base64,([A-Za-z0-9+/]*={0,2})$/i.exec(value);\n const encoded = dataUrl?.[2] ?? value;\n if (encoded.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(encoded)) {\n return null;\n }\n\n const padding = encoded.endsWith(\"==\") ? 2 : encoded.endsWith(\"=\") ? 1 : 0;\n return {\n mediaType: dataUrl?.[1],\n chars: encoded.length,\n bytes: (encoded.length / 4) * 3 - padding\n };\n}\n\nfunction base64Redaction(\n value: string,\n mediaType?: string,\n minimumLength?: number\n): string {\n const details = base64Details(value, minimumLength);\n if (!details) return value;\n const type = mediaType ?? details.mediaType;\n return `[base64${type ? ` ${type}` : \"\"} data omitted: ${details.chars.toLocaleString()} chars, approximately ${details.bytes.toLocaleString()} bytes]`;\n}\n\nfunction redactBase64Payloads(value: unknown): unknown {\n const ancestors = new WeakSet<object>();\n let nodes = 0;\n\n function visit(current: unknown, depth: number): unknown {\n if (depth > MAX_REDACTION_DEPTH) return \"[nested value omitted]\";\n if (++nodes > MAX_REDACTION_NODES) return \"[remaining values omitted]\";\n if (typeof current === \"string\") return base64Redaction(current);\n if (typeof current !== \"object\" || current === null) return current;\n // Binary values cross the sandbox boundary as Uint8Array/ArrayBuffer —\n // walking them would rebuild them as index-keyed plain objects. The same\n // is true of Date/Map/Set, whose own enumerable entries are empty.\n if (\n current instanceof ArrayBuffer ||\n ArrayBuffer.isView(current) ||\n current instanceof Date ||\n current instanceof Map ||\n current instanceof Set\n ) {\n return current;\n }\n if (ancestors.has(current)) return \"[circular reference omitted]\";\n\n ancestors.add(current);\n try {\n if (Array.isArray(current)) {\n return current.map((entry) => visit(entry, depth + 1));\n }\n\n const record = current as Record<string, unknown>;\n const screenshot =\n record.type === \"browser_screenshot\" &&\n typeof record.mediaType === \"string\";\n return Object.fromEntries(\n Object.entries(record).map(([key, entry]) => [\n key,\n screenshot && key === \"data\" && typeof entry === \"string\"\n ? base64Redaction(entry, record.mediaType as string, 0)\n : visit(entry, depth + 1)\n ])\n );\n } finally {\n ancestors.delete(current);\n }\n }\n\n return visit(value, 0);\n}\n\nfunction transformBrowserResult(value: unknown): unknown {\n // Keep canonical screenshot output intact for UIMessage persistence and the\n // chat renderer. Other results are redacted before truncation so a nested\n // binary payload cannot become a large serialized preview.\n return browserScreenshotOutput(value)\n ? value\n : truncateResult(redactBase64Payloads(value));\n}\n\nfunction browserExecuteModelOutput(\n output: unknown\n): { type: \"text\"; value: string } | { type: \"json\"; value: JSONValue } {\n const screenshot = browserScreenshotOutput(output);\n if (screenshot) {\n const approximateBytes = Math.floor((screenshot.data.length * 3) / 4);\n return {\n type: \"text\",\n value: `Screenshot captured successfully (${screenshot.mediaType}, approximately ${approximateBytes.toLocaleString()} bytes); the image is kept for the UI and omitted here.`\n };\n }\n\n const redacted = redactBase64Payloads(output);\n try {\n const serialized = JSON.stringify(redacted);\n return {\n type: \"json\",\n value:\n serialized === undefined ? null : (JSON.parse(serialized) as JSONValue)\n };\n } catch {\n return {\n type: \"text\",\n value:\n \"Browser execution completed, but its result could not be serialized for model context.\"\n };\n }\n}\n\n/**\n * The Durable Object state to build the runtime in: the explicit `ctx` if\n * given, otherwise the current Agent's `ctx` (via `getCurrentAgent()`), so\n * `createBrowserRuntime` can be called from an Agent method without threading\n * `this.ctx` through.\n */\nfunction resolveCtx(\n options: CreateBrowserToolsOptions\n): DurableObjectState | undefined {\n if (options.ctx) return options.ctx;\n const agent = agentContext.getStore()?.agent as\n | { ctx?: DurableObjectState }\n | undefined;\n return agent?.ctx;\n}\n\nfunction connectorOptions(\n options: CreateBrowserToolsOptions,\n ctx: DurableObjectState\n): BrowserConnectorOptions {\n if (options.cdpUrl) {\n return {\n cdpUrl: options.cdpUrl,\n cdpHeaders: options.cdpHeaders,\n timeout: options.timeout\n };\n }\n if (!options.browser) {\n throw new Error(\n \"Either 'browser' (Fetcher binding) or 'cdpUrl' must be provided\"\n );\n }\n return {\n browser: options.browser,\n store: options.store ?? new DurableBrowserSessionStore(ctx.storage),\n session: options.session,\n timeout: options.timeout\n };\n}\n\n/**\n * Create the browser codemode runtime: the `browser_execute` tool plus the\n * runtime handle and connector for host-side wiring (approvals, session info,\n * sweeps).\n *\n * @example\n * ```ts\n * export class MyAgent extends Agent<Env> {\n * get browser() {\n * return createBrowserRuntime({\n * ctx: this.ctx,\n * browser: this.env.BROWSER,\n * loader: this.env.LOADER,\n * session: { mode: \"dynamic\" }\n * });\n * }\n *\n * @callable()\n * async closeBrowserSession() {\n * await this.browser.connector.closeSession();\n * }\n * }\n * ```\n */\nexport function createBrowserRuntime(\n options: CreateBrowserToolsOptions\n): BrowserRuntime {\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\n const ctx = resolveCtx(options);\n if (!ctx) {\n throw new Error(\n \"createBrowserRuntime requires a Durable Object 'ctx' — pass it explicitly, or call from within an Agent so it can be resolved via getCurrentAgent()\"\n );\n }\n\n const connector = new BrowserConnector(ctx, connectorOptions(options, ctx));\n const runtime = createCodemodeRuntime({\n ctx,\n executor: new DynamicWorkerExecutor({\n loader: options.loader,\n timeout: options.timeout\n }),\n connectors: [connector],\n name: options.name ?? \"browser\",\n transformResult: transformBrowserResult\n });\n\n // `connectorOptions` drops `session` when a custom endpoint is used, so the\n // connector is plain Chromium there whatever the session options say.\n const isKitesurf = !options.cdpUrl && options.session?.browser === \"kitesurf\";\n const browserExecute = runtime.tool({\n connectorHints: {\n cdp: isKitesurf\n ? 'Kitesurf one-shot Browser CDP. Call codemode.describe(\"cdp\") for connector types and Kitesurf execution rules. codemode.search indexes connector methods and snippets, not underlying CDP commands. Complete the task in one execution and do not pause. Return screenshots as { type: \"browser_screenshot\", mediaType: \"image/png\", data: screenshot.data }.'\n : \"Browser CDP. Return screenshots as { type: 'browser_screenshot', mediaType: 'image/png', data: screenshot.data }; the UI keeps the image while the model receives a compact summary.\"\n }\n });\n const tools: ToolSet = {\n browser_execute: {\n ...browserExecute,\n toModelOutput: ({ output }: { output: unknown }) =>\n browserExecuteModelOutput(output)\n }\n };\n\n // Quick Actions ride the same `browser` binding, so they are on by default\n // for Chromium. The binding RPC cannot select Kitesurf, so selecting\n // Kitesurf disables the defaults rather than silently adding Chromium tools.\n // Callers can still request a mixed-engine toolset explicitly.\n const enableQuickActions =\n options.quickActions !== false &&\n (!isKitesurf || options.quickActions !== undefined);\n // `env.BROWSER` satisfies both the CDP `BrowserBinding` (fetch) and the\n // `QuickActionBinding` (quickAction) surfaces; our narrower option type only\n // sees the former, so reuse it here unless an explicit binding wins.\n if (enableQuickActions) {\n const qa =\n typeof options.quickActions === \"object\" ? options.quickActions : {};\n const quickActionBrowser =\n qa.browser ??\n (options.browser as unknown as QuickActionBinding | undefined);\n if (quickActionBrowser) {\n Object.assign(\n tools,\n createQuickActionTools({\n browser: quickActionBrowser,\n actions: qa.actions,\n maxChars: qa.maxChars,\n options: qa.options\n })\n );\n } else if (options.quickActions) {\n // Explicitly requested but no binding to back them.\n throw new Error(\n \"quickActions requires a Browser Run binding — set 'browser' (env.BROWSER) or 'quickActions.browser'\"\n );\n } else if (!didDebugQuickActionSkip) {\n // Defaulted on, but only `cdpUrl` is set: there is no binding to call\n // Quick Actions through, so they are skipped. Surface it once so a user\n // expecting `browser_markdown` et al. isn't left wondering.\n didDebugQuickActionSkip = true;\n console.debug(\n \"[agents/browser] Quick Action tools skipped — no Browser Run binding (only 'cdpUrl' is set). Pass 'browser' or 'quickActions.browser' to enable them.\"\n );\n }\n }\n\n return { runtime, connector, tools };\n}\n\n/**\n * Create AI SDK tools for browser automation via CDP code mode.\n *\n * Returns a `ToolSet` with a single durable `browser_execute` tool backed by\n * a codemode runtime: the model writes TypeScript against the `cdp` connector\n * (`cdp.send`, `cdp.attachToTarget`, `cdp.spec`, …), executions are recorded\n * for abort-and-replay, and browser sessions survive pauses.\n *\n * @example\n * ```ts\n * import { createBrowserTools } from \"agents/browser/ai\";\n * import { generateText } from \"ai\";\n *\n * // inside a Durable Object / Agent:\n * const browserTools = createBrowserTools({\n * ctx: this.ctx,\n * browser: this.env.BROWSER,\n * loader: this.env.LOADER,\n * });\n *\n * const result = await generateText({\n * model,\n * tools: { ...browserTools, ...otherTools },\n * messages,\n * });\n * ```\n */\nexport function createBrowserTools(\n options: CreateBrowserToolsOptions\n): ToolSet {\n return createBrowserRuntime(options).tools;\n}\n\n/** A Quick Action exposed as an AI SDK tool. */\nexport type QuickActionToolName =\n | \"markdown\"\n | \"extract\"\n | \"links\"\n | \"scrape\"\n | \"content\";\n\nexport interface CreateQuickActionToolsOptions {\n /**\n * Browser Run binding with Quick Actions support (`env.BROWSER`). Requires a\n * Worker `compatibility_date` of `2026-03-24`+ and `remote: true` for local\n * `wrangler dev`.\n */\n browser: QuickActionBinding;\n\n /**\n * Which tools to expose. Defaults to the text-returning, model-friendly set\n * (`markdown`, `extract`, `links`, `scrape`). `content` (raw HTML) is opt-in\n * since it is large and rarely what a model wants.\n */\n actions?: QuickActionToolName[];\n\n /**\n * Bound every result to roughly this many characters before returning it to\n * the model, to protect the context window, preserving each result's shape:\n * text (markdown/content) is truncated to a string, oversized arrays\n * (links/scrape) are trimmed but stay arrays, and only an opaque oversized\n * object degrades to a truncated-preview summary. Set to `0` to disable.\n * Defaults to 50000.\n */\n maxChars?: number;\n\n /**\n * Common Browser Run options merged into every request — e.g. `cookies`,\n * `authenticate`, or `setExtraHTTPHeaders` for authenticated pages, and\n * `gotoOptions` / `viewport` for JavaScript-heavy pages. The model only ever\n * supplies the page (`url`/`html`) and action-specific fields; these\n * host-supplied options are never exposed to it.\n */\n options?: QuickActionCommonOptions;\n}\n\nconst DEFAULT_QUICK_ACTION_TOOLS: QuickActionToolName[] = [\n \"markdown\",\n \"extract\",\n \"links\",\n \"scrape\"\n];\n\nconst DEFAULT_QUICK_ACTION_MAX_CHARS = 50_000;\n\nconst pageInputSchema = z\n .object({\n url: z.string().url().optional().describe(\"URL of the page to load\"),\n html: z\n .string()\n .optional()\n .describe(\"Raw HTML to render instead of loading a URL\")\n })\n .refine((value) => Boolean(value.url) || Boolean(value.html), {\n message: \"Provide either 'url' or 'html'\"\n });\n\nfunction toPage(\n input: { url?: string; html?: string },\n options?: QuickActionCommonOptions\n): QuickActionPage {\n const page = input.url ? { url: input.url } : { html: input.html as string };\n return { ...options, ...page } as QuickActionPage;\n}\n\nfunction truncate(text: string, maxChars: number): string {\n if (maxChars <= 0 || text.length <= maxChars) return text;\n return `${text.slice(0, maxChars)}\\n\\n[truncated ${text.length - maxChars} characters]`;\n}\n\n/**\n * Keep a tool result within a rough character budget so a single browse cannot\n * blow the model's context window — while preserving the result's shape so the\n * model sees a consistent type across calls:\n *\n * - strings (markdown/content) are truncated to a string;\n * - arrays (links/scrape) are trimmed from the end but stay arrays;\n * - only an opaque oversized object (e.g. a sprawling `extract`) degrades to a\n * `{ truncated, note, preview }` summary, since it cannot be trimmed safely.\n */\nfunction boundResult(value: unknown, maxChars: number): unknown {\n if (maxChars <= 0) return value;\n if (typeof value === \"string\") return truncate(value, maxChars);\n let json: string;\n try {\n json = JSON.stringify(value);\n } catch {\n return value;\n }\n if (json.length <= maxChars) return value;\n if (Array.isArray(value)) {\n const trimmed = boundArray(value, maxChars);\n // If even the first element overflows the budget, `trimmed` is empty —\n // returning `[]` would read as \"no results\" rather than \"too large\", so\n // fall through to the explicit truncated-preview summary instead.\n if (trimmed.length > 0) return trimmed;\n }\n return {\n truncated: true,\n note: `Result is too large (${json.length} characters); narrow the request.`,\n preview: `${json.slice(0, maxChars)}…`\n };\n}\n\n/**\n * Take as many leading items as fit within `maxChars` (measured against their\n * JSON length), returning a trimmed array of the same element type. Silent by\n * design: the model gets fewer, valid items rather than a reshaped result.\n */\nfunction boundArray(value: unknown[], maxChars: number): unknown[] {\n const out: unknown[] = [];\n let size = 2; // the enclosing \"[]\"\n for (const item of value) {\n const itemSize = JSON.stringify(item).length + 1; // + a separating comma\n if (size + itemSize > maxChars) break;\n out.push(item);\n size += itemSize;\n }\n return out;\n}\n\n/**\n * Create AI SDK tools for Browser Run [Quick Actions](https://developers.cloudflare.com/browser-run/quick-actions/):\n * stateless one-shot browsing (read a page as Markdown, extract structured\n * data with AI, list links, scrape elements). Unlike `createBrowserTools`,\n * these need only the `browser` binding — no Durable Object, loader, or\n * sandbox — so they work from any Worker.\n *\n * @example\n * ```ts\n * import { createQuickActionTools } from \"agents/browser/ai\";\n *\n * const tools = createQuickActionTools({ browser: this.env.BROWSER });\n * const result = await generateText({ model, tools, messages });\n * ```\n */\nexport function createQuickActionTools(\n options: CreateQuickActionToolsOptions\n): ToolSet {\n const { browser } = options;\n const requestOptions = options.options;\n const enabled = new Set(options.actions ?? DEFAULT_QUICK_ACTION_TOOLS);\n const maxChars = options.maxChars ?? DEFAULT_QUICK_ACTION_MAX_CHARS;\n const tools: ToolSet = {};\n\n if (enabled.has(\"markdown\")) {\n tools.browser_markdown = tool({\n description:\n \"Load a web page (or render raw HTML) and return its content as Markdown. Best for reading articles, docs, or any page as text.\",\n inputSchema: pageInputSchema,\n execute: async (input) =>\n boundResult(\n await browserMarkdown(browser, toPage(input, requestOptions)),\n maxChars\n )\n });\n }\n\n if (enabled.has(\"extract\")) {\n tools.browser_extract = tool({\n description:\n \"Extract structured data from a web page using AI. Describe what you want in 'prompt'. Passing a JSON Schema in 'schema' is strongly recommended — without one the extractor often fails to produce JSON.\",\n inputSchema: z\n .object({\n url: z.string().url().optional().describe(\"URL of the page to load\"),\n html: z\n .string()\n .optional()\n .describe(\"Raw HTML to render instead of loading a URL\"),\n prompt: z\n .string()\n .optional()\n .describe(\"What to extract, in natural language\"),\n schema: z\n .record(z.string(), z.unknown(), {\n error: \"Schema must be a JSON object\"\n })\n .optional()\n .describe(\"Optional JSON Schema describing the desired output\")\n })\n .refine((value) => Boolean(value.url) || Boolean(value.html), {\n message: \"Provide either 'url' or 'html'\"\n })\n .refine((value) => Boolean(value.prompt) || Boolean(value.schema), {\n message: \"Provide either 'prompt' or 'schema'\"\n }),\n execute: async (input) =>\n boundResult(\n await browserExtract(browser, {\n ...toPage(input, requestOptions),\n prompt: input.prompt,\n response_format: input.schema\n ? { type: \"json_schema\", json_schema: input.schema }\n : undefined\n }),\n maxChars\n )\n });\n }\n\n if (enabled.has(\"links\")) {\n tools.browser_links = tool({\n description:\n \"Return every link found on a web page (including ones not visible). Useful for discovering pages to follow.\",\n inputSchema: pageInputSchema,\n execute: async (input) =>\n boundResult(\n await browserLinks(browser, toPage(input, requestOptions)),\n maxChars\n )\n });\n }\n\n if (enabled.has(\"scrape\")) {\n tools.browser_scrape = tool({\n description:\n \"Scrape specific elements from a web page by CSS selector. Returns the matched elements' text, HTML, and attributes.\",\n inputSchema: z\n .object({\n url: z.string().url().optional().describe(\"URL of the page to load\"),\n html: z\n .string()\n .optional()\n .describe(\"Raw HTML to render instead of loading a URL\"),\n selectors: z\n .array(z.string())\n .min(1)\n .describe(\"CSS selectors to extract\")\n })\n .refine((value) => Boolean(value.url) || Boolean(value.html), {\n message: \"Provide either 'url' or 'html'\"\n }),\n execute: async (input) =>\n boundResult(\n await browserScrape(browser, {\n ...toPage(input, requestOptions),\n elements: input.selectors.map((selector) => ({ selector }))\n }),\n maxChars\n )\n });\n }\n\n if (enabled.has(\"content\")) {\n tools.browser_content = tool({\n description:\n \"Load a web page and return its fully rendered HTML (after JavaScript runs). Prefer 'browser_markdown' unless you need the raw HTML.\",\n inputSchema: pageInputSchema,\n execute: async (input) =>\n boundResult(\n await browserContent(browser, toPage(input, requestOptions)),\n maxChars\n )\n });\n }\n\n return tools;\n}\n"],"mappings":"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"}