agents 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -9
- package/dist/abortable-C1SpfVoi.js +21 -0
- package/dist/abortable-C1SpfVoi.js.map +1 -0
- package/dist/{agent-routing-0DR0Tk2v.d.ts → agent-routing-QDcchcQP.d.ts} +16 -16
- package/dist/agent-routing.d.ts +1 -1
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-YrATZJu2.d.ts → agent-tools-DHL2XI7u.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/ai-ahruGw7e.d.ts +239 -0
- package/dist/ai-sdk-Bdsf6mSA.js +2444 -0
- package/dist/ai-sdk-Bdsf6mSA.js.map +1 -0
- package/dist/apply-chunks-1FheRb9W.js +99 -0
- package/dist/apply-chunks-1FheRb9W.js.map +1 -0
- package/dist/broadcast-state-CEyI4uAK.js +69 -0
- package/dist/broadcast-state-CEyI4uAK.js.map +1 -0
- package/dist/browser/ai.d.ts +8 -227
- package/dist/browser/ai.js +259 -1
- package/dist/browser/ai.js.map +1 -0
- package/dist/browser/index.d.ts +56 -46
- package/dist/browser/index.js +4 -361
- package/dist/browser/{ai-sdk.d.ts → tools/ai-sdk.d.ts} +7 -7
- package/dist/browser/{ai-sdk.js → tools/ai-sdk.js} +6 -5
- package/dist/browser/tools/ai-sdk.js.map +1 -0
- package/dist/browser/tools/pi.d.ts +111 -0
- package/dist/browser/tools/pi.js +119 -0
- package/dist/browser/tools/pi.js.map +1 -0
- package/dist/browser/{tanstack-ai.d.ts → tools/tanstack-ai.d.ts} +39 -37
- package/dist/browser/{tanstack-ai.js → tools/tanstack-ai.js} +73 -59
- package/dist/browser/tools/tanstack-ai.js.map +1 -0
- package/dist/browser-CEdNlsaD.js +481 -0
- package/dist/browser-CEdNlsaD.js.map +1 -0
- package/dist/{browser-DE3d-RLk.d.ts → browser-D30VlpcA.d.ts} +63 -37
- package/dist/{browser-tool-CQ10e6Kj.js → browser-tool-4iomavs_.js} +198 -62
- package/dist/browser-tool-4iomavs_.js.map +1 -0
- package/dist/{browser-tool-DuNdlwZ9.d.ts → browser-tool-vtrPOV8e.d.ts} +25 -6
- package/dist/{capability-B4WbF81e.js → capability-DBAKc6UZ.js} +1 -3
- package/dist/capability-DBAKc6UZ.js.map +1 -0
- package/dist/{capability-runner-DBAnGr6L.d.ts → capability-runner-BiVUtjqC.d.ts} +9 -7
- package/dist/channel-Bak_6zDP.d.ts +333 -0
- package/dist/chat/index.d.ts +11 -9
- package/dist/chat/index.js +5 -194
- package/dist/chat/index.js.map +1 -1
- package/dist/chat/react.d.ts +2 -4
- package/dist/chat/react.js +3 -1
- package/dist/chat/react.js.map +1 -1
- package/dist/chat-sdk/index.d.ts +1 -1
- package/dist/chat-sdk/index.js +1 -1
- package/dist/cli.js +144 -0
- package/dist/{client-je3koD9Z.d.ts → client-BGIQKJhX.d.ts} +2 -2
- package/dist/{client-fyQrLGkD.js → client-BnYbNT3z.js} +29 -5
- package/dist/client-BnYbNT3z.js.map +1 -0
- package/dist/client-tools-aIBO0Fk7.d.ts +53 -0
- package/dist/client.d.ts +1 -1
- package/dist/{connector-58XDGvc3.js → connector-CtZylXdk.js} +3 -603
- package/dist/connector-CtZylXdk.js.map +1 -0
- package/dist/{connector-Cl-VqPmA.d.ts → connector-DEXzVoaY.d.ts} +9 -374
- package/dist/conversations-FjHDRZyD.d.ts +192 -0
- package/dist/{current-agent-vAk_5JMt.d.ts → current-agent-CKgT5d1O.d.ts} +3 -5
- package/dist/current-agent-DhoDkSnH.js.map +1 -1
- package/dist/daemon-core-Buubj-y1.js +481 -0
- package/dist/daemon-core-Buubj-y1.js.map +1 -0
- package/dist/daemon-core-CbohVPAu.d.ts +132 -0
- package/dist/{do-oauth-client-provider-Tmf1vgKz.d.ts → do-oauth-client-provider-DfsUcpc3.d.ts} +7 -1
- package/dist/{durable-object-lifecycle-HhgOMWq9.d.ts → durable-object-lifecycle-DOI_bzCH.d.ts} +2 -2
- package/dist/{channels/email.d.ts → experimental/channels/email/index.d.ts} +25 -12
- package/dist/{channels/email.js → experimental/channels/email/index.js} +13 -35
- package/dist/experimental/channels/email/index.js.map +1 -0
- package/dist/experimental/channels/index.d.ts +270 -0
- package/dist/experimental/channels/index.js +1186 -0
- package/dist/experimental/channels/index.js.map +1 -0
- package/dist/{channels/slack.d.ts → experimental/channels/slack/index.d.ts} +19 -9
- package/dist/experimental/channels/slack/index.js +267 -0
- package/dist/experimental/channels/slack/index.js.map +1 -0
- package/dist/{channels/telegram.d.ts → experimental/channels/telegram/index.d.ts} +19 -9
- package/dist/experimental/channels/telegram/index.js +198 -0
- package/dist/experimental/channels/telegram/index.js.map +1 -0
- package/dist/experimental/channels/web/ai-sdk.d.ts +55 -0
- package/dist/experimental/channels/web/ai-sdk.js +266 -0
- package/dist/experimental/channels/web/ai-sdk.js.map +1 -0
- package/dist/experimental/channels/web/client.d.ts +97 -0
- package/dist/experimental/channels/web/client.js +349 -0
- package/dist/experimental/channels/web/client.js.map +1 -0
- package/dist/experimental/channels/web/index.d.ts +189 -0
- package/dist/experimental/channels/web/index.js +332 -0
- package/dist/experimental/channels/web/index.js.map +1 -0
- package/dist/gateway-BFO6vRDn.d.ts +100 -0
- package/dist/handle-zAzh0UW2.d.ts +460 -0
- package/dist/harness/ai-sdk/index.d.ts +175 -0
- package/dist/harness/ai-sdk/index.js +605 -0
- package/dist/harness/ai-sdk/index.js.map +1 -0
- package/dist/harness/container/daemon/index.d.ts +76 -0
- package/dist/harness/container/daemon/index.js +3 -0
- package/dist/harness/container/index.d.ts +740 -0
- package/dist/harness/container/index.js +2152 -0
- package/dist/harness/container/index.js.map +1 -0
- package/dist/harness/container/runtime/index.d.ts +144 -0
- package/dist/harness/container/runtime/index.js +1082 -0
- package/dist/harness/container/runtime/index.js.map +1 -0
- package/dist/harness/opencode/index.d.ts +369 -0
- package/dist/harness/opencode/index.js +1072 -0
- package/dist/harness/opencode/index.js.map +1 -0
- package/dist/harness/pi/index.d.ts +3 -2
- package/dist/harness/pi/index.js +3 -3
- package/dist/harness/store/index.d.ts +24 -0
- package/dist/harness/store/index.js +2 -0
- package/dist/harness/think/index.d.ts +821 -0
- package/dist/harness/think/index.js +2721 -0
- package/dist/harness/think/index.js.map +1 -0
- package/dist/harness-B6B9S3rb.d.ts +203 -0
- package/dist/{images-iiTDSyRu.js → images-Ce9SCu3X.js} +2 -248
- package/dist/images-Ce9SCu3X.js.map +1 -0
- package/dist/{index-BreL0YrQ.d.ts → index-BEL3ZV-s.d.ts} +2 -6
- package/dist/index-CBt8oRJt.d.ts +198 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +2 -2
- package/dist/ingress-EFbrS547.js +9 -0
- package/dist/ingress-EFbrS547.js.map +1 -0
- package/dist/input-schema-BQykTEp_.js +20 -0
- package/dist/input-schema-BQykTEp_.js.map +1 -0
- package/dist/input-schema-D2QAtHZH.js +23 -0
- package/dist/input-schema-D2QAtHZH.js.map +1 -0
- package/dist/internal-kmw70xwR.js +46 -0
- package/dist/internal-kmw70xwR.js.map +1 -0
- package/dist/internal_context.d.ts +1 -1
- package/dist/lifecycle/index.d.ts +3 -3
- package/dist/lifecycle/index.js +2 -2
- package/dist/{lifecycle-CFu6OV03.js → lifecycle-DGorpAmA.js} +2 -4
- package/dist/lifecycle-DGorpAmA.js.map +1 -0
- package/dist/mcp/client/do-oauth-client-provider.d.ts +1 -1
- package/dist/mcp/client/do-oauth-client-provider.js +9 -0
- package/dist/mcp/client/do-oauth-client-provider.js.map +1 -1
- package/dist/mcp/client/index.d.ts +1 -1
- package/dist/mcp/client/index.js +1 -1
- package/dist/mcp/client/x402.d.ts +35 -4
- package/dist/mcp/client/x402.js +24 -3
- package/dist/mcp/client/x402.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +2 -2
- package/dist/models/ai-sdk/index.d.ts +16 -14
- package/dist/models/ai-sdk/index.js +1 -2442
- package/dist/models/opencode/index.d.ts +65 -0
- package/dist/models/opencode/index.js +285 -0
- package/dist/models/opencode/index.js.map +1 -0
- package/dist/models/pi-ai/index.d.ts +9 -7
- package/dist/models/pi-ai/index.js +2 -1
- package/dist/models/pi-ai/index.js.map +1 -1
- package/dist/options-CiIsJHXR.d.ts +130 -0
- package/dist/protocol-BEgrJYC5.d.ts +331 -0
- package/dist/protocol-CukuI73M.d.ts +386 -0
- package/dist/protocol-cOklVBBD.js +227 -0
- package/dist/protocol-cOklVBBD.js.map +1 -0
- package/dist/{protocol-kHsr-f0X.js → protocol-eXeJxhgu.js} +2 -67
- package/dist/protocol-eXeJxhgu.js.map +1 -0
- package/dist/protocol-y2sSY584.js +148 -0
- package/dist/protocol-y2sSY584.js.map +1 -0
- package/dist/queue/index.d.ts +1 -1
- package/dist/queue/index.js +1 -1
- package/dist/{queue-BB-zfIYF.js → queue-CcIjVYTE.js} +2 -2
- package/dist/{queue-BB-zfIYF.js.map → queue-CcIjVYTE.js.map} +1 -1
- package/dist/react.d.ts +2 -2
- package/dist/routing/index.d.ts +2 -2
- package/dist/routing/index.js +1 -1
- package/dist/{scheduler-RdACNXDP.d.ts → scheduler-BCLESHSC.d.ts} +2 -12
- package/dist/{scheduler-DZ3xQfeK.js → scheduler-FIHv2-kJ.js} +2 -4
- package/dist/scheduler-FIHv2-kJ.js.map +1 -0
- package/dist/schedules/index.d.ts +1 -1
- package/dist/schedules/index.js +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/session-store-Do4xkDcf.js +606 -0
- package/dist/session-store-Do4xkDcf.js.map +1 -0
- package/dist/session-store-DoPY12xM.d.ts +383 -0
- package/dist/sessions/index.d.ts +11 -434
- package/dist/sessions/index.js +1 -2271
- package/dist/sessions-_vN5BEZX.js +2272 -0
- package/dist/sessions-_vN5BEZX.js.map +1 -0
- package/dist/settings-C45hDliX.js +253 -0
- package/dist/settings-C45hDliX.js.map +1 -0
- package/dist/{transport-PfFnt-Ld.d.ts → settings-NgGwF7Qt.d.ts} +14 -208
- package/dist/{src-BZeu-SCD.js → src-CQxJFv4l.js} +8 -8
- package/dist/src-CQxJFv4l.js.map +1 -0
- package/dist/stall-watchdog-BpRF2uwG.js +195 -0
- package/dist/stall-watchdog-BpRF2uwG.js.map +1 -0
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.js +1 -3
- package/dist/state/index.js.map +1 -1
- package/dist/store-BKM4Xm9M.d.ts +332 -0
- package/dist/store-CslVzfN7.js +458 -0
- package/dist/store-CslVzfN7.js.map +1 -0
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.js +1 -1
- package/dist/{streams-DW-UCOUc.js → streams-lsHMJhRW.js} +17 -4
- package/dist/streams-lsHMJhRW.js.map +1 -0
- package/dist/{streams-Cmkj9QfW.d.ts → streams-vrCtbUIn.d.ts} +2 -2
- package/dist/sub-routing.d.ts +1 -1
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.js +1 -1
- package/dist/{tasks-68DESxf0.js → tasks-BN_5AWqI.js} +3 -2
- package/dist/tasks-BN_5AWqI.js.map +1 -0
- package/dist/{tasks-9YxYtByh.d.ts → tasks-E89KdwkS.d.ts} +2 -2
- package/dist/tool-CTp72Jb_.d.ts +278 -0
- package/dist/tool-CxKsvxjm.js +1126 -0
- package/dist/tool-CxKsvxjm.js.map +1 -0
- package/dist/tool-DoVberpN.d.ts +301 -0
- package/dist/tool-cQRkwSZZ.js +410 -0
- package/dist/tool-cQRkwSZZ.js.map +1 -0
- package/dist/tool-helpers-O5BDVEAY.js +58 -0
- package/dist/tool-helpers-O5BDVEAY.js.map +1 -0
- package/dist/transport-k2mFrtL8.d.ts +200 -0
- package/dist/turns-DCV3ycDl.js +317 -0
- package/dist/turns-DCV3ycDl.js.map +1 -0
- package/dist/voice/client.js +1 -1
- package/dist/voice/index.d.ts +2 -2
- package/dist/voice/index.js +1 -1
- package/dist/web/fetch/index.d.ts +89 -0
- package/dist/web/fetch/index.js +20 -0
- package/dist/web/fetch/index.js.map +1 -0
- package/dist/web/fetch/tools/ai-sdk.d.ts +80 -0
- package/dist/web/fetch/tools/ai-sdk.js +47 -0
- package/dist/web/fetch/tools/ai-sdk.js.map +1 -0
- package/dist/web/fetch/tools/pi.d.ts +84 -0
- package/dist/web/fetch/tools/pi.js +88 -0
- package/dist/web/fetch/tools/pi.js.map +1 -0
- package/dist/web/fetch/tools/tanstack-ai.d.ts +78 -0
- package/dist/web/fetch/tools/tanstack-ai.js +45 -0
- package/dist/web/fetch/tools/tanstack-ai.js.map +1 -0
- package/dist/web/search/index.d.ts +58 -0
- package/dist/web/search/index.js +2 -0
- package/dist/web/search/tools/ai-sdk.d.ts +77 -0
- package/dist/web/search/tools/ai-sdk.js +46 -0
- package/dist/web/search/tools/ai-sdk.js.map +1 -0
- package/dist/web/search/tools/pi.d.ts +82 -0
- package/dist/web/search/tools/pi.js +89 -0
- package/dist/web/search/tools/pi.js.map +1 -0
- package/dist/web/search/tools/tanstack-ai.d.ts +71 -0
- package/dist/web/search/tools/tanstack-ai.js +46 -0
- package/dist/web/search/tools/tanstack-ai.js.map +1 -0
- package/dist/websockets/index.d.ts +12 -296
- package/dist/websockets/index.js +1 -1
- package/dist/{websockets-Ci-LZFHH.js → websockets-C3zy8YR0.js} +20 -8
- package/dist/websockets-C3zy8YR0.js.map +1 -0
- package/dist/{wire-types-CrjKvDyi.d.ts → wire-types-Cv0iwjk5.d.ts} +3 -51
- package/dist/workflow-types.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/dist/workflows.js +1 -1
- package/docs/browse-the-web.md +29 -1
- package/docs/fetch-the-web.md +276 -0
- package/docs/harnesses/pi.md +25 -0
- package/docs/harnesses/think.md +215 -0
- package/docs/index.md +99 -75
- package/docs/lifecycle.md +42 -3
- package/docs/queue.md +2 -3
- package/docs/scheduling.md +2 -6
- package/docs/search-the-web.md +135 -0
- package/package.json +148 -44
- package/dist/ai-fm7xx1BK.js +0 -312
- package/dist/ai-fm7xx1BK.js.map +0 -1
- package/dist/browser/ai-sdk.js.map +0 -1
- package/dist/browser/index.js.map +0 -1
- package/dist/browser/tanstack-ai.js.map +0 -1
- package/dist/browser-tool-CQ10e6Kj.js.map +0 -1
- package/dist/capability-B4WbF81e.js.map +0 -1
- package/dist/channel-Bnm4S7T2.d.ts +0 -491
- package/dist/channels/ai-sdk.d.ts +0 -46
- package/dist/channels/ai-sdk.js +0 -120
- package/dist/channels/ai-sdk.js.map +0 -1
- package/dist/channels/email.js.map +0 -1
- package/dist/channels/index.d.ts +0 -233
- package/dist/channels/index.js +0 -608
- package/dist/channels/index.js.map +0 -1
- package/dist/channels/slack.js +0 -614
- package/dist/channels/slack.js.map +0 -1
- package/dist/channels/tanstack-ai.d.ts +0 -39
- package/dist/channels/tanstack-ai.js +0 -17
- package/dist/channels/tanstack-ai.js.map +0 -1
- package/dist/channels/telegram.js +0 -427
- package/dist/channels/telegram.js.map +0 -1
- package/dist/channels/voice.d.ts +0 -45
- package/dist/channels/voice.js +0 -122
- package/dist/channels/voice.js.map +0 -1
- package/dist/client-fyQrLGkD.js.map +0 -1
- package/dist/connector-58XDGvc3.js.map +0 -1
- package/dist/images-iiTDSyRu.js.map +0 -1
- package/dist/index-BB0kqhIz.d.ts +0 -101
- package/dist/ingress-BfetZbMO.js +0 -83
- package/dist/ingress-BfetZbMO.js.map +0 -1
- package/dist/internal-CYlgHl1l.js +0 -59
- package/dist/internal-CYlgHl1l.js.map +0 -1
- package/dist/lifecycle-CFu6OV03.js.map +0 -1
- package/dist/models/ai-sdk/index.js.map +0 -1
- package/dist/protocol-kHsr-f0X.js.map +0 -1
- package/dist/scheduler-DZ3xQfeK.js.map +0 -1
- package/dist/sessions/index.js.map +0 -1
- package/dist/src-BZeu-SCD.js.map +0 -1
- package/dist/streams-DW-UCOUc.js.map +0 -1
- package/dist/surface-bZZJqBka.js +0 -17
- package/dist/surface-bZZJqBka.js.map +0 -1
- package/dist/tasks-68DESxf0.js.map +0 -1
- package/dist/tool-schema-CBjGPrsQ.js +0 -31
- package/dist/tool-schema-CBjGPrsQ.js.map +0 -1
- package/dist/websockets-Ci-LZFHH.js.map +0 -1
- package/docs/channels.md +0 -323
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { s as LifecycleCapability } from "./capability-runner-
|
|
1
|
+
import { s as LifecycleCapability } from "./capability-runner-BiVUtjqC.js";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from "./
|
|
3
|
+
O as CdpConnection,
|
|
4
|
+
a as ListableBrowserSessionStore,
|
|
5
|
+
d as BrowserBinding,
|
|
6
|
+
m as BrowserSessionGuardrails,
|
|
7
|
+
s as BrowserLiveView,
|
|
8
|
+
u as LiveViewMode
|
|
9
|
+
} from "./session-store-DoPY12xM.js";
|
|
10
10
|
|
|
11
11
|
//#region src/browser/spec.d.ts
|
|
12
12
|
/**
|
|
@@ -87,6 +87,16 @@ interface CdpSpecSource {
|
|
|
87
87
|
declare function loadCdpSpec(source: CdpSpecSource): Promise<SearchableCdpSpec>;
|
|
88
88
|
//#endregion
|
|
89
89
|
//#region src/browser/browser.d.ts
|
|
90
|
+
/**
|
|
91
|
+
* The scope used when a caller doesn't pick one: every caller that leaves
|
|
92
|
+
* `scope` out shares this one active tab. See {@link BrowserConnectOptions}.
|
|
93
|
+
*/
|
|
94
|
+
declare const DEFAULT_BROWSER_SCOPE = "shared";
|
|
95
|
+
/**
|
|
96
|
+
* Scope records kept per browser. Writing a new one past the cap deletes the
|
|
97
|
+
* least recently used; a scope that comes back afterwards starts fresh.
|
|
98
|
+
*/
|
|
99
|
+
declare const MAX_BROWSER_SCOPES = 100;
|
|
90
100
|
/**
|
|
91
101
|
* Browser Run settings applied every time a browser is created — including
|
|
92
102
|
* when a lost browser is replaced — so options like guardrails survive a
|
|
@@ -136,9 +146,9 @@ interface BrowserOptions {
|
|
|
136
146
|
* Where the browser's record lives. Defaults to a
|
|
137
147
|
* {@link DurableBrowserSessionStore} over the host object's storage, which
|
|
138
148
|
* requires installing the `Browser` with `Lifecycle.use()`. Passing a store
|
|
139
|
-
* lets the `Browser` work without Lifecycle.
|
|
149
|
+
* lets the `Browser` work without Lifecycle. It must implement `list`.
|
|
140
150
|
*/
|
|
141
|
-
store?:
|
|
151
|
+
store?: ListableBrowserSessionStore;
|
|
142
152
|
/** Default CDP command timeout for {@link Browser.connect}. */
|
|
143
153
|
timeoutMs?: number;
|
|
144
154
|
/**
|
|
@@ -163,32 +173,45 @@ interface ResolvedBrowser {
|
|
|
163
173
|
restarted: boolean;
|
|
164
174
|
createdAt: number;
|
|
165
175
|
updatedAt: number;
|
|
176
|
+
}
|
|
177
|
+
interface BrowserConnectOptions {
|
|
166
178
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
179
|
+
* Who is driving. Connections with the same scope share an active tab, and
|
|
180
|
+
* each scope keeps its own, so two conversations on one browser don't
|
|
181
|
+
* drive each other's page. Cookies, logins, and the tabs themselves are
|
|
182
|
+
* shared by every scope: a scope splits "which tab is mine", not the
|
|
183
|
+
* browser. Defaults to {@link DEFAULT_BROWSER_SCOPE}.
|
|
170
184
|
*/
|
|
171
|
-
|
|
185
|
+
scope?: string;
|
|
172
186
|
}
|
|
173
187
|
interface BrowserConnection {
|
|
174
188
|
name: string;
|
|
175
189
|
sessionId: string;
|
|
190
|
+
/** The scope this connection works in; see {@link BrowserConnectOptions}. */
|
|
191
|
+
scope: string;
|
|
176
192
|
/**
|
|
177
|
-
* `true` when
|
|
178
|
-
*
|
|
179
|
-
*
|
|
193
|
+
* `true` when this scope worked in an earlier browser that has since been
|
|
194
|
+
* replaced, whichever scope's connection replaced it. Its tabs and page
|
|
195
|
+
* state are gone; surface this loudly to the model. `false` on a scope's
|
|
196
|
+
* first connection, even one that replaced a lost browser: the scope had
|
|
197
|
+
* nothing to lose. This is per scope, not a browser-wide signal.
|
|
180
198
|
*/
|
|
181
199
|
restarted: boolean;
|
|
182
|
-
/**
|
|
200
|
+
/**
|
|
201
|
+
* The tab this scope last worked in, when it recorded one in this
|
|
202
|
+
* browser.
|
|
203
|
+
*/
|
|
183
204
|
activeTargetId?: string;
|
|
184
205
|
/** Closing this connection does NOT close the browser. */
|
|
185
206
|
cdp: CdpConnection;
|
|
186
207
|
/**
|
|
187
|
-
* Record the tab
|
|
208
|
+
* Record the tab this scope is working in (or clear it with `undefined`).
|
|
188
209
|
* Never resurrects: returns `false` when the browser was closed or
|
|
189
210
|
* replaced since this connection resolved it.
|
|
190
211
|
*/
|
|
191
212
|
setActiveTarget(targetId: string | undefined): Promise<boolean>;
|
|
213
|
+
/** The tabs other scopes are working in, in this browser. */
|
|
214
|
+
targetsInOtherScopes(): Promise<Set<string>>;
|
|
192
215
|
/**
|
|
193
216
|
* The Chrome DevTools Protocol description this browser serves, read from
|
|
194
217
|
* the browser itself (cached per binding).
|
|
@@ -224,17 +247,17 @@ declare class Browser extends LifecycleCapability {
|
|
|
224
247
|
*/
|
|
225
248
|
resolve(): Promise<ResolvedBrowser>;
|
|
226
249
|
/**
|
|
227
|
-
* Resolve the browser and open a CDP connection to it
|
|
228
|
-
*
|
|
250
|
+
* Resolve the browser and open a CDP connection to it for one scope (see
|
|
251
|
+
* {@link BrowserConnectOptions.scope}). Commands sent over the connection
|
|
252
|
+
* refresh the record's `updatedAt` (throttled to
|
|
229
253
|
* {@link SESSION_TOUCH_INTERVAL_MS}), so hosts can tell an actively used
|
|
230
254
|
* browser from one the platform has likely reclaimed.
|
|
231
255
|
*
|
|
232
256
|
* If the browser expires between the liveness probe and the WebSocket
|
|
233
257
|
* upgrade, the record is retired and the browser resolved once more, so
|
|
234
|
-
* the caller gets a fresh browser
|
|
235
|
-
* error.
|
|
258
|
+
* the caller gets a fresh browser instead of an error.
|
|
236
259
|
*/
|
|
237
|
-
connect(): Promise<BrowserConnection>;
|
|
260
|
+
connect(options?: BrowserConnectOptions): Promise<BrowserConnection>;
|
|
238
261
|
/**
|
|
239
262
|
* Close the browser: retire the record (so the next resolve reports
|
|
240
263
|
* `restarted: true`) and delete its Browser Run session. Returns `false`
|
|
@@ -258,18 +281,21 @@ declare class Browser extends LifecycleCapability {
|
|
|
258
281
|
}
|
|
259
282
|
//#endregion
|
|
260
283
|
export {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
284
|
+
BrowserProvider as a,
|
|
285
|
+
DEFAULT_BROWSER_SCOPE as c,
|
|
286
|
+
browserRun as d,
|
|
287
|
+
CdpField as f,
|
|
288
|
+
loadCdpSpec as g,
|
|
289
|
+
SearchableCdpSpec as h,
|
|
290
|
+
BrowserOptions as i,
|
|
291
|
+
MAX_BROWSER_SCOPES as l,
|
|
292
|
+
CdpSpecSource as m,
|
|
293
|
+
BrowserConnectOptions as n,
|
|
294
|
+
BrowserRunOptions as o,
|
|
295
|
+
CdpItems as p,
|
|
296
|
+
BrowserConnection as r,
|
|
297
|
+
BrowserRunProvider as s,
|
|
272
298
|
Browser as t,
|
|
273
|
-
|
|
299
|
+
ResolvedBrowser as u
|
|
274
300
|
};
|
|
275
|
-
//# sourceMappingURL=browser-
|
|
301
|
+
//# sourceMappingURL=browser-D30VlpcA.d.ts.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
|
|
2
2
|
import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
3
|
+
import { s as validateConnectorArgs, v as CdpProtocolError } from "./session-store-Do4xkDcf.js";
|
|
4
|
+
import { i as transformBrowserResult, r as resolveCtx } from "./tool-helpers-O5BDVEAY.js";
|
|
5
|
+
import "./browser-CEdNlsaD.js";
|
|
6
|
+
import { CodemodeConnector, DynamicWorkerExecutor, MAX_DURABLE_VALUE_BYTES, createCodemodeRuntime } from "@cloudflare/codemode";
|
|
6
7
|
/**
|
|
7
8
|
* `cdp.attachToTarget` returns `{ sessionId: "target:<targetId>" }` — a
|
|
8
9
|
* stable handle rather than a connection-scoped CDP session id, so replayed
|
|
@@ -11,6 +12,18 @@ import { CodemodeConnector, DynamicWorkerExecutor, createCodemodeRuntime } from
|
|
|
11
12
|
const ATTACH_HANDLE_PREFIX = "target:";
|
|
12
13
|
/** Chrome's JSON-RPC code for a CDP session id it doesn't know. */
|
|
13
14
|
const CDP_SESSION_NOT_FOUND = -32001;
|
|
15
|
+
/**
|
|
16
|
+
* Codemode records every `send` result for replay and fails the run when one
|
|
17
|
+
* is over {@link MAX_DURABLE_VALUE_BYTES}, telling the model to write to a
|
|
18
|
+
* file, which this sandbox can't. A full-page screenshot is the usual
|
|
19
|
+
* culprit, so say how to take a smaller one instead.
|
|
20
|
+
*/
|
|
21
|
+
function assertScreenshotFits(result) {
|
|
22
|
+
const size = JSON.stringify(result ?? null).length;
|
|
23
|
+
if (size <= MAX_DURABLE_VALUE_BYTES) return;
|
|
24
|
+
const megabytes = (size / 1e6).toFixed(1);
|
|
25
|
+
throw new Error(`The screenshot result is ${megabytes} MB, over the 1 MB limit on a cdp.send result. Capture just the viewport (no captureBeyondViewport or clip larger than the window), or pass format: "jpeg" with quality: 60.`);
|
|
26
|
+
}
|
|
14
27
|
/** {@link BrowserSessionConnector} `#liveParams`: nothing to detach. */
|
|
15
28
|
const DETACHED = Symbol("detached");
|
|
16
29
|
/** Reports awaiting their tool call; bounded in case a caller never reads. */
|
|
@@ -24,20 +37,25 @@ const BROWSER_LIFETIME_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
24
37
|
"Browser.crash",
|
|
25
38
|
"Browser.crashGpuProcess"
|
|
26
39
|
]);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"Page
|
|
37
|
-
"
|
|
38
|
-
"
|
|
40
|
+
/**
|
|
41
|
+
* How to use the `cdp` connector, one rule per line. `codemode.describe("cdp")`
|
|
42
|
+
* returns these, and `browserTool` puts them in its description. Each rule
|
|
43
|
+
* fixes a mistake models make with CDP, or states something about this
|
|
44
|
+
* browser they can't know; leave out what a model knows already.
|
|
45
|
+
*/
|
|
46
|
+
const BROWSER_INSTRUCTIONS = [
|
|
47
|
+
"The browser persists between runs: tabs, cookies, and logins are still there next time. You never start or close it.",
|
|
48
|
+
"If the browser was replaced (idle timeout, crash), the result says restarted: true and earlier tabs and logins are gone. Before an action that matters (submitting a form, a purchase), check you're on the page you expect.",
|
|
49
|
+
"Page-scoped commands (Page.*, Runtime.*, DOM.*, Input.*, Network.*, Emulation.*) need sessionId: \"active\", your tab, which is remembered between runs. Browser.* and Target.* commands take no sessionId.",
|
|
50
|
+
"Other open tabs (Target.getTargets) may belong to other conversations using this browser: don't close, navigate, or attach to a tab you didn't open unless the user asks.",
|
|
51
|
+
"Target.createTarget opens a tab and makes it active. To switch to another open tab, call cdp.attachToTarget({ targetId }); the sessionId it returns keeps working in later runs, while one from a raw Target.attachToTarget only works in the current run.",
|
|
52
|
+
"Tabs a page opens itself (popups, target=_blank links) don't become active; the result lists them as newTabs.",
|
|
53
|
+
"Runtime.evaluate: pass returnByValue: true, or objects come back as a remote reference with no value, and awaitPromise: true for async expressions. The value is at result.value. A thrown error doesn't reject: check exceptionDetails.",
|
|
54
|
+
"Page.navigate returns before the page loads and doesn't throw when it fails: check errorText, then poll document.readyState with Runtime.evaluate until it is 'complete'.",
|
|
55
|
+
"Pick out what you need inside Runtime.evaluate and return only that. Results over about 24,000 characters are cut short, and a single cdp.send result over 1 MB (a full-page screenshot, say) fails the run."
|
|
39
56
|
].join("\n");
|
|
40
57
|
var _browser = /* @__PURE__ */ new WeakMap();
|
|
58
|
+
var _scope = /* @__PURE__ */ new WeakMap();
|
|
41
59
|
var _states = /* @__PURE__ */ new WeakMap();
|
|
42
60
|
var _connecting = /* @__PURE__ */ new WeakMap();
|
|
43
61
|
var _reports = /* @__PURE__ */ new WeakMap();
|
|
@@ -49,8 +67,10 @@ var _BrowserSessionConnector_brand = /* @__PURE__ */ new WeakSet();
|
|
|
49
67
|
* The model never manages sessions: every execution reattaches to the
|
|
50
68
|
* browser (or gets a replacement, reported as `restarted`), and
|
|
51
69
|
* `sessionId: "active"` addresses the tab it last worked in. The active tab
|
|
52
|
-
* is stored
|
|
53
|
-
* long as the tab does
|
|
70
|
+
* is stored per scope (see {@link BrowserSessionConnectorOptions.scope}), so
|
|
71
|
+
* it survives between executions for as long as the tab does, and one
|
|
72
|
+
* scope's executions never land in another scope's tab unless the model
|
|
73
|
+
* attaches to it.
|
|
54
74
|
*
|
|
55
75
|
* The CDP socket is per pass: opened on the first call, closed when the pass
|
|
56
76
|
* ends. The browser itself outlives the execution.
|
|
@@ -60,16 +80,18 @@ var BrowserSessionConnector = class extends CodemodeConnector {
|
|
|
60
80
|
super(ctx, {});
|
|
61
81
|
_classPrivateMethodInitSpec(this, _BrowserSessionConnector_brand);
|
|
62
82
|
_classPrivateFieldInitSpec(this, _browser, void 0);
|
|
83
|
+
_classPrivateFieldInitSpec(this, _scope, void 0);
|
|
63
84
|
_classPrivateFieldInitSpec(this, _states, /* @__PURE__ */ new Map());
|
|
64
85
|
_classPrivateFieldInitSpec(this, _connecting, /* @__PURE__ */ new Map());
|
|
65
86
|
_classPrivateFieldInitSpec(this, _reports, /* @__PURE__ */ new Map());
|
|
66
87
|
_classPrivateFieldSet2(_browser, this, options.browser);
|
|
88
|
+
_classPrivateFieldSet2(_scope, this, options.scope);
|
|
67
89
|
}
|
|
68
90
|
name() {
|
|
69
91
|
return "cdp";
|
|
70
92
|
}
|
|
71
93
|
instructions() {
|
|
72
|
-
return
|
|
94
|
+
return BROWSER_INSTRUCTIONS;
|
|
73
95
|
}
|
|
74
96
|
tool(name, tool) {
|
|
75
97
|
return validateConnectorArgs(this.name(), name, tool);
|
|
@@ -117,6 +139,7 @@ var BrowserSessionConnector = class extends CodemodeConnector {
|
|
|
117
139
|
throw await _assertClassBrand(_BrowserSessionConnector_brand, this, _teach).call(this, state, error, method, sessionId);
|
|
118
140
|
}
|
|
119
141
|
_assertClassBrand(_BrowserSessionConnector_brand, this, _observe).call(this, state, method, liveParams, result);
|
|
142
|
+
if (method === "Page.captureScreenshot") assertScreenshotFits(result);
|
|
120
143
|
return result;
|
|
121
144
|
}
|
|
122
145
|
},
|
|
@@ -190,8 +213,9 @@ var BrowserSessionConnector = class extends CodemodeConnector {
|
|
|
190
213
|
};
|
|
191
214
|
}
|
|
192
215
|
/**
|
|
193
|
-
* The pass is over: note tabs the page opened, save the active
|
|
194
|
-
*
|
|
216
|
+
* The pass is over: note tabs the page opened, save the scope's active
|
|
217
|
+
* tab, note whether another scope shares it, and drop the socket. The
|
|
218
|
+
* browser stays alive.
|
|
195
219
|
*/
|
|
196
220
|
async onPassEnd(executionId) {
|
|
197
221
|
const state = _classPrivateFieldGet2(_states, this).get(executionId);
|
|
@@ -199,7 +223,8 @@ var BrowserSessionConnector = class extends CodemodeConnector {
|
|
|
199
223
|
_classPrivateFieldGet2(_states, this).delete(executionId);
|
|
200
224
|
try {
|
|
201
225
|
const open = await _assertClassBrand(_BrowserSessionConnector_brand, this, _recordNewTabs).call(this, executionId, state);
|
|
202
|
-
await _assertClassBrand(_BrowserSessionConnector_brand, this, _saveActiveTarget).call(this, state, open);
|
|
226
|
+
const active = await _assertClassBrand(_BrowserSessionConnector_brand, this, _saveActiveTarget).call(this, state, open);
|
|
227
|
+
if (active && state.activeResolved) await _assertClassBrand(_BrowserSessionConnector_brand, this, _recordSharedTab).call(this, state, active);
|
|
203
228
|
} finally {
|
|
204
229
|
state.connected.cdp.disconnect();
|
|
205
230
|
}
|
|
@@ -242,7 +267,7 @@ function _state(executionId) {
|
|
|
242
267
|
return promise;
|
|
243
268
|
}
|
|
244
269
|
async function _connect(executionId) {
|
|
245
|
-
const connected = await _classPrivateFieldGet2(_browser, this).connect();
|
|
270
|
+
const connected = await _classPrivateFieldGet2(_browser, this).connect(_classPrivateFieldGet2(_scope, this) === void 0 ? void 0 : { scope: _classPrivateFieldGet2(_scope, this) });
|
|
246
271
|
let initialPages;
|
|
247
272
|
try {
|
|
248
273
|
initialPages = await _assertClassBrand(_BrowserSessionConnector_brand, this, _pages).call(this, connected.cdp);
|
|
@@ -251,10 +276,13 @@ async function _connect(executionId) {
|
|
|
251
276
|
throw error;
|
|
252
277
|
}
|
|
253
278
|
const state = {
|
|
279
|
+
executionId,
|
|
254
280
|
connected,
|
|
255
281
|
attached: /* @__PURE__ */ new Map(),
|
|
282
|
+
workedIn: /* @__PURE__ */ new Set(),
|
|
256
283
|
initialPages: new Set(initialPages.map((page) => page.targetId)),
|
|
257
|
-
activeResolved: false
|
|
284
|
+
activeResolved: false,
|
|
285
|
+
closed: /* @__PURE__ */ new Set()
|
|
258
286
|
};
|
|
259
287
|
_classPrivateFieldGet2(_states, this).set(executionId, state);
|
|
260
288
|
_assertClassBrand(_BrowserSessionConnector_brand, this, _report).call(this, executionId, connected.restarted);
|
|
@@ -265,7 +293,9 @@ function _report(executionId, restarted) {
|
|
|
265
293
|
if (!report) {
|
|
266
294
|
report = {
|
|
267
295
|
restarted,
|
|
268
|
-
newTabs: []
|
|
296
|
+
newTabs: [],
|
|
297
|
+
tabClosed: false,
|
|
298
|
+
tabShared: false
|
|
269
299
|
};
|
|
270
300
|
_classPrivateFieldGet2(_reports, this).set(executionId, report);
|
|
271
301
|
if (_classPrivateFieldGet2(_reports, this).size > MAX_PENDING_REPORTS) {
|
|
@@ -292,7 +322,18 @@ async function _recordNewTabs(executionId, state) {
|
|
|
292
322
|
}
|
|
293
323
|
const report = _assertClassBrand(_BrowserSessionConnector_brand, this, _report).call(this, executionId, state.connected.restarted);
|
|
294
324
|
const opened = new Set(report.newTabs.map((tab) => tab.targetId));
|
|
295
|
-
|
|
325
|
+
let grew = true;
|
|
326
|
+
while (grew) {
|
|
327
|
+
grew = false;
|
|
328
|
+
for (const page of pages) {
|
|
329
|
+
const opener = page.openerId;
|
|
330
|
+
if (!opener || opened.has(page.targetId) || state.initialPages.has(page.targetId)) continue;
|
|
331
|
+
if (state.workedIn.has(opener) || opened.has(opener)) {
|
|
332
|
+
opened.add(page.targetId);
|
|
333
|
+
grew = true;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
296
337
|
report.newTabs = pages.filter((page) => opened.has(page.targetId)).map(({ targetId, url, title }) => ({
|
|
297
338
|
targetId,
|
|
298
339
|
url,
|
|
@@ -301,20 +342,31 @@ async function _recordNewTabs(executionId, state) {
|
|
|
301
342
|
return new Set(pages.map((page) => page.targetId));
|
|
302
343
|
}
|
|
303
344
|
/**
|
|
304
|
-
* Save the tab this pass settled on, forgetting one that has since closed
|
|
305
|
-
* Without the list of open tabs, save the choice
|
|
306
|
-
* execution checks the stored tab is still open
|
|
345
|
+
* Save the tab this pass settled on, forgetting one that has since closed,
|
|
346
|
+
* and return it. Without the list of open tabs, save the choice
|
|
347
|
+
* unchecked: the next execution checks the stored tab is still open
|
|
348
|
+
* before using it.
|
|
307
349
|
*/
|
|
308
350
|
async function _saveActiveTarget(state, open) {
|
|
309
351
|
const stored = state.connected.activeTargetId;
|
|
352
|
+
if (!state.activeResolved && stored && open && !open.has(stored) && !state.closed.has(stored)) _assertClassBrand(_BrowserSessionConnector_brand, this, _report).call(this, state.executionId, state.connected.restarted).tabClosed = true;
|
|
310
353
|
const candidate = state.activeResolved ? state.activeTargetId : stored;
|
|
311
354
|
const active = candidate && (!open || open.has(candidate)) ? candidate : void 0;
|
|
312
|
-
if (active === stored) return;
|
|
355
|
+
if (active === stored) return active;
|
|
313
356
|
try {
|
|
314
357
|
await state.connected.setActiveTarget(active);
|
|
315
358
|
} catch (error) {
|
|
316
359
|
_assertClassBrand(_BrowserSessionConnector_brand, this, _warn).call(this, "save the active tab", error);
|
|
317
360
|
}
|
|
361
|
+
return active;
|
|
362
|
+
}
|
|
363
|
+
/** Report when another scope is working in this pass's tab too. */
|
|
364
|
+
async function _recordSharedTab(state, active) {
|
|
365
|
+
try {
|
|
366
|
+
if ((await state.connected.targetsInOtherScopes()).has(active)) _assertClassBrand(_BrowserSessionConnector_brand, this, _report).call(this, state.executionId, state.connected.restarted).tabShared = true;
|
|
367
|
+
} catch (error) {
|
|
368
|
+
_assertClassBrand(_BrowserSessionConnector_brand, this, _warn).call(this, "check whether the active tab is shared", error);
|
|
369
|
+
}
|
|
318
370
|
}
|
|
319
371
|
function _warn(action, error) {
|
|
320
372
|
console.warn(`[agents/browser] Failed to ${action} for browser "${_classPrivateFieldGet2(_browser, this).name}"`, error);
|
|
@@ -328,17 +380,18 @@ async function _resolveSessionId(state, sessionId) {
|
|
|
328
380
|
return sessionId;
|
|
329
381
|
}
|
|
330
382
|
/**
|
|
331
|
-
* Decide which tab `"active"` means, once per pass: the stored tab
|
|
332
|
-
* is still open, else
|
|
333
|
-
*
|
|
383
|
+
* Decide which tab `"active"` means, once per pass: the scope's stored tab
|
|
384
|
+
* if it is still open, else a new blank tab. Never a tab the scope didn't
|
|
385
|
+
* open, even a blank one: it may be another scope's, or a popup.
|
|
334
386
|
*/
|
|
335
387
|
async function _activeTarget(state) {
|
|
336
388
|
if (state.activeTargetId) return state.activeTargetId;
|
|
337
|
-
const
|
|
338
|
-
const
|
|
389
|
+
const { connected } = state;
|
|
390
|
+
const pages = await _assertClassBrand(_BrowserSessionConnector_brand, this, _pages).call(this, connected.cdp);
|
|
391
|
+
const stored = connected.activeTargetId;
|
|
339
392
|
let targetId = pages.find((page) => page.targetId === stored)?.targetId;
|
|
340
|
-
if (!targetId &&
|
|
341
|
-
targetId
|
|
393
|
+
if (!targetId && stored && !state.closed.has(stored)) _assertClassBrand(_BrowserSessionConnector_brand, this, _report).call(this, state.executionId, connected.restarted).tabClosed = true;
|
|
394
|
+
if (!targetId) targetId = (await connected.cdp.send("Target.createTarget", { url: "about:blank" })).targetId;
|
|
342
395
|
_assertClassBrand(_BrowserSessionConnector_brand, this, _setActive).call(this, state, targetId);
|
|
343
396
|
return targetId;
|
|
344
397
|
}
|
|
@@ -351,6 +404,7 @@ async function _attach(state, targetId, timeoutMs) {
|
|
|
351
404
|
if (existing) return existing;
|
|
352
405
|
const live = await state.connected.cdp.attachToTarget(targetId, { timeoutMs });
|
|
353
406
|
state.attached.set(targetId, live);
|
|
407
|
+
state.workedIn.add(targetId);
|
|
354
408
|
return live;
|
|
355
409
|
}
|
|
356
410
|
/** Track tab changes the model makes through raw Target commands. */
|
|
@@ -359,9 +413,12 @@ function _observe(state, method, params, result) {
|
|
|
359
413
|
if (method === "Target.createTarget") {
|
|
360
414
|
const created = result?.targetId;
|
|
361
415
|
if (typeof created === "string") _assertClassBrand(_BrowserSessionConnector_brand, this, _setActive).call(this, state, created);
|
|
362
|
-
} else if (method === "Target.attachToTarget" && targetId)
|
|
363
|
-
|
|
416
|
+
} else if (method === "Target.attachToTarget" && targetId) {
|
|
417
|
+
_assertClassBrand(_BrowserSessionConnector_brand, this, _setActive).call(this, state, targetId);
|
|
418
|
+
state.workedIn.add(targetId);
|
|
419
|
+
} else if (method === "Target.closeTarget" && targetId) {
|
|
364
420
|
state.attached.delete(targetId);
|
|
421
|
+
state.closed.add(targetId);
|
|
365
422
|
if (state.activeTargetId === targetId) state.activeTargetId = void 0;
|
|
366
423
|
} else if (method === "Target.detachFromTarget") {
|
|
367
424
|
for (const [target, live] of state.attached) if (target === targetId || live === params?.sessionId) state.attached.delete(target);
|
|
@@ -415,11 +472,17 @@ function targetOfHandle(handle) {
|
|
|
415
472
|
//#endregion
|
|
416
473
|
//#region src/browser/browser-tool.ts
|
|
417
474
|
/**
|
|
418
|
-
* The harness-neutral core of `browserTool`, shared by the
|
|
419
|
-
* (`agents/browser/ai-sdk
|
|
420
|
-
*
|
|
475
|
+
* The harness-neutral core of `browserTool`, shared by the adapters in
|
|
476
|
+
* `tools/` (`agents/browser/ai-sdk`, `agents/browser/tanstack-ai`,
|
|
477
|
+
* `agents/browser/pi`).
|
|
478
|
+
* Internal — not an entry point.
|
|
421
479
|
*/
|
|
480
|
+
const DEFAULT_TIMEOUT_MS = 6e4;
|
|
422
481
|
const RESTARTED_NOTICE = "The browser was restarted before this run (it expired or was closed): earlier tabs, logins, and page state are gone. Your code ran in a fresh browser — navigate again before relying on page state.";
|
|
482
|
+
const TAB_CLOSED_NOTICE = "The tab you were working in was closed (by another conversation using this browser, or a person). `sessionId: \"active\"` now opens a blank tab — navigate again before relying on page state.";
|
|
483
|
+
const TAB_SHARED_NOTICE = "Another conversation using this browser is also working in your tab, so its page may change between your runs. Open a tab of your own with Target.createTarget if you need one.";
|
|
484
|
+
/** Scopes whose runtime and connector stay built; older ones are rebuilt. */
|
|
485
|
+
const MAX_CACHED_SCOPES = 32;
|
|
423
486
|
/**
|
|
424
487
|
* A codemode runtime name per browser. Browser names are host-chosen and
|
|
425
488
|
* unrestricted; runtime names allow only `[a-zA-Z0-9_.-]`, so anything else
|
|
@@ -428,15 +491,35 @@ const RESTARTED_NOTICE = "The browser was restarted before this run (it expired
|
|
|
428
491
|
function browserRuntimeName(name) {
|
|
429
492
|
return `browser-tool_${name.replace(/[^a-zA-Z0-9_-]/g, (char) => `.${char.codePointAt(0)?.toString(16)}.`)}`;
|
|
430
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* The latest run queued per browser and scope, so runs in one scope go one
|
|
496
|
+
* at a time, even from tools built separately (one per turn, say). Per
|
|
497
|
+
* isolate, which is per Durable Object.
|
|
498
|
+
*/
|
|
499
|
+
const runQueues = /* @__PURE__ */ new WeakMap();
|
|
500
|
+
function queued(browser, scope, run) {
|
|
501
|
+
let queues = runQueues.get(browser);
|
|
502
|
+
if (!queues) runQueues.set(browser, queues = /* @__PURE__ */ new Map());
|
|
503
|
+
const next = (queues.get(scope) ?? Promise.resolve()).then(run, run);
|
|
504
|
+
const settled = next.catch(() => void 0);
|
|
505
|
+
queues.set(scope, settled);
|
|
506
|
+
settled.then(() => {
|
|
507
|
+
if (queues.get(scope) === settled) queues.delete(scope);
|
|
508
|
+
});
|
|
509
|
+
return next;
|
|
510
|
+
}
|
|
431
511
|
/** Add what happened to the browser to the codemode result. */
|
|
432
512
|
function withBrowserReport(output, report) {
|
|
433
513
|
if (!report) return output;
|
|
514
|
+
const notices = [
|
|
515
|
+
report.restarted && RESTARTED_NOTICE,
|
|
516
|
+
report.tabClosed && !report.restarted && TAB_CLOSED_NOTICE,
|
|
517
|
+
report.tabShared && TAB_SHARED_NOTICE
|
|
518
|
+
].filter((notice) => typeof notice === "string");
|
|
434
519
|
return {
|
|
435
520
|
...output,
|
|
436
|
-
...report.restarted ? {
|
|
437
|
-
|
|
438
|
-
notice: RESTARTED_NOTICE
|
|
439
|
-
} : {},
|
|
521
|
+
...report.restarted ? { restarted: true } : {},
|
|
522
|
+
...notices.length > 0 ? { notice: notices.join(" ") } : {},
|
|
440
523
|
...report.newTabs.length > 0 ? { newTabs: report.newTabs } : {}
|
|
441
524
|
};
|
|
442
525
|
}
|
|
@@ -450,31 +533,84 @@ function browserReportNotes(output) {
|
|
|
450
533
|
/**
|
|
451
534
|
* Build the codemode runtime and connector for one `browserTool`, and wrap
|
|
452
535
|
* `execute` so each result carries the browser report.
|
|
536
|
+
*
|
|
537
|
+
* Each scope gets its own connector (which knows its scope) on the same
|
|
538
|
+
* codemode runtime, built on first use. Runs in one scope wait for each
|
|
539
|
+
* other, since they drive one tab; runs in different scopes go in parallel.
|
|
453
540
|
*/
|
|
454
541
|
function createBrowserToolCore(options, adapter) {
|
|
455
542
|
const ctx = resolveCtx(options);
|
|
456
543
|
if (!ctx) throw new Error("browserTool requires a Durable Object 'ctx' — pass it explicitly, or call from within an Agent so it can be resolved via getCurrentAgent()");
|
|
457
|
-
const
|
|
458
|
-
const
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
544
|
+
const timeout = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
545
|
+
const executor = new DynamicWorkerExecutor({
|
|
546
|
+
loader: options.loader,
|
|
547
|
+
timeout
|
|
548
|
+
});
|
|
549
|
+
const description = [
|
|
550
|
+
"Run JavaScript that drives a persistent Chrome browser over the Chrome DevTools Protocol (CDP).",
|
|
551
|
+
"",
|
|
552
|
+
"Write an async arrow function, `async () => { ... }`, and return a small JSON value. Use the `cdp` global to reach the browser. `fetch` is blocked and there is no file system or Node.js API.",
|
|
553
|
+
"",
|
|
554
|
+
"## cdp",
|
|
555
|
+
"",
|
|
556
|
+
"- `cdp.send({ method, params?, sessionId?, timeoutMs? })` sends a CDP command and returns its result without the JSON-RPC envelope: `Page.navigate` returns `{ frameId, errorText? }`, `Runtime.evaluate` returns `{ result: { value }, exceptionDetails? }`.",
|
|
557
|
+
"- `cdp.attachToTarget({ targetId })` makes an open tab active and returns `{ sessionId }`.",
|
|
558
|
+
"- `cdp.spec()` returns the whole protocol (about 650 KB) as `{ domains: [{ name, commands, events, types }] }`. Filter it in code, for example `spec.domains.find((d) => d.name === \"Page\").commands.find((c) => c.name === \"navigate\")`.",
|
|
559
|
+
"- `cdp.getDebugLog()` returns recent protocol traffic, for when a command fails or times out.",
|
|
560
|
+
"",
|
|
561
|
+
"## Rules",
|
|
562
|
+
"",
|
|
563
|
+
[
|
|
564
|
+
BROWSER_INSTRUCTIONS,
|
|
565
|
+
`Each run times out after ${Math.round(timeout / 1e3)}s, so split long jobs (crawling a site, say) across runs.`,
|
|
566
|
+
adapter.screenshotHint
|
|
567
|
+
].join("\n").split("\n").map((rule) => `- ${rule}`).join("\n"),
|
|
568
|
+
"- A `SyntaxError` from \"Failed to start Worker\" means your code didn't parse; its line number points into wrapper code, not yours. Check regex literals and escapes."
|
|
569
|
+
].join("\n");
|
|
570
|
+
const durableCtx = ctx;
|
|
571
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
572
|
+
function scoped(scope) {
|
|
573
|
+
const cached = scopes.get(scope);
|
|
574
|
+
if (cached) {
|
|
575
|
+
scopes.delete(scope);
|
|
576
|
+
scopes.set(scope, cached);
|
|
577
|
+
return cached;
|
|
578
|
+
}
|
|
579
|
+
const connector = new BrowserSessionConnector(durableCtx, {
|
|
580
|
+
browser: options.browser,
|
|
581
|
+
scope
|
|
582
|
+
});
|
|
583
|
+
const built = {
|
|
584
|
+
connector,
|
|
585
|
+
tool: createCodemodeRuntime({
|
|
586
|
+
ctx: durableCtx,
|
|
587
|
+
executor,
|
|
588
|
+
connectors: [connector],
|
|
589
|
+
name: browserRuntimeName(options.browser.name),
|
|
590
|
+
transformResult: transformBrowserResult
|
|
591
|
+
}).tool({ description })
|
|
592
|
+
};
|
|
593
|
+
scopes.set(scope, built);
|
|
594
|
+
if (scopes.size > MAX_CACHED_SCOPES) {
|
|
595
|
+
const oldest = scopes.keys().next().value;
|
|
596
|
+
if (oldest !== void 0) scopes.delete(oldest);
|
|
597
|
+
}
|
|
598
|
+
return built;
|
|
599
|
+
}
|
|
600
|
+
const defaultScope = options.scope ?? "shared";
|
|
601
|
+
const { inputSchema } = scoped(defaultScope).tool;
|
|
468
602
|
return {
|
|
469
|
-
description
|
|
470
|
-
inputSchema
|
|
471
|
-
|
|
472
|
-
|
|
603
|
+
description,
|
|
604
|
+
inputSchema,
|
|
605
|
+
/** Run `input` in `scope`, which defaults to the tool's `scope`. */
|
|
606
|
+
execute: (input, scope = defaultScope) => queued(options.browser, scope, async () => {
|
|
607
|
+
const { connector, tool } = scoped(scope);
|
|
608
|
+
const output = await tool.execute(input, void 0);
|
|
473
609
|
return withBrowserReport(output, connector.takeReport(output.executionId));
|
|
474
|
-
}
|
|
610
|
+
})
|
|
475
611
|
};
|
|
476
612
|
}
|
|
477
613
|
//#endregion
|
|
478
614
|
export { createBrowserToolCore as n, browserReportNotes as t };
|
|
479
615
|
|
|
480
|
-
//# sourceMappingURL=browser-tool-
|
|
616
|
+
//# sourceMappingURL=browser-tool-4iomavs_.js.map
|