agents 0.15.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-tool-types-VPsjVYL0.d.ts → agent-tool-types-NofdbL9X.d.ts} +57 -4
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-BGpgfpJT.d.ts → agent-tools-DLquv-dp.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/browser/ai.d.ts +211 -7
- package/dist/browser/ai.js +236 -25
- package/dist/browser/ai.js.map +1 -1
- package/dist/browser/index.d.ts +133 -69
- package/dist/browser/index.js +3 -2
- package/dist/browser/tanstack-ai.d.ts +17 -7
- package/dist/browser/tanstack-ai.js +25 -19
- package/dist/browser/tanstack-ai.js.map +1 -1
- package/dist/chat/index.d.ts +111 -5
- package/dist/chat/index.js +207 -35
- package/dist/chat/index.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +1 -1
- package/dist/{classPrivateFieldGet2-Beqsfu2Z.js → classPrivateFieldGet2-CZ7QjTXN.js} +5 -5
- package/dist/{classPrivateMethodInitSpec-B5ko1s2R.js → classPrivateMethodInitSpec-D-0__zd9.js} +2 -2
- package/dist/client.d.ts +19 -2
- package/dist/client.js +31 -11
- package/dist/client.js.map +1 -1
- package/dist/{compaction-helpers-BEUILPss.d.ts → compaction-helpers-DVcu5lPN.d.ts} +91 -12
- package/dist/connector-CrKhowfD.js +1291 -0
- package/dist/connector-CrKhowfD.js.map +1 -0
- package/dist/connector-v2M1zlZp.d.ts +659 -0
- package/dist/experimental/memory/session/index.d.ts +75 -12
- package/dist/experimental/memory/session/index.js +226 -21
- package/dist/experimental/memory/session/index.js.map +1 -1
- package/dist/experimental/memory/utils/index.d.ts +2 -2
- package/dist/{index-CPe1OtI0.d.ts → index-B7IbEeze.d.ts} +32 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.js +119 -45
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/observability/index.d.ts +1 -1
- package/dist/react.d.ts +12 -1
- package/dist/react.js +101 -30
- package/dist/react.js.map +1 -1
- package/dist/{retries-CF_HKSlJ.d.ts → retries-CwlpAGet.d.ts} +35 -5
- package/dist/retries.d.ts +9 -5
- package/dist/retries.js +87 -1
- package/dist/retries.js.map +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/skills/index.js +2 -2
- package/dist/sub-routing.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/package.json +11 -11
- package/dist/shared-4CAYLCTO.d.ts +0 -34
- package/dist/shared-wyII629d.js +0 -432
- package/dist/shared-wyII629d.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { n as AgentEmail } from "./internal_context-Dg4Cgjcu.js";
|
|
2
|
-
import { t as RetryOptions } from "./retries-
|
|
2
|
+
import { t as RetryOptions } from "./retries-CwlpAGet.js";
|
|
3
3
|
import {
|
|
4
4
|
n as Observability,
|
|
5
5
|
r as ObservabilityEvent,
|
|
6
6
|
s as MCPObservabilityEvent
|
|
7
|
-
} from "./index-
|
|
7
|
+
} from "./index-B7IbEeze.js";
|
|
8
8
|
import { t as AgentMcpOAuthProvider } from "./do-oauth-client-provider-D4ZwyBDu.js";
|
|
9
9
|
import {
|
|
10
10
|
_ as WorkflowPage,
|
|
@@ -2343,7 +2343,15 @@ interface AgentStaticOptions {
|
|
|
2343
2343
|
/**
|
|
2344
2344
|
* Maximum age in milliseconds of an unmanaged interrupted-fiber row before
|
|
2345
2345
|
* recovery stops retrying a repeatedly-throwing `onFiberRecovered()` hook
|
|
2346
|
-
* and discards the row
|
|
2346
|
+
* and discards the row (emitting `fiber:recovery:skipped` with reason
|
|
2347
|
+
* `max_age_exceeded`). Defaults to 24h.
|
|
2348
|
+
*
|
|
2349
|
+
* Set to `0` to retain rows indefinitely. NOTE: with `0`, a hook that keeps
|
|
2350
|
+
* throwing is retried forever — the recovery alarm backs off exponentially
|
|
2351
|
+
* (capped at 5 minutes) so it is not a busy-loop, but the Durable Object
|
|
2352
|
+
* stays warm (never idle-evicts) for as long as the un-recoverable row
|
|
2353
|
+
* exists. Prefer a finite age unless you intend to inspect/clear such rows
|
|
2354
|
+
* yourself.
|
|
2347
2355
|
*/
|
|
2348
2356
|
fiberRecoveryMaxAgeMs?: number;
|
|
2349
2357
|
/**
|
|
@@ -2467,6 +2475,13 @@ declare class Agent<
|
|
|
2467
2475
|
private _managedFiberTerminalWaiters;
|
|
2468
2476
|
/** @internal Prevents re-entrant recovery from overlapping alarm ticks. */
|
|
2469
2477
|
private _runFiberRecoveryInProgress;
|
|
2478
|
+
/**
|
|
2479
|
+
* @internal Consecutive runFiber-recovery scans that made NO forward progress
|
|
2480
|
+
* while work was still pending. Drives the exponential backoff of the
|
|
2481
|
+
* recovery follow-up alarm so a repeatedly-throwing recovery hook does not
|
|
2482
|
+
* busy-loop the DO. Reset to 0 whenever a scan recovers anything.
|
|
2483
|
+
*/
|
|
2484
|
+
private _recoveryNoProgressScans;
|
|
2470
2485
|
/** @internal Single-flight background recovery for parent agent-tool rows. */
|
|
2471
2486
|
private _agentToolRunRecoveryPromise;
|
|
2472
2487
|
private _ParentClass;
|
|
@@ -3296,6 +3311,18 @@ declare class Agent<
|
|
|
3296
3311
|
targetPath: ReadonlyArray<AgentPathStep>
|
|
3297
3312
|
): Promise<void>;
|
|
3298
3313
|
private _executeScheduleCallback;
|
|
3314
|
+
/**
|
|
3315
|
+
* Whether any runFiber recovery work is still outstanding: orphaned
|
|
3316
|
+
* `cf_agents_runs` rows left by a dead process (excluding fibers currently
|
|
3317
|
+
* executing in memory, which already hold a keepAlive ref) or managed
|
|
3318
|
+
* ledger fibers stuck in a non-terminal state with no live run row.
|
|
3319
|
+
*
|
|
3320
|
+
* Used by `_scheduleNextAlarm` to arm a follow-up alarm so multi-pass
|
|
3321
|
+
* recovery (e.g. after a scan-deadline yield, or while retrying a throwing
|
|
3322
|
+
* recovery hook) resumes instead of starving.
|
|
3323
|
+
* @internal
|
|
3324
|
+
*/
|
|
3325
|
+
private _hasPendingFiberRecovery;
|
|
3299
3326
|
private _scheduleNextAlarm;
|
|
3300
3327
|
/**
|
|
3301
3328
|
* Override PartyServer's onAlarm hook as a no-op.
|
|
@@ -3861,6 +3888,32 @@ declare class Agent<
|
|
|
3861
3888
|
* callers should treat it as fire-and-forget.
|
|
3862
3889
|
*/
|
|
3863
3890
|
destroy(): Promise<void>;
|
|
3891
|
+
/**
|
|
3892
|
+
* @internal Defer this agent's destruction to its own alarm invocation
|
|
3893
|
+
* instead of running it inline (#1625).
|
|
3894
|
+
*
|
|
3895
|
+
* `destroy()` is a multi-step I/O sequence (drop tables, delete alarm,
|
|
3896
|
+
* delete all storage, dispose connections). Running it on the `waitUntil`
|
|
3897
|
+
* of a request whose client has already disconnected — the MCP
|
|
3898
|
+
* Streamable-HTTP session-DELETE path — gives it little to no
|
|
3899
|
+
* post-invocation grace, so the runtime routinely cancels it mid-flight.
|
|
3900
|
+
* This method instead performs two fast storage writes (a durable
|
|
3901
|
+
* "condemned" marker and an immediate alarm) that the caller can await
|
|
3902
|
+
* before responding; the alarm then fires as a fresh invocation with its
|
|
3903
|
+
* own full execution budget and runs `destroy()` there. If even that
|
|
3904
|
+
* invocation is interrupted, the marker survives and the next wake
|
|
3905
|
+
* finishes teardown — see the `alarm()` preamble.
|
|
3906
|
+
*
|
|
3907
|
+
* Unlike `destroy()`, this method does not abort the isolate, so RPC
|
|
3908
|
+
* callers don't need to swallow an abort error.
|
|
3909
|
+
*/
|
|
3910
|
+
_cf_scheduleDestroy(): Promise<void>;
|
|
3911
|
+
/**
|
|
3912
|
+
* Whether a (deferred or interrupted) destroy is pending. Reads the
|
|
3913
|
+
* durable marker directly — the in-memory `_isFacet` flag may not be
|
|
3914
|
+
* hydrated yet at the call sites, but facets never write the marker.
|
|
3915
|
+
*/
|
|
3916
|
+
private _hasPendingDestroy;
|
|
3864
3917
|
/** @internal Drop every internal Agents SDK table during top-level destroy. */
|
|
3865
3918
|
protected _dropInternalTablesForDestroy(): void;
|
|
3866
3919
|
/**
|
|
@@ -4794,4 +4847,4 @@ export {
|
|
|
4794
4847
|
MCPServer as z,
|
|
4795
4848
|
WorkerTransport as zt
|
|
4796
4849
|
};
|
|
4797
|
-
//# sourceMappingURL=agent-tool-types-
|
|
4850
|
+
//# sourceMappingURL=agent-tool-types-NofdbL9X.d.ts.map
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
s as AgentToolInterruptedReason,
|
|
17
17
|
t as AgentToolChildAdapter,
|
|
18
18
|
u as AgentToolRunInspection
|
|
19
|
-
} from "./agent-tool-types-
|
|
19
|
+
} from "./agent-tool-types-NofdbL9X.js";
|
|
20
20
|
export {
|
|
21
21
|
AgentToolChildAdapter,
|
|
22
22
|
AgentToolDisplayMetadata,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
a as AgentToolEventState,
|
|
3
3
|
i as AgentToolEventMessage
|
|
4
|
-
} from "./agent-tool-types-
|
|
4
|
+
} from "./agent-tool-types-NofdbL9X.js";
|
|
5
5
|
|
|
6
6
|
//#region src/chat/agent-tools.d.ts
|
|
7
7
|
declare function createAgentToolEventState(): AgentToolEventState;
|
|
@@ -11,4 +11,4 @@ declare function applyAgentToolEvent(
|
|
|
11
11
|
): AgentToolEventState;
|
|
12
12
|
//#endregion
|
|
13
13
|
export { createAgentToolEventState as n, applyAgentToolEvent as t };
|
|
14
|
-
//# sourceMappingURL=agent-tools-
|
|
14
|
+
//# sourceMappingURL=agent-tools-DLquv-dp.d.ts.map
|
package/dist/agent-tools.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
s as AgentToolInterruptedReason,
|
|
17
17
|
t as AgentToolChildAdapter,
|
|
18
18
|
u as AgentToolRunInspection
|
|
19
|
-
} from "./agent-tool-types-
|
|
19
|
+
} from "./agent-tool-types-NofdbL9X.js";
|
|
20
20
|
import { Tool } from "ai";
|
|
21
21
|
|
|
22
22
|
//#region src/agent-tools.d.ts
|
package/dist/browser/ai.d.ts
CHANGED
|
@@ -1,21 +1,159 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
I as BrowserBinding,
|
|
3
|
+
f as BrowserSessionStore,
|
|
4
|
+
r as BrowserConnectorSessionOptions,
|
|
5
|
+
t as BrowserConnector,
|
|
6
|
+
v as QuickActionBinding,
|
|
7
|
+
y as QuickActionCommonOptions
|
|
8
|
+
} from "../connector-v2M1zlZp.js";
|
|
2
9
|
import { ToolSet } from "ai";
|
|
10
|
+
import { CodemodeRuntimeHandle } from "@cloudflare/codemode";
|
|
3
11
|
|
|
4
12
|
//#region src/browser/ai.d.ts
|
|
13
|
+
interface CreateBrowserToolsOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Durable Object state. The codemode runtime that backs the browser tool
|
|
16
|
+
* lives in a facet of this DO, and browser session ids are stored in its
|
|
17
|
+
* storage — so the tool must be created from inside a Durable Object
|
|
18
|
+
* (e.g. an Agent).
|
|
19
|
+
*
|
|
20
|
+
* Optional: when omitted, it is resolved from the current Agent via
|
|
21
|
+
* `getCurrentAgent()`, so inside an Agent method you can just pass `browser`
|
|
22
|
+
* and `loader`. Pass it explicitly outside an Agent context.
|
|
23
|
+
*
|
|
24
|
+
* The worker must export the `CodemodeRuntime` class (the
|
|
25
|
+
* `@cloudflare/codemode/vite` plugin does this automatically, or add
|
|
26
|
+
* `export { CodemodeRuntime } from "@cloudflare/codemode"` to your entry).
|
|
27
|
+
*/
|
|
28
|
+
ctx?: DurableObjectState;
|
|
29
|
+
/**
|
|
30
|
+
* WorkerLoader binding for sandboxed code execution.
|
|
31
|
+
*
|
|
32
|
+
* Requires `"worker_loaders": [{ "binding": "LOADER" }]` in wrangler.jsonc.
|
|
33
|
+
*/
|
|
34
|
+
loader: WorkerLoader;
|
|
35
|
+
/**
|
|
36
|
+
* Browser Rendering binding (Fetcher).
|
|
37
|
+
*
|
|
38
|
+
* This is the primary way to connect — works both locally in
|
|
39
|
+
* `wrangler dev` and when deployed to Cloudflare Workers.
|
|
40
|
+
*
|
|
41
|
+
* Requires `"browser": { "binding": "BROWSER" }` in wrangler.jsonc.
|
|
42
|
+
*/
|
|
43
|
+
browser?: BrowserBinding;
|
|
44
|
+
/**
|
|
45
|
+
* Optional CDP base URL override (e.g. `http://localhost:9222`).
|
|
46
|
+
*
|
|
47
|
+
* Use when connecting to a manually managed Chrome instance or
|
|
48
|
+
* a remote CDP endpoint behind a tunnel.
|
|
49
|
+
*/
|
|
50
|
+
cdpUrl?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Headers to send with CDP URL discovery requests.
|
|
53
|
+
* Useful when the CDP endpoint requires authentication
|
|
54
|
+
* (e.g. Cloudflare Access headers).
|
|
55
|
+
*/
|
|
56
|
+
cdpHeaders?: Record<string, string>;
|
|
57
|
+
/**
|
|
58
|
+
* Browser session lifecycle (binding-backed only). Defaults to one fresh
|
|
59
|
+
* session per codemode execution (`one-shot`).
|
|
60
|
+
*/
|
|
61
|
+
session?: BrowserConnectorSessionOptions;
|
|
62
|
+
/**
|
|
63
|
+
* Durable store for Browser Run session ids. Defaults to a
|
|
64
|
+
* {@link DurableBrowserSessionStore} over `ctx.storage`.
|
|
65
|
+
*/
|
|
66
|
+
store?: BrowserSessionStore;
|
|
67
|
+
/**
|
|
68
|
+
* Sandbox execution timeout in milliseconds. Defaults to 30000 (30s).
|
|
69
|
+
* Also used as the per-CDP-command timeout.
|
|
70
|
+
*/
|
|
71
|
+
timeout?: number;
|
|
72
|
+
/**
|
|
73
|
+
* Codemode runtime name — the durable identity of the tool's executions
|
|
74
|
+
* and snippets. Defaults to `"browser"`.
|
|
75
|
+
*/
|
|
76
|
+
name?: string;
|
|
77
|
+
/**
|
|
78
|
+
* Also expose stateless {@link createQuickActionTools | Quick Action} tools
|
|
79
|
+
* (`browser_markdown`, `browser_extract`, …) alongside the durable
|
|
80
|
+
* `browser_execute` tool.
|
|
81
|
+
*
|
|
82
|
+
* Enabled by default whenever a Browser Run `browser` binding is available
|
|
83
|
+
* (they share it). Pass an object to configure them, or `false` to disable.
|
|
84
|
+
* The Quick Action binding defaults to `browser`; override it via
|
|
85
|
+
* `quickActions.browser`. When only `cdpUrl` is set (no binding), the
|
|
86
|
+
* defaults are skipped silently — pass `quickActions: { browser }` to force
|
|
87
|
+
* them.
|
|
88
|
+
*/
|
|
89
|
+
quickActions?:
|
|
90
|
+
| boolean
|
|
91
|
+
| {
|
|
92
|
+
browser?: QuickActionBinding;
|
|
93
|
+
actions?: QuickActionToolName[];
|
|
94
|
+
maxChars?: number;
|
|
95
|
+
options?: QuickActionCommonOptions;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The browser tool's moving parts, for hosts that need more than the tools:
|
|
100
|
+
*
|
|
101
|
+
* - `runtime` — the codemode runtime handle (approve/reject paused runs,
|
|
102
|
+
* `expirePaused`, audit via `executions()`, snippets).
|
|
103
|
+
* - `connector` — host-side session helpers: `sessionInfo()`,
|
|
104
|
+
* `closeSession()`, and `sweep()` for a recurring cleanup task.
|
|
105
|
+
* - `tools` — what `createBrowserTools` returns.
|
|
106
|
+
*/
|
|
107
|
+
interface BrowserRuntime {
|
|
108
|
+
runtime: CodemodeRuntimeHandle;
|
|
109
|
+
connector: BrowserConnector;
|
|
110
|
+
tools: ToolSet;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create the browser codemode runtime: the `browser_execute` tool plus the
|
|
114
|
+
* runtime handle and connector for host-side wiring (approvals, session info,
|
|
115
|
+
* sweeps).
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* export class MyAgent extends Agent<Env> {
|
|
120
|
+
* get browser() {
|
|
121
|
+
* return createBrowserRuntime({
|
|
122
|
+
* ctx: this.ctx,
|
|
123
|
+
* browser: this.env.BROWSER,
|
|
124
|
+
* loader: this.env.LOADER,
|
|
125
|
+
* session: { mode: "dynamic" }
|
|
126
|
+
* });
|
|
127
|
+
* }
|
|
128
|
+
*
|
|
129
|
+
* @callable()
|
|
130
|
+
* async closeBrowserSession() {
|
|
131
|
+
* await this.browser.connector.closeSession();
|
|
132
|
+
* }
|
|
133
|
+
* }
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
declare function createBrowserRuntime(
|
|
137
|
+
options: CreateBrowserToolsOptions
|
|
138
|
+
): BrowserRuntime;
|
|
5
139
|
/**
|
|
6
140
|
* Create AI SDK tools for browser automation via CDP code mode.
|
|
7
141
|
*
|
|
8
|
-
* Returns a `ToolSet` with `
|
|
9
|
-
*
|
|
142
|
+
* Returns a `ToolSet` with a single durable `browser_execute` tool backed by
|
|
143
|
+
* a codemode runtime: the model writes TypeScript against the `cdp` connector
|
|
144
|
+
* (`cdp.send`, `cdp.attachToTarget`, `cdp.spec`, …), executions are recorded
|
|
145
|
+
* for abort-and-replay, and browser sessions survive pauses.
|
|
10
146
|
*
|
|
11
147
|
* @example
|
|
12
148
|
* ```ts
|
|
13
149
|
* import { createBrowserTools } from "agents/browser/ai";
|
|
14
150
|
* import { generateText } from "ai";
|
|
15
151
|
*
|
|
152
|
+
* // inside a Durable Object / Agent:
|
|
16
153
|
* const browserTools = createBrowserTools({
|
|
17
|
-
*
|
|
18
|
-
*
|
|
154
|
+
* ctx: this.ctx,
|
|
155
|
+
* browser: this.env.BROWSER,
|
|
156
|
+
* loader: this.env.LOADER,
|
|
19
157
|
* });
|
|
20
158
|
*
|
|
21
159
|
* const result = await generateText({
|
|
@@ -25,7 +163,73 @@ import { ToolSet } from "ai";
|
|
|
25
163
|
* });
|
|
26
164
|
* ```
|
|
27
165
|
*/
|
|
28
|
-
declare function createBrowserTools(
|
|
166
|
+
declare function createBrowserTools(
|
|
167
|
+
options: CreateBrowserToolsOptions
|
|
168
|
+
): ToolSet;
|
|
169
|
+
/** A Quick Action exposed as an AI SDK tool. */
|
|
170
|
+
type QuickActionToolName =
|
|
171
|
+
| "markdown"
|
|
172
|
+
| "extract"
|
|
173
|
+
| "links"
|
|
174
|
+
| "scrape"
|
|
175
|
+
| "content";
|
|
176
|
+
interface CreateQuickActionToolsOptions {
|
|
177
|
+
/**
|
|
178
|
+
* Browser Run binding with Quick Actions support (`env.BROWSER`). Requires a
|
|
179
|
+
* Worker `compatibility_date` of `2026-03-24`+ and `remote: true` for local
|
|
180
|
+
* `wrangler dev`.
|
|
181
|
+
*/
|
|
182
|
+
browser: QuickActionBinding;
|
|
183
|
+
/**
|
|
184
|
+
* Which tools to expose. Defaults to the text-returning, model-friendly set
|
|
185
|
+
* (`markdown`, `extract`, `links`, `scrape`). `content` (raw HTML) is opt-in
|
|
186
|
+
* since it is large and rarely what a model wants.
|
|
187
|
+
*/
|
|
188
|
+
actions?: QuickActionToolName[];
|
|
189
|
+
/**
|
|
190
|
+
* Bound every result to roughly this many characters before returning it to
|
|
191
|
+
* the model, to protect the context window, preserving each result's shape:
|
|
192
|
+
* text (markdown/content) is truncated to a string, oversized arrays
|
|
193
|
+
* (links/scrape) are trimmed but stay arrays, and only an opaque oversized
|
|
194
|
+
* object degrades to a truncated-preview summary. Set to `0` to disable.
|
|
195
|
+
* Defaults to 50000.
|
|
196
|
+
*/
|
|
197
|
+
maxChars?: number;
|
|
198
|
+
/**
|
|
199
|
+
* Common Browser Run options merged into every request — e.g. `cookies`,
|
|
200
|
+
* `authenticate`, or `setExtraHTTPHeaders` for authenticated pages, and
|
|
201
|
+
* `gotoOptions` / `viewport` for JavaScript-heavy pages. The model only ever
|
|
202
|
+
* supplies the page (`url`/`html`) and action-specific fields; these
|
|
203
|
+
* host-supplied options are never exposed to it.
|
|
204
|
+
*/
|
|
205
|
+
options?: QuickActionCommonOptions;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Create AI SDK tools for Browser Run [Quick Actions](https://developers.cloudflare.com/browser-run/quick-actions/):
|
|
209
|
+
* stateless one-shot browsing (read a page as Markdown, extract structured
|
|
210
|
+
* data with AI, list links, scrape elements). Unlike `createBrowserTools`,
|
|
211
|
+
* these need only the `browser` binding — no Durable Object, loader, or
|
|
212
|
+
* sandbox — so they work from any Worker.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```ts
|
|
216
|
+
* import { createQuickActionTools } from "agents/browser/ai";
|
|
217
|
+
*
|
|
218
|
+
* const tools = createQuickActionTools({ browser: this.env.BROWSER });
|
|
219
|
+
* const result = await generateText({ model, tools, messages });
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
declare function createQuickActionTools(
|
|
223
|
+
options: CreateQuickActionToolsOptions
|
|
224
|
+
): ToolSet;
|
|
29
225
|
//#endregion
|
|
30
|
-
export {
|
|
226
|
+
export {
|
|
227
|
+
BrowserRuntime,
|
|
228
|
+
CreateBrowserToolsOptions,
|
|
229
|
+
CreateQuickActionToolsOptions,
|
|
230
|
+
QuickActionToolName,
|
|
231
|
+
createBrowserRuntime,
|
|
232
|
+
createBrowserTools,
|
|
233
|
+
createQuickActionTools
|
|
234
|
+
};
|
|
31
235
|
//# sourceMappingURL=ai.d.ts.map
|
package/dist/browser/ai.js
CHANGED
|
@@ -1,21 +1,117 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { __DO_NOT_USE_WILL_BREAK__agentContext } from "../internal_context.js";
|
|
2
|
+
import { c as browserLinks, d as browserScrape, i as DurableBrowserSessionStore, l as browserMarkdown, o as browserContent, s as browserExtract, t as BrowserConnector } from "../connector-CrKhowfD.js";
|
|
2
3
|
import { tool } from "ai";
|
|
3
4
|
import { z } from "zod";
|
|
5
|
+
import { DynamicWorkerExecutor, createCodemodeRuntime, truncateResult } from "@cloudflare/codemode";
|
|
4
6
|
//#region src/browser/ai.ts
|
|
7
|
+
let didWarnExperimental = false;
|
|
8
|
+
let didDebugQuickActionSkip = false;
|
|
9
|
+
/**
|
|
10
|
+
* The Durable Object state to build the runtime in: the explicit `ctx` if
|
|
11
|
+
* given, otherwise the current Agent's `ctx` (via `getCurrentAgent()`), so
|
|
12
|
+
* `createBrowserRuntime` can be called from an Agent method without threading
|
|
13
|
+
* `this.ctx` through.
|
|
14
|
+
*/
|
|
15
|
+
function resolveCtx(options) {
|
|
16
|
+
if (options.ctx) return options.ctx;
|
|
17
|
+
return (__DO_NOT_USE_WILL_BREAK__agentContext.getStore()?.agent)?.ctx;
|
|
18
|
+
}
|
|
19
|
+
function connectorOptions(options, ctx) {
|
|
20
|
+
if (options.cdpUrl) return {
|
|
21
|
+
cdpUrl: options.cdpUrl,
|
|
22
|
+
cdpHeaders: options.cdpHeaders,
|
|
23
|
+
timeout: options.timeout
|
|
24
|
+
};
|
|
25
|
+
if (!options.browser) throw new Error("Either 'browser' (Fetcher binding) or 'cdpUrl' must be provided");
|
|
26
|
+
return {
|
|
27
|
+
browser: options.browser,
|
|
28
|
+
store: options.store ?? new DurableBrowserSessionStore(ctx.storage),
|
|
29
|
+
session: options.session,
|
|
30
|
+
timeout: options.timeout
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create the browser codemode runtime: the `browser_execute` tool plus the
|
|
35
|
+
* runtime handle and connector for host-side wiring (approvals, session info,
|
|
36
|
+
* sweeps).
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* export class MyAgent extends Agent<Env> {
|
|
41
|
+
* get browser() {
|
|
42
|
+
* return createBrowserRuntime({
|
|
43
|
+
* ctx: this.ctx,
|
|
44
|
+
* browser: this.env.BROWSER,
|
|
45
|
+
* loader: this.env.LOADER,
|
|
46
|
+
* session: { mode: "dynamic" }
|
|
47
|
+
* });
|
|
48
|
+
* }
|
|
49
|
+
*
|
|
50
|
+
* @callable()
|
|
51
|
+
* async closeBrowserSession() {
|
|
52
|
+
* await this.browser.connector.closeSession();
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
function createBrowserRuntime(options) {
|
|
58
|
+
if (!didWarnExperimental) {
|
|
59
|
+
didWarnExperimental = true;
|
|
60
|
+
console.warn("[agents/browser] Browser tools are experimental and may change in a future release.");
|
|
61
|
+
}
|
|
62
|
+
const ctx = resolveCtx(options);
|
|
63
|
+
if (!ctx) throw new Error("createBrowserRuntime requires a Durable Object 'ctx' — pass it explicitly, or call from within an Agent so it can be resolved via getCurrentAgent()");
|
|
64
|
+
const connector = new BrowserConnector(ctx, connectorOptions(options, ctx));
|
|
65
|
+
const runtime = createCodemodeRuntime({
|
|
66
|
+
ctx,
|
|
67
|
+
executor: new DynamicWorkerExecutor({
|
|
68
|
+
loader: options.loader,
|
|
69
|
+
timeout: options.timeout
|
|
70
|
+
}),
|
|
71
|
+
connectors: [connector],
|
|
72
|
+
name: options.name ?? "browser",
|
|
73
|
+
transformResult: truncateResult
|
|
74
|
+
});
|
|
75
|
+
const tools = { browser_execute: runtime.tool() };
|
|
76
|
+
if (options.quickActions !== false) {
|
|
77
|
+
const qa = options.quickActions == null || options.quickActions === true ? {} : options.quickActions;
|
|
78
|
+
const quickActionBrowser = qa.browser ?? options.browser;
|
|
79
|
+
if (quickActionBrowser) Object.assign(tools, createQuickActionTools({
|
|
80
|
+
browser: quickActionBrowser,
|
|
81
|
+
actions: qa.actions,
|
|
82
|
+
maxChars: qa.maxChars,
|
|
83
|
+
options: qa.options
|
|
84
|
+
}));
|
|
85
|
+
else if (options.quickActions) throw new Error("quickActions requires a Browser Run binding — set 'browser' (env.BROWSER) or 'quickActions.browser'");
|
|
86
|
+
else if (!didDebugQuickActionSkip) {
|
|
87
|
+
didDebugQuickActionSkip = true;
|
|
88
|
+
console.debug("[agents/browser] Quick Action tools skipped — no Browser Run binding (only 'cdpUrl' is set). Pass 'browser' or 'quickActions.browser' to enable them.");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
runtime,
|
|
93
|
+
connector,
|
|
94
|
+
tools
|
|
95
|
+
};
|
|
96
|
+
}
|
|
5
97
|
/**
|
|
6
98
|
* Create AI SDK tools for browser automation via CDP code mode.
|
|
7
99
|
*
|
|
8
|
-
* Returns a `ToolSet` with `
|
|
9
|
-
*
|
|
100
|
+
* Returns a `ToolSet` with a single durable `browser_execute` tool backed by
|
|
101
|
+
* a codemode runtime: the model writes TypeScript against the `cdp` connector
|
|
102
|
+
* (`cdp.send`, `cdp.attachToTarget`, `cdp.spec`, …), executions are recorded
|
|
103
|
+
* for abort-and-replay, and browser sessions survive pauses.
|
|
10
104
|
*
|
|
11
105
|
* @example
|
|
12
106
|
* ```ts
|
|
13
107
|
* import { createBrowserTools } from "agents/browser/ai";
|
|
14
108
|
* import { generateText } from "ai";
|
|
15
109
|
*
|
|
110
|
+
* // inside a Durable Object / Agent:
|
|
16
111
|
* const browserTools = createBrowserTools({
|
|
17
|
-
*
|
|
18
|
-
*
|
|
112
|
+
* ctx: this.ctx,
|
|
113
|
+
* browser: this.env.BROWSER,
|
|
114
|
+
* loader: this.env.LOADER,
|
|
19
115
|
* });
|
|
20
116
|
*
|
|
21
117
|
* const result = await generateText({
|
|
@@ -26,29 +122,144 @@ import { z } from "zod";
|
|
|
26
122
|
* ```
|
|
27
123
|
*/
|
|
28
124
|
function createBrowserTools(options) {
|
|
29
|
-
|
|
125
|
+
return createBrowserRuntime(options).tools;
|
|
126
|
+
}
|
|
127
|
+
const DEFAULT_QUICK_ACTION_TOOLS = [
|
|
128
|
+
"markdown",
|
|
129
|
+
"extract",
|
|
130
|
+
"links",
|
|
131
|
+
"scrape"
|
|
132
|
+
];
|
|
133
|
+
const DEFAULT_QUICK_ACTION_MAX_CHARS = 5e4;
|
|
134
|
+
const pageInputSchema = z.object({
|
|
135
|
+
url: z.string().url().optional().describe("URL of the page to load"),
|
|
136
|
+
html: z.string().optional().describe("Raw HTML to render instead of loading a URL")
|
|
137
|
+
}).refine((value) => Boolean(value.url) || Boolean(value.html), { message: "Provide either 'url' or 'html'" });
|
|
138
|
+
function toPage(input, options) {
|
|
139
|
+
const page = input.url ? { url: input.url } : { html: input.html };
|
|
30
140
|
return {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
141
|
+
...options,
|
|
142
|
+
...page
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
function truncate(text, maxChars) {
|
|
146
|
+
if (maxChars <= 0 || text.length <= maxChars) return text;
|
|
147
|
+
return `${text.slice(0, maxChars)}\n\n[truncated ${text.length - maxChars} characters]`;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Keep a tool result within a rough character budget so a single browse cannot
|
|
151
|
+
* blow the model's context window — while preserving the result's shape so the
|
|
152
|
+
* model sees a consistent type across calls:
|
|
153
|
+
*
|
|
154
|
+
* - strings (markdown/content) are truncated to a string;
|
|
155
|
+
* - arrays (links/scrape) are trimmed from the end but stay arrays;
|
|
156
|
+
* - only an opaque oversized object (e.g. a sprawling `extract`) degrades to a
|
|
157
|
+
* `{ truncated, note, preview }` summary, since it cannot be trimmed safely.
|
|
158
|
+
*/
|
|
159
|
+
function boundResult(value, maxChars) {
|
|
160
|
+
if (maxChars <= 0) return value;
|
|
161
|
+
if (typeof value === "string") return truncate(value, maxChars);
|
|
162
|
+
let json;
|
|
163
|
+
try {
|
|
164
|
+
json = JSON.stringify(value);
|
|
165
|
+
} catch {
|
|
166
|
+
return value;
|
|
167
|
+
}
|
|
168
|
+
if (json.length <= maxChars) return value;
|
|
169
|
+
if (Array.isArray(value)) {
|
|
170
|
+
const trimmed = boundArray(value, maxChars);
|
|
171
|
+
if (trimmed.length > 0) return trimmed;
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
truncated: true,
|
|
175
|
+
note: `Result is too large (${json.length} characters); narrow the request.`,
|
|
176
|
+
preview: `${json.slice(0, maxChars)}…`
|
|
49
177
|
};
|
|
50
178
|
}
|
|
179
|
+
/**
|
|
180
|
+
* Take as many leading items as fit within `maxChars` (measured against their
|
|
181
|
+
* JSON length), returning a trimmed array of the same element type. Silent by
|
|
182
|
+
* design: the model gets fewer, valid items rather than a reshaped result.
|
|
183
|
+
*/
|
|
184
|
+
function boundArray(value, maxChars) {
|
|
185
|
+
const out = [];
|
|
186
|
+
let size = 2;
|
|
187
|
+
for (const item of value) {
|
|
188
|
+
const itemSize = JSON.stringify(item).length + 1;
|
|
189
|
+
if (size + itemSize > maxChars) break;
|
|
190
|
+
out.push(item);
|
|
191
|
+
size += itemSize;
|
|
192
|
+
}
|
|
193
|
+
return out;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Create AI SDK tools for Browser Run [Quick Actions](https://developers.cloudflare.com/browser-run/quick-actions/):
|
|
197
|
+
* stateless one-shot browsing (read a page as Markdown, extract structured
|
|
198
|
+
* data with AI, list links, scrape elements). Unlike `createBrowserTools`,
|
|
199
|
+
* these need only the `browser` binding — no Durable Object, loader, or
|
|
200
|
+
* sandbox — so they work from any Worker.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```ts
|
|
204
|
+
* import { createQuickActionTools } from "agents/browser/ai";
|
|
205
|
+
*
|
|
206
|
+
* const tools = createQuickActionTools({ browser: this.env.BROWSER });
|
|
207
|
+
* const result = await generateText({ model, tools, messages });
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
function createQuickActionTools(options) {
|
|
211
|
+
const { browser } = options;
|
|
212
|
+
const requestOptions = options.options;
|
|
213
|
+
const enabled = new Set(options.actions ?? DEFAULT_QUICK_ACTION_TOOLS);
|
|
214
|
+
const maxChars = options.maxChars ?? DEFAULT_QUICK_ACTION_MAX_CHARS;
|
|
215
|
+
const tools = {};
|
|
216
|
+
if (enabled.has("markdown")) tools.browser_markdown = tool({
|
|
217
|
+
description: "Load a web page (or render raw HTML) and return its content as Markdown. Best for reading articles, docs, or any page as text.",
|
|
218
|
+
inputSchema: pageInputSchema,
|
|
219
|
+
execute: async (input) => boundResult(await browserMarkdown(browser, toPage(input, requestOptions)), maxChars)
|
|
220
|
+
});
|
|
221
|
+
if (enabled.has("extract")) tools.browser_extract = tool({
|
|
222
|
+
description: "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.",
|
|
223
|
+
inputSchema: z.object({
|
|
224
|
+
url: z.string().url().optional().describe("URL of the page to load"),
|
|
225
|
+
html: z.string().optional().describe("Raw HTML to render instead of loading a URL"),
|
|
226
|
+
prompt: z.string().optional().describe("What to extract, in natural language"),
|
|
227
|
+
schema: z.unknown().optional().describe("Optional JSON Schema describing the desired output")
|
|
228
|
+
}).refine((value) => Boolean(value.url) || Boolean(value.html), { message: "Provide either 'url' or 'html'" }).refine((value) => Boolean(value.prompt) || Boolean(value.schema), { message: "Provide either 'prompt' or 'schema'" }),
|
|
229
|
+
execute: async (input) => boundResult(await browserExtract(browser, {
|
|
230
|
+
...toPage(input, requestOptions),
|
|
231
|
+
prompt: input.prompt,
|
|
232
|
+
response_format: input.schema ? {
|
|
233
|
+
type: "json_schema",
|
|
234
|
+
schema: input.schema
|
|
235
|
+
} : void 0
|
|
236
|
+
}), maxChars)
|
|
237
|
+
});
|
|
238
|
+
if (enabled.has("links")) tools.browser_links = tool({
|
|
239
|
+
description: "Return every link found on a web page (including ones not visible). Useful for discovering pages to follow.",
|
|
240
|
+
inputSchema: pageInputSchema,
|
|
241
|
+
execute: async (input) => boundResult(await browserLinks(browser, toPage(input, requestOptions)), maxChars)
|
|
242
|
+
});
|
|
243
|
+
if (enabled.has("scrape")) tools.browser_scrape = tool({
|
|
244
|
+
description: "Scrape specific elements from a web page by CSS selector. Returns the matched elements' text, HTML, and attributes.",
|
|
245
|
+
inputSchema: z.object({
|
|
246
|
+
url: z.string().url().optional().describe("URL of the page to load"),
|
|
247
|
+
html: z.string().optional().describe("Raw HTML to render instead of loading a URL"),
|
|
248
|
+
selectors: z.array(z.string()).min(1).describe("CSS selectors to extract")
|
|
249
|
+
}).refine((value) => Boolean(value.url) || Boolean(value.html), { message: "Provide either 'url' or 'html'" }),
|
|
250
|
+
execute: async (input) => boundResult(await browserScrape(browser, {
|
|
251
|
+
...toPage(input, requestOptions),
|
|
252
|
+
elements: input.selectors.map((selector) => ({ selector }))
|
|
253
|
+
}), maxChars)
|
|
254
|
+
});
|
|
255
|
+
if (enabled.has("content")) tools.browser_content = tool({
|
|
256
|
+
description: "Load a web page and return its fully rendered HTML (after JavaScript runs). Prefer 'browser_markdown' unless you need the raw HTML.",
|
|
257
|
+
inputSchema: pageInputSchema,
|
|
258
|
+
execute: async (input) => boundResult(await browserContent(browser, toPage(input, requestOptions)), maxChars)
|
|
259
|
+
});
|
|
260
|
+
return tools;
|
|
261
|
+
}
|
|
51
262
|
//#endregion
|
|
52
|
-
export { createBrowserTools };
|
|
263
|
+
export { createBrowserRuntime, createBrowserTools, createQuickActionTools };
|
|
53
264
|
|
|
54
265
|
//# sourceMappingURL=ai.js.map
|