@browserbasehq/orca 3.1.0-patch.4 → 3.2.0-preview.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/cjs/lib/inference.js +1 -4
- package/dist/cjs/lib/inference.js.map +1 -1
- package/dist/cjs/lib/v3/agent/AgentProvider.js +0 -1
- package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/act.d.ts +1 -1
- package/dist/cjs/lib/v3/agent/tools/act.js +20 -4
- package/dist/cjs/lib/v3/agent/tools/act.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/ariaTree.d.ts +8 -1
- package/dist/cjs/lib/v3/agent/tools/ariaTree.js +60 -22
- package/dist/cjs/lib/v3/agent/tools/ariaTree.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/click.js +23 -31
- package/dist/cjs/lib/v3/agent/tools/click.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/dragAndDrop.js +22 -30
- package/dist/cjs/lib/v3/agent/tools/dragAndDrop.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/extract.d.ts +2 -2
- package/dist/cjs/lib/v3/agent/tools/extract.js +16 -3
- package/dist/cjs/lib/v3/agent/tools/extract.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js +30 -30
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/fillform.d.ts +7 -1
- package/dist/cjs/lib/v3/agent/tools/fillform.js +60 -37
- package/dist/cjs/lib/v3/agent/tools/fillform.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/index.d.ts +5 -0
- package/dist/cjs/lib/v3/agent/tools/index.js +5 -5
- package/dist/cjs/lib/v3/agent/tools/index.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/screenshot.d.ts +8 -0
- package/dist/cjs/lib/v3/agent/tools/screenshot.js +32 -15
- package/dist/cjs/lib/v3/agent/tools/screenshot.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/scroll.js +12 -0
- package/dist/cjs/lib/v3/agent/tools/scroll.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/type.js +23 -31
- package/dist/cjs/lib/v3/agent/tools/type.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/wait.js +6 -0
- package/dist/cjs/lib/v3/agent/tools/wait.js.map +1 -1
- package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js +4 -0
- package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
- package/dist/cjs/lib/v3/api.d.ts +2 -2
- package/dist/cjs/lib/v3/api.js +1 -1
- package/dist/cjs/lib/v3/api.js.map +1 -1
- package/dist/cjs/lib/v3/cache/ActCache.d.ts +0 -1
- package/dist/cjs/lib/v3/cache/ActCache.js +2 -18
- package/dist/cjs/lib/v3/cache/ActCache.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/actHandler.js +1 -2
- package/dist/cjs/lib/v3/handlers/actHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/extractHandler.js +2 -2
- package/dist/cjs/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/observeHandler.js +1 -2
- package/dist/cjs/lib/v3/handlers/observeHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +11 -16
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/cjs/lib/v3/index.d.ts +2 -1
- package/dist/cjs/lib/v3/launch/browserbase.d.ts +1 -1
- package/dist/cjs/lib/v3/launch/browserbase.js +4 -9
- package/dist/cjs/lib/v3/launch/browserbase.js.map +1 -1
- package/dist/cjs/lib/v3/llm/LLMProvider.js +0 -5
- package/dist/cjs/lib/v3/llm/LLMProvider.js.map +1 -1
- package/dist/cjs/lib/v3/runtimePaths.js +2 -1
- package/dist/cjs/lib/v3/runtimePaths.js.map +1 -1
- package/dist/cjs/lib/v3/shutdown/supervisor.js +2 -2
- package/dist/cjs/lib/v3/shutdown/supervisor.js.map +1 -1
- package/dist/cjs/lib/v3/timeoutConfig.d.ts +1 -1
- package/dist/cjs/lib/v3/timeoutConfig.js +5 -0
- package/dist/cjs/lib/v3/timeoutConfig.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/shutdown.d.ts +1 -1
- package/dist/cjs/lib/v3/types/private/shutdown.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/agent.d.ts +12 -1
- package/dist/cjs/lib/v3/types/public/agent.js +0 -1
- package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/api.d.ts +3 -0
- package/dist/cjs/lib/v3/types/public/api.js +1 -0
- package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/model.d.ts +4 -2
- package/dist/cjs/lib/v3/types/public/model.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/options.d.ts +1 -0
- package/dist/cjs/lib/v3/understudy/cdp.d.ts +5 -1
- package/dist/cjs/lib/v3/understudy/cdp.js +54 -7
- package/dist/cjs/lib/v3/understudy/cdp.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/context.d.ts +1 -0
- package/dist/cjs/lib/v3/understudy/context.js +142 -60
- package/dist/cjs/lib/v3/understudy/context.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/frame.js +23 -6
- package/dist/cjs/lib/v3/understudy/frame.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/page.d.ts +13 -0
- package/dist/cjs/lib/v3/understudy/page.js +56 -3
- package/dist/cjs/lib/v3/understudy/page.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/screenshotUtils.d.ts +0 -1
- package/dist/cjs/lib/v3/understudy/screenshotUtils.js +0 -18
- package/dist/cjs/lib/v3/understudy/screenshotUtils.js.map +1 -1
- package/dist/cjs/lib/v3/v3.js +38 -24
- package/dist/cjs/lib/v3/v3.js.map +1 -1
- package/dist/cjs/tests/integration/cdp-session-detached.spec.js +1 -1
- package/dist/cjs/tests/integration/cdp-session-detached.spec.js.map +1 -1
- package/dist/cjs/tests/integration/context-addInitScript.spec.js +104 -11
- package/dist/cjs/tests/integration/context-addInitScript.spec.js.map +1 -1
- package/dist/cjs/tests/integration/iframe-ctx-addInitScript-race.spec.d.ts +1 -0
- package/dist/cjs/tests/integration/iframe-ctx-addInitScript-race.spec.js +219 -0
- package/dist/cjs/tests/integration/iframe-ctx-addInitScript-race.spec.js.map +1 -0
- package/dist/cjs/tests/integration/page-extra-http-headers.spec.d.ts +1 -0
- package/dist/cjs/tests/integration/page-extra-http-headers.spec.js +85 -0
- package/dist/cjs/tests/integration/page-extra-http-headers.spec.js.map +1 -0
- package/dist/cjs/tests/integration/page-screenshot.spec.js +1 -1
- package/dist/cjs/tests/integration/page-screenshot.spec.js.map +1 -1
- package/dist/cjs/tests/integration/timeouts.spec.js +168 -0
- package/dist/cjs/tests/integration/timeouts.spec.js.map +1 -1
- package/dist/cjs/tests/unit/model-deprecation.test.js +5 -8
- package/dist/cjs/tests/unit/model-deprecation.test.js.map +1 -1
- package/dist/cjs/tests/unit/page-extra-http-headers.test.d.ts +1 -0
- package/dist/cjs/tests/unit/page-extra-http-headers.test.js +92 -0
- package/dist/cjs/tests/unit/page-extra-http-headers.test.js.map +1 -0
- package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +13 -1
- package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
- package/dist/cjs/tests/unit/public-api/public-types.test.js.map +1 -1
- package/dist/esm/lib/inference.js +1 -4
- package/dist/esm/lib/inference.js.map +1 -1
- package/dist/esm/lib/v3/agent/AgentProvider.js +0 -1
- package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/act.d.ts +1 -1
- package/dist/esm/lib/v3/agent/tools/act.js +20 -4
- package/dist/esm/lib/v3/agent/tools/act.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/ariaTree.d.ts +8 -1
- package/dist/esm/lib/v3/agent/tools/ariaTree.js +60 -22
- package/dist/esm/lib/v3/agent/tools/ariaTree.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/click.js +23 -31
- package/dist/esm/lib/v3/agent/tools/click.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/dragAndDrop.js +22 -30
- package/dist/esm/lib/v3/agent/tools/dragAndDrop.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/extract.d.ts +2 -2
- package/dist/esm/lib/v3/agent/tools/extract.js +16 -3
- package/dist/esm/lib/v3/agent/tools/extract.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js +30 -30
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/fillform.d.ts +7 -1
- package/dist/esm/lib/v3/agent/tools/fillform.js +60 -37
- package/dist/esm/lib/v3/agent/tools/fillform.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/index.d.ts +5 -0
- package/dist/esm/lib/v3/agent/tools/index.js +5 -5
- package/dist/esm/lib/v3/agent/tools/index.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/screenshot.d.ts +8 -0
- package/dist/esm/lib/v3/agent/tools/screenshot.js +32 -15
- package/dist/esm/lib/v3/agent/tools/screenshot.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/scroll.js +12 -0
- package/dist/esm/lib/v3/agent/tools/scroll.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/type.js +23 -31
- package/dist/esm/lib/v3/agent/tools/type.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/wait.js +6 -0
- package/dist/esm/lib/v3/agent/tools/wait.js.map +1 -1
- package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js +4 -0
- package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
- package/dist/esm/lib/v3/api.d.ts +2 -2
- package/dist/esm/lib/v3/api.js +1 -1
- package/dist/esm/lib/v3/api.js.map +1 -1
- package/dist/esm/lib/v3/cache/ActCache.d.ts +0 -1
- package/dist/esm/lib/v3/cache/ActCache.js +2 -18
- package/dist/esm/lib/v3/cache/ActCache.js.map +1 -1
- package/dist/esm/lib/v3/handlers/actHandler.js +1 -2
- package/dist/esm/lib/v3/handlers/actHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/extractHandler.js +2 -2
- package/dist/esm/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/observeHandler.js +1 -2
- package/dist/esm/lib/v3/handlers/observeHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js +11 -16
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/esm/lib/v3/index.d.ts +2 -1
- package/dist/esm/lib/v3/launch/browserbase.d.ts +1 -1
- package/dist/esm/lib/v3/launch/browserbase.js +4 -9
- package/dist/esm/lib/v3/launch/browserbase.js.map +1 -1
- package/dist/esm/lib/v3/llm/LLMProvider.js +0 -5
- package/dist/esm/lib/v3/llm/LLMProvider.js.map +1 -1
- package/dist/esm/lib/v3/runtimePaths.js +2 -1
- package/dist/esm/lib/v3/runtimePaths.js.map +1 -1
- package/dist/esm/lib/v3/shutdown/supervisor.js +2 -2
- package/dist/esm/lib/v3/shutdown/supervisor.js.map +1 -1
- package/dist/esm/lib/v3/timeoutConfig.d.ts +1 -1
- package/dist/esm/lib/v3/timeoutConfig.js +5 -0
- package/dist/esm/lib/v3/timeoutConfig.js.map +1 -1
- package/dist/esm/lib/v3/types/private/shutdown.d.ts +1 -1
- package/dist/esm/lib/v3/types/private/shutdown.js.map +1 -1
- package/dist/esm/lib/v3/types/public/agent.d.ts +12 -1
- package/dist/esm/lib/v3/types/public/agent.js +0 -1
- package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
- package/dist/esm/lib/v3/types/public/api.d.ts +3 -0
- package/dist/esm/lib/v3/types/public/api.js +1 -0
- package/dist/esm/lib/v3/types/public/api.js.map +1 -1
- package/dist/esm/lib/v3/types/public/model.d.ts +4 -2
- package/dist/esm/lib/v3/types/public/model.js.map +1 -1
- package/dist/esm/lib/v3/types/public/options.d.ts +1 -0
- package/dist/esm/lib/v3/understudy/cdp.d.ts +5 -1
- package/dist/esm/lib/v3/understudy/cdp.js +55 -8
- package/dist/esm/lib/v3/understudy/cdp.js.map +1 -1
- package/dist/esm/lib/v3/understudy/context.d.ts +1 -0
- package/dist/esm/lib/v3/understudy/context.js +142 -60
- package/dist/esm/lib/v3/understudy/context.js.map +1 -1
- package/dist/esm/lib/v3/understudy/frame.js +23 -6
- package/dist/esm/lib/v3/understudy/frame.js.map +1 -1
- package/dist/esm/lib/v3/understudy/page.d.ts +13 -0
- package/dist/esm/lib/v3/understudy/page.js +58 -5
- package/dist/esm/lib/v3/understudy/page.js.map +1 -1
- package/dist/esm/lib/v3/understudy/screenshotUtils.d.ts +0 -1
- package/dist/esm/lib/v3/understudy/screenshotUtils.js +0 -17
- package/dist/esm/lib/v3/understudy/screenshotUtils.js.map +1 -1
- package/dist/esm/lib/v3/v3.js +38 -24
- package/dist/esm/lib/v3/v3.js.map +1 -1
- package/dist/esm/tests/integration/cdp-session-detached.spec.js +1 -1
- package/dist/esm/tests/integration/cdp-session-detached.spec.js.map +1 -1
- package/dist/esm/tests/integration/context-addInitScript.spec.js +104 -11
- package/dist/esm/tests/integration/context-addInitScript.spec.js.map +1 -1
- package/dist/esm/tests/integration/iframe-ctx-addInitScript-race.spec.d.ts +1 -0
- package/dist/esm/tests/integration/iframe-ctx-addInitScript-race.spec.js +217 -0
- package/dist/esm/tests/integration/iframe-ctx-addInitScript-race.spec.js.map +1 -0
- package/dist/esm/tests/integration/page-extra-http-headers.spec.d.ts +1 -0
- package/dist/esm/tests/integration/page-extra-http-headers.spec.js +83 -0
- package/dist/esm/tests/integration/page-extra-http-headers.spec.js.map +1 -0
- package/dist/esm/tests/integration/page-screenshot.spec.js +1 -1
- package/dist/esm/tests/integration/page-screenshot.spec.js.map +1 -1
- package/dist/esm/tests/integration/timeouts.spec.js +168 -0
- package/dist/esm/tests/integration/timeouts.spec.js.map +1 -1
- package/dist/esm/tests/unit/model-deprecation.test.js +5 -8
- package/dist/esm/tests/unit/model-deprecation.test.js.map +1 -1
- package/dist/esm/tests/unit/page-extra-http-headers.test.d.ts +1 -0
- package/dist/esm/tests/unit/page-extra-http-headers.test.js +90 -0
- package/dist/esm/tests/unit/page-extra-http-headers.test.js.map +1 -0
- package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +13 -1
- package/dist/esm/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
- package/dist/esm/tests/unit/public-api/public-types.test.js.map +1 -1
- package/package.json +4 -2
|
@@ -16,6 +16,7 @@ class CdpConnection {
|
|
|
16
16
|
sessions = new Map();
|
|
17
17
|
/** Maps sessionId -> targetId (1:1 mapping) */
|
|
18
18
|
sessionToTarget = new Map();
|
|
19
|
+
sessionDispatchWaiters = new Set();
|
|
19
20
|
id = null; // root
|
|
20
21
|
transportCloseHandlers = new Set();
|
|
21
22
|
/** Optional CDP logger - set this to receive all outgoing CDP method calls */
|
|
@@ -53,13 +54,14 @@ class CdpConnection {
|
|
|
53
54
|
});
|
|
54
55
|
this.ws.on("message", (data) => this.onMessage(data.toString()));
|
|
55
56
|
}
|
|
56
|
-
static async connect(wsUrl) {
|
|
57
|
+
static async connect(wsUrl, options) {
|
|
57
58
|
// Include User-Agent header for server-side observability and version tracking
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
59
|
+
// Merge user-provided headers, letting them override defaults
|
|
60
|
+
const headers = {
|
|
61
|
+
"User-Agent": `Stagehand/${version_js_1.STAGEHAND_VERSION}`,
|
|
62
|
+
...options?.headers,
|
|
63
|
+
};
|
|
64
|
+
const ws = new ws_1.default(wsUrl, { headers });
|
|
63
65
|
await new Promise((resolve, reject) => {
|
|
64
66
|
ws.once("open", () => resolve());
|
|
65
67
|
ws.once("error", (e) => reject(e));
|
|
@@ -118,10 +120,31 @@ class CdpConnection {
|
|
|
118
120
|
entry.reject(new sdkErrors_js_1.CdpConnectionClosedError(why));
|
|
119
121
|
this.inflight.delete(id);
|
|
120
122
|
}
|
|
123
|
+
for (const waiter of Array.from(this.sessionDispatchWaiters)) {
|
|
124
|
+
waiter.reject(new sdkErrors_js_1.CdpConnectionClosedError(why));
|
|
125
|
+
}
|
|
121
126
|
}
|
|
122
127
|
getSession(sessionId) {
|
|
123
128
|
return this.sessions.get(sessionId);
|
|
124
129
|
}
|
|
130
|
+
waitForSessionDispatch(sessionId, method, match) {
|
|
131
|
+
return new Promise((resolve, reject) => {
|
|
132
|
+
const waiter = {
|
|
133
|
+
sessionId,
|
|
134
|
+
method,
|
|
135
|
+
match,
|
|
136
|
+
resolve: () => {
|
|
137
|
+
this.sessionDispatchWaiters.delete(waiter);
|
|
138
|
+
resolve();
|
|
139
|
+
},
|
|
140
|
+
reject: (error) => {
|
|
141
|
+
this.sessionDispatchWaiters.delete(waiter);
|
|
142
|
+
reject(error);
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
this.sessionDispatchWaiters.add(waiter);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
125
148
|
async attachToTarget(targetId) {
|
|
126
149
|
const { sessionId } = (await this.send("Target.attachToTarget", { targetId, flatten: true }));
|
|
127
150
|
let session = this.sessions.get(sessionId);
|
|
@@ -165,10 +188,15 @@ class CdpConnection {
|
|
|
165
188
|
.params;
|
|
166
189
|
for (const [id, entry] of this.inflight.entries()) {
|
|
167
190
|
if (entry.sessionId === p.sessionId) {
|
|
168
|
-
entry.reject(new
|
|
191
|
+
entry.reject(new sdkErrors_js_1.PageNotFoundError(`target closed before CDP response (sessionId=${p.sessionId}, targetId=${p.targetId})`));
|
|
169
192
|
this.inflight.delete(id);
|
|
170
193
|
}
|
|
171
194
|
}
|
|
195
|
+
for (const waiter of Array.from(this.sessionDispatchWaiters)) {
|
|
196
|
+
if (waiter.sessionId === p.sessionId) {
|
|
197
|
+
waiter.reject(new sdkErrors_js_1.PageNotFoundError(`target closed before CDP send (sessionId=${p.sessionId}, targetId=${p.targetId})`));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
172
200
|
this.sessions.delete(p.sessionId);
|
|
173
201
|
this.sessionToTarget.delete(p.sessionId);
|
|
174
202
|
}
|
|
@@ -189,6 +217,15 @@ class CdpConnection {
|
|
|
189
217
|
if (sessionId) {
|
|
190
218
|
const session = this.sessions.get(sessionId);
|
|
191
219
|
session?.dispatch(method, params);
|
|
220
|
+
// Forward target lifecycle events to root listeners as well.
|
|
221
|
+
// Some browsers emit these via a parent session rather than the root
|
|
222
|
+
// connection; fan-out keeps target tracking consistent.
|
|
223
|
+
if (method.startsWith("Target.")) {
|
|
224
|
+
const handlers = this.eventHandlers.get(method);
|
|
225
|
+
if (handlers)
|
|
226
|
+
for (const h of handlers)
|
|
227
|
+
h(params);
|
|
228
|
+
}
|
|
192
229
|
}
|
|
193
230
|
else {
|
|
194
231
|
const handlers = this.eventHandlers.get(method);
|
|
@@ -217,6 +254,16 @@ class CdpConnection {
|
|
|
217
254
|
void p.catch(() => { });
|
|
218
255
|
const targetId = this.sessionToTarget.get(sessionId) ?? null;
|
|
219
256
|
this.cdpLogger?.({ method, params, targetId });
|
|
257
|
+
for (const waiter of Array.from(this.sessionDispatchWaiters)) {
|
|
258
|
+
if (waiter.sessionId !== sessionId)
|
|
259
|
+
continue;
|
|
260
|
+
if (waiter.method !== method)
|
|
261
|
+
continue;
|
|
262
|
+
if (waiter.match && !waiter.match(params))
|
|
263
|
+
continue;
|
|
264
|
+
waiter.resolve();
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
220
267
|
this.ws.send(JSON.stringify(payload));
|
|
221
268
|
return p;
|
|
222
269
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdp.js","sourceRoot":"","sources":["../../../../../lib/v3/understudy/cdp.ts"],"names":[],"mappings":"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","sourcesContent":["// lib/v3/understudy/cdp.ts\nimport WebSocket from \"ws\";\nimport type { Protocol } from \"devtools-protocol\";\nimport { STAGEHAND_VERSION } from \"../../version.js\";\nimport { CdpConnectionClosedError } from \"../types/public/sdkErrors.js\";\n\n/**\n * CDP transport & session multiplexer\n *\n * Owns the browser WebSocket and multiplexes flattened Target sessions.\n * Tracks inflight CDP calls, routes responses to the right session, and forwards events.\n *\n * This does not interpret Page/DOM/Runtime semantics — callers own that logic.\n */\nexport interface CDPSessionLike {\n send<R = unknown>(method: string, params?: object): Promise<R>;\n on<P = unknown>(event: string, handler: (params: P) => void): void;\n off<P = unknown>(event: string, handler: (params: P) => void): void;\n close(): Promise<void>;\n readonly id: string | null;\n}\n\ntype Inflight = {\n resolve: (v: unknown) => void;\n reject: (e: Error) => void;\n sessionId?: string | null;\n method: string;\n params?: object;\n stack?: string;\n ts: number;\n};\n\ntype EventHandler = (params: unknown) => void;\n\ntype RawMessage =\n | {\n id: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n sessionId?: string;\n }\n | { method: string; params?: unknown; sessionId?: string };\n\nexport class CdpConnection implements CDPSessionLike {\n private ws: WebSocket;\n private nextId = 1;\n private inflight = new Map<number, Inflight>();\n private eventHandlers = new Map<string, Set<EventHandler>>();\n private sessions = new Map<string, CdpSession>();\n /** Maps sessionId -> targetId (1:1 mapping) */\n private sessionToTarget = new Map<string, string>();\n public readonly id: string | null = null; // root\n private transportCloseHandlers = new Set<(why: string) => void>();\n\n /** Optional CDP logger - set this to receive all outgoing CDP method calls */\n public cdpLogger?: (info: {\n method: string;\n params?: object;\n targetId?: string | null;\n }) => void;\n\n /** Optional CDP event logger - set this to receive all incoming CDP events */\n public cdpEventLogger?: (info: {\n method: string;\n params?: unknown;\n targetId?: string | null;\n }) => void;\n\n public onTransportClosed(handler: (why: string) => void): void {\n this.transportCloseHandlers.add(handler);\n }\n public offTransportClosed(handler: (why: string) => void): void {\n this.transportCloseHandlers.delete(handler);\n }\n\n private emitTransportClosed(why: string) {\n for (const h of this.transportCloseHandlers) {\n try {\n h(why);\n } catch {\n //\n }\n }\n }\n\n private constructor(ws: WebSocket) {\n this.ws = ws;\n this.ws.on(\"close\", (code, reason) => {\n // Reason is a Buffer in ws; stringify defensively\n const why = `socket-close code=${code} reason=${String(reason || \"\")}`;\n this.rejectAllInflight(why);\n this.emitTransportClosed(why);\n });\n\n this.ws.on(\"error\", (err) => {\n const why = `socket-error ${err?.message ?? String(err)}`;\n this.rejectAllInflight(why);\n this.emitTransportClosed(why);\n });\n this.ws.on(\"message\", (data) => this.onMessage(data.toString()));\n }\n\n static async connect(wsUrl: string): Promise<CdpConnection> {\n // Include User-Agent header for server-side observability and version tracking\n const ws = new WebSocket(wsUrl, {\n headers: {\n \"User-Agent\": `Stagehand/${STAGEHAND_VERSION}`,\n },\n });\n await new Promise<void>((resolve, reject) => {\n ws.once(\"open\", () => resolve());\n ws.once(\"error\", (e) => reject(e));\n });\n return new CdpConnection(ws);\n }\n\n async enableAutoAttach(): Promise<void> {\n await this.send(\"Target.setAutoAttach\", {\n autoAttach: true,\n flatten: true,\n waitForDebuggerOnStart: true,\n });\n await this.send(\"Target.setDiscoverTargets\", { discover: true });\n }\n\n async send<R = unknown>(method: string, params?: object): Promise<R> {\n const id = this.nextId++;\n const payload = { id, method, params };\n const stack = new Error().stack?.split(\"\\n\").slice(1, 4).join(\"\\n\");\n const p = new Promise<R>((resolve, reject) => {\n this.inflight.set(id, {\n resolve,\n reject,\n sessionId: null,\n method,\n params,\n stack,\n ts: Date.now(),\n });\n });\n // Prevent unhandledRejection if a session detaches before the caller awaits.\n void p.catch(() => {});\n this.cdpLogger?.({ method, params, targetId: null });\n this.ws.send(JSON.stringify(payload));\n return p;\n }\n\n on<P = unknown>(event: string, handler: (params: P) => void): void {\n const set = this.eventHandlers.get(event) ?? new Set<EventHandler>();\n set.add(handler as EventHandler);\n this.eventHandlers.set(event, set);\n }\n\n off<P = unknown>(event: string, handler: (params: P) => void): void {\n const set = this.eventHandlers.get(event);\n if (set) set.delete(handler as EventHandler);\n }\n\n async close(): Promise<void> {\n if (this.ws.readyState === WebSocket.CLOSED) return;\n await new Promise<void>((resolve) => {\n this.ws.once(\"close\", () => resolve());\n this.ws.close();\n });\n }\n\n private rejectAllInflight(why: string): void {\n for (const [id, entry] of this.inflight.entries()) {\n entry.reject(new CdpConnectionClosedError(why));\n this.inflight.delete(id);\n }\n }\n\n getSession(sessionId: string): CdpSession | undefined {\n return this.sessions.get(sessionId);\n }\n\n async attachToTarget(targetId: string): Promise<CdpSession> {\n const { sessionId } = (await this.send<{ sessionId: string }>(\n \"Target.attachToTarget\",\n { targetId, flatten: true },\n )) as { sessionId: string };\n\n let session = this.sessions.get(sessionId);\n if (!session) {\n session = new CdpSession(this, sessionId);\n this.sessions.set(sessionId, session);\n }\n this.sessionToTarget.set(sessionId, targetId);\n return session;\n }\n\n async getTargets(): Promise<Protocol.Target.TargetInfo[]> {\n const res = await this.send<{\n targetInfos: Protocol.Target.TargetInfo[];\n }>(\"Target.getTargets\");\n return res.targetInfos;\n }\n\n private onMessage(json: string): void {\n const msg = JSON.parse(json) as RawMessage;\n\n if (\"id\" in msg) {\n const rec = this.inflight.get(msg.id);\n if (!rec) return;\n\n this.inflight.delete(msg.id);\n\n if (\"error\" in msg && msg.error) {\n rec.reject(new Error(`${msg.error.code} ${msg.error.message}`));\n } else {\n rec.resolve((msg as { result?: unknown }).result);\n }\n return;\n }\n\n if (\"method\" in msg) {\n if (msg.method === \"Target.attachedToTarget\") {\n const p = (msg as { params: Protocol.Target.AttachedToTargetEvent })\n .params;\n if (!this.sessions.has(p.sessionId)) {\n this.sessions.set(p.sessionId, new CdpSession(this, p.sessionId));\n }\n this.sessionToTarget.set(p.sessionId, p.targetInfo.targetId);\n } else if (msg.method === \"Target.detachedFromTarget\") {\n const p = (msg as { params: Protocol.Target.DetachedFromTargetEvent })\n .params;\n for (const [id, entry] of this.inflight.entries()) {\n if (entry.sessionId === p.sessionId) {\n entry.reject(new Error(\"CDP session detached\"));\n this.inflight.delete(id);\n }\n }\n this.sessions.delete(p.sessionId);\n this.sessionToTarget.delete(p.sessionId);\n } else if (msg.method === \"Target.targetDestroyed\") {\n const p = (msg as { params: { targetId: string } }).params;\n // Remove any session mapping for this target\n for (const [sessionId, targetId] of this.sessionToTarget.entries()) {\n if (targetId === p.targetId) {\n this.sessionToTarget.delete(sessionId);\n break;\n }\n }\n }\n\n const { method, params, sessionId } = msg;\n\n // Log incoming CDP events\n const targetId = this.sessionToTarget.get(sessionId) || sessionId;\n this.cdpEventLogger?.({ method, params, targetId });\n\n if (sessionId) {\n const session = this.sessions.get(sessionId);\n session?.dispatch(method, params);\n } else {\n const handlers = this.eventHandlers.get(method);\n if (handlers) for (const h of handlers) h(params);\n }\n }\n }\n\n _sendViaSession<R = unknown>(\n sessionId: string,\n method: string,\n params?: object,\n ): Promise<R> {\n const id = this.nextId++;\n const payload = { id, method, params, sessionId };\n const stack = new Error().stack?.split(\"\\n\").slice(1, 4).join(\"\\n\");\n\n const p = new Promise<R>((resolve, reject) => {\n this.inflight.set(id, {\n resolve,\n reject,\n sessionId,\n method,\n params,\n stack,\n ts: Date.now(),\n });\n });\n // Prevent unhandledRejection if a session detaches before the caller awaits.\n void p.catch(() => {});\n const targetId = this.sessionToTarget.get(sessionId) ?? null;\n this.cdpLogger?.({ method, params, targetId });\n this.ws.send(JSON.stringify(payload));\n return p;\n }\n\n _onSessionEvent(\n sessionId: string,\n event: string,\n handler: EventHandler,\n ): void {\n const key = `${sessionId}:${event}`;\n const set = this.eventHandlers.get(key) ?? new Set<EventHandler>();\n set.add(handler);\n this.eventHandlers.set(key, set);\n }\n\n _offSessionEvent(\n sessionId: string,\n event: string,\n handler: EventHandler,\n ): void {\n const key = `${sessionId}:${event}`;\n const set = this.eventHandlers.get(key);\n if (set) set.delete(handler);\n }\n\n _dispatchToSession(sessionId: string, event: string, params: unknown): void {\n const key = `${sessionId}:${event}`;\n const handlers = this.eventHandlers.get(key);\n if (handlers) for (const h of handlers) h(params);\n }\n}\n\nexport class CdpSession implements CDPSessionLike {\n constructor(\n private readonly root: CdpConnection,\n public readonly id: string,\n ) {}\n\n send<R = unknown>(method: string, params?: object): Promise<R> {\n return this.root._sendViaSession<R>(this.id, method, params);\n }\n\n on<P = unknown>(event: string, handler: (params: P) => void): void {\n this.root._onSessionEvent(this.id, event, handler as EventHandler);\n }\n\n off<P = unknown>(event: string, handler: (params: P) => void): void {\n this.root._offSessionEvent(this.id, event, handler as EventHandler);\n }\n\n async close(): Promise<void> {\n await this.root.send<void>(\"Target.detachFromTarget\", {\n sessionId: this.id,\n });\n }\n\n dispatch(event: string, params: unknown): void {\n this.root._dispatchToSession(this.id, event, params);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cdp.js","sourceRoot":"","sources":["../../../../../lib/v3/understudy/cdp.ts"],"names":[],"mappings":"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","sourcesContent":["// lib/v3/understudy/cdp.ts\nimport WebSocket from \"ws\";\nimport type { Protocol } from \"devtools-protocol\";\nimport { STAGEHAND_VERSION } from \"../../version.js\";\nimport {\n CdpConnectionClosedError,\n PageNotFoundError,\n} from \"../types/public/sdkErrors.js\";\n\n/**\n * CDP transport & session multiplexer\n *\n * Owns the browser WebSocket and multiplexes flattened Target sessions.\n * Tracks inflight CDP calls, routes responses to the right session, and forwards events.\n *\n * This does not interpret Page/DOM/Runtime semantics — callers own that logic.\n */\nexport interface CDPSessionLike {\n send<R = unknown>(method: string, params?: object): Promise<R>;\n on<P = unknown>(event: string, handler: (params: P) => void): void;\n off<P = unknown>(event: string, handler: (params: P) => void): void;\n close(): Promise<void>;\n readonly id: string | null;\n}\n\ntype Inflight = {\n resolve: (v: unknown) => void;\n reject: (e: Error) => void;\n sessionId?: string | null;\n method: string;\n params?: object;\n stack?: string;\n ts: number;\n};\n\ntype EventHandler = (params: unknown) => void;\ntype SessionDispatchWaiter = {\n sessionId: string;\n method: string;\n match?: (params?: object) => boolean;\n resolve: () => void;\n reject: (error: Error) => void;\n};\n\ntype RawMessage =\n | {\n id: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n sessionId?: string;\n }\n | { method: string; params?: unknown; sessionId?: string };\n\nexport class CdpConnection implements CDPSessionLike {\n private ws: WebSocket;\n private nextId = 1;\n private inflight = new Map<number, Inflight>();\n private eventHandlers = new Map<string, Set<EventHandler>>();\n private sessions = new Map<string, CdpSession>();\n /** Maps sessionId -> targetId (1:1 mapping) */\n private sessionToTarget = new Map<string, string>();\n private sessionDispatchWaiters = new Set<SessionDispatchWaiter>();\n public readonly id: string | null = null; // root\n private transportCloseHandlers = new Set<(why: string) => void>();\n\n /** Optional CDP logger - set this to receive all outgoing CDP method calls */\n public cdpLogger?: (info: {\n method: string;\n params?: object;\n targetId?: string | null;\n }) => void;\n\n /** Optional CDP event logger - set this to receive all incoming CDP events */\n public cdpEventLogger?: (info: {\n method: string;\n params?: unknown;\n targetId?: string | null;\n }) => void;\n\n public onTransportClosed(handler: (why: string) => void): void {\n this.transportCloseHandlers.add(handler);\n }\n public offTransportClosed(handler: (why: string) => void): void {\n this.transportCloseHandlers.delete(handler);\n }\n\n private emitTransportClosed(why: string) {\n for (const h of this.transportCloseHandlers) {\n try {\n h(why);\n } catch {\n //\n }\n }\n }\n\n private constructor(ws: WebSocket) {\n this.ws = ws;\n this.ws.on(\"close\", (code, reason) => {\n // Reason is a Buffer in ws; stringify defensively\n const why = `socket-close code=${code} reason=${String(reason || \"\")}`;\n this.rejectAllInflight(why);\n this.emitTransportClosed(why);\n });\n\n this.ws.on(\"error\", (err) => {\n const why = `socket-error ${err?.message ?? String(err)}`;\n this.rejectAllInflight(why);\n this.emitTransportClosed(why);\n });\n this.ws.on(\"message\", (data) => this.onMessage(data.toString()));\n }\n\n static async connect(\n wsUrl: string,\n options?: { headers?: Record<string, string> },\n ): Promise<CdpConnection> {\n // Include User-Agent header for server-side observability and version tracking\n // Merge user-provided headers, letting them override defaults\n const headers = {\n \"User-Agent\": `Stagehand/${STAGEHAND_VERSION}`,\n ...options?.headers,\n };\n const ws = new WebSocket(wsUrl, { headers });\n await new Promise<void>((resolve, reject) => {\n ws.once(\"open\", () => resolve());\n ws.once(\"error\", (e) => reject(e));\n });\n return new CdpConnection(ws);\n }\n\n async enableAutoAttach(): Promise<void> {\n await this.send(\"Target.setAutoAttach\", {\n autoAttach: true,\n flatten: true,\n waitForDebuggerOnStart: true,\n });\n await this.send(\"Target.setDiscoverTargets\", { discover: true });\n }\n\n async send<R = unknown>(method: string, params?: object): Promise<R> {\n const id = this.nextId++;\n const payload = { id, method, params };\n const stack = new Error().stack?.split(\"\\n\").slice(1, 4).join(\"\\n\");\n const p = new Promise<R>((resolve, reject) => {\n this.inflight.set(id, {\n resolve,\n reject,\n sessionId: null,\n method,\n params,\n stack,\n ts: Date.now(),\n });\n });\n // Prevent unhandledRejection if a session detaches before the caller awaits.\n void p.catch(() => {});\n this.cdpLogger?.({ method, params, targetId: null });\n this.ws.send(JSON.stringify(payload));\n return p;\n }\n\n on<P = unknown>(event: string, handler: (params: P) => void): void {\n const set = this.eventHandlers.get(event) ?? new Set<EventHandler>();\n set.add(handler as EventHandler);\n this.eventHandlers.set(event, set);\n }\n\n off<P = unknown>(event: string, handler: (params: P) => void): void {\n const set = this.eventHandlers.get(event);\n if (set) set.delete(handler as EventHandler);\n }\n\n async close(): Promise<void> {\n if (this.ws.readyState === WebSocket.CLOSED) return;\n await new Promise<void>((resolve) => {\n this.ws.once(\"close\", () => resolve());\n this.ws.close();\n });\n }\n\n private rejectAllInflight(why: string): void {\n for (const [id, entry] of this.inflight.entries()) {\n entry.reject(new CdpConnectionClosedError(why));\n this.inflight.delete(id);\n }\n for (const waiter of Array.from(this.sessionDispatchWaiters)) {\n waiter.reject(new CdpConnectionClosedError(why));\n }\n }\n\n getSession(sessionId: string): CdpSession | undefined {\n return this.sessions.get(sessionId);\n }\n\n waitForSessionDispatch(\n sessionId: string,\n method: string,\n match?: (params?: object) => boolean,\n ): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const waiter: SessionDispatchWaiter = {\n sessionId,\n method,\n match,\n resolve: () => {\n this.sessionDispatchWaiters.delete(waiter);\n resolve();\n },\n reject: (error: Error) => {\n this.sessionDispatchWaiters.delete(waiter);\n reject(error);\n },\n };\n this.sessionDispatchWaiters.add(waiter);\n });\n }\n\n async attachToTarget(targetId: string): Promise<CdpSession> {\n const { sessionId } = (await this.send<{ sessionId: string }>(\n \"Target.attachToTarget\",\n { targetId, flatten: true },\n )) as { sessionId: string };\n\n let session = this.sessions.get(sessionId);\n if (!session) {\n session = new CdpSession(this, sessionId);\n this.sessions.set(sessionId, session);\n }\n this.sessionToTarget.set(sessionId, targetId);\n return session;\n }\n\n async getTargets(): Promise<Protocol.Target.TargetInfo[]> {\n const res = await this.send<{\n targetInfos: Protocol.Target.TargetInfo[];\n }>(\"Target.getTargets\");\n return res.targetInfos;\n }\n\n private onMessage(json: string): void {\n const msg = JSON.parse(json) as RawMessage;\n\n if (\"id\" in msg) {\n const rec = this.inflight.get(msg.id);\n if (!rec) return;\n\n this.inflight.delete(msg.id);\n\n if (\"error\" in msg && msg.error) {\n rec.reject(new Error(`${msg.error.code} ${msg.error.message}`));\n } else {\n rec.resolve((msg as { result?: unknown }).result);\n }\n return;\n }\n\n if (\"method\" in msg) {\n if (msg.method === \"Target.attachedToTarget\") {\n const p = (msg as { params: Protocol.Target.AttachedToTargetEvent })\n .params;\n if (!this.sessions.has(p.sessionId)) {\n this.sessions.set(p.sessionId, new CdpSession(this, p.sessionId));\n }\n this.sessionToTarget.set(p.sessionId, p.targetInfo.targetId);\n } else if (msg.method === \"Target.detachedFromTarget\") {\n const p = (msg as { params: Protocol.Target.DetachedFromTargetEvent })\n .params;\n for (const [id, entry] of this.inflight.entries()) {\n if (entry.sessionId === p.sessionId) {\n entry.reject(\n new PageNotFoundError(\n `target closed before CDP response (sessionId=${p.sessionId}, targetId=${p.targetId})`,\n ),\n );\n this.inflight.delete(id);\n }\n }\n for (const waiter of Array.from(this.sessionDispatchWaiters)) {\n if (waiter.sessionId === p.sessionId) {\n waiter.reject(\n new PageNotFoundError(\n `target closed before CDP send (sessionId=${p.sessionId}, targetId=${p.targetId})`,\n ),\n );\n }\n }\n this.sessions.delete(p.sessionId);\n this.sessionToTarget.delete(p.sessionId);\n } else if (msg.method === \"Target.targetDestroyed\") {\n const p = (msg as { params: { targetId: string } }).params;\n // Remove any session mapping for this target\n for (const [sessionId, targetId] of this.sessionToTarget.entries()) {\n if (targetId === p.targetId) {\n this.sessionToTarget.delete(sessionId);\n break;\n }\n }\n }\n\n const { method, params, sessionId } = msg;\n\n // Log incoming CDP events\n const targetId = this.sessionToTarget.get(sessionId) || sessionId;\n this.cdpEventLogger?.({ method, params, targetId });\n\n if (sessionId) {\n const session = this.sessions.get(sessionId);\n session?.dispatch(method, params);\n\n // Forward target lifecycle events to root listeners as well.\n // Some browsers emit these via a parent session rather than the root\n // connection; fan-out keeps target tracking consistent.\n if (method.startsWith(\"Target.\")) {\n const handlers = this.eventHandlers.get(method);\n if (handlers) for (const h of handlers) h(params);\n }\n } else {\n const handlers = this.eventHandlers.get(method);\n if (handlers) for (const h of handlers) h(params);\n }\n }\n }\n\n _sendViaSession<R = unknown>(\n sessionId: string,\n method: string,\n params?: object,\n ): Promise<R> {\n const id = this.nextId++;\n const payload = { id, method, params, sessionId };\n const stack = new Error().stack?.split(\"\\n\").slice(1, 4).join(\"\\n\");\n\n const p = new Promise<R>((resolve, reject) => {\n this.inflight.set(id, {\n resolve,\n reject,\n sessionId,\n method,\n params,\n stack,\n ts: Date.now(),\n });\n });\n // Prevent unhandledRejection if a session detaches before the caller awaits.\n void p.catch(() => {});\n const targetId = this.sessionToTarget.get(sessionId) ?? null;\n this.cdpLogger?.({ method, params, targetId });\n for (const waiter of Array.from(this.sessionDispatchWaiters)) {\n if (waiter.sessionId !== sessionId) continue;\n if (waiter.method !== method) continue;\n if (waiter.match && !waiter.match(params)) continue;\n waiter.resolve();\n break;\n }\n this.ws.send(JSON.stringify(payload));\n return p;\n }\n\n _onSessionEvent(\n sessionId: string,\n event: string,\n handler: EventHandler,\n ): void {\n const key = `${sessionId}:${event}`;\n const set = this.eventHandlers.get(key) ?? new Set<EventHandler>();\n set.add(handler);\n this.eventHandlers.set(key, set);\n }\n\n _offSessionEvent(\n sessionId: string,\n event: string,\n handler: EventHandler,\n ): void {\n const key = `${sessionId}:${event}`;\n const set = this.eventHandlers.get(key);\n if (set) set.delete(handler);\n }\n\n _dispatchToSession(sessionId: string, event: string, params: unknown): void {\n const key = `${sessionId}:${event}`;\n const handlers = this.eventHandlers.get(key);\n if (handlers) for (const h of handlers) h(params);\n }\n}\n\nexport class CdpSession implements CDPSessionLike {\n constructor(\n private readonly root: CdpConnection,\n public readonly id: string,\n ) {}\n\n send<R = unknown>(method: string, params?: object): Promise<R> {\n return this.root._sendViaSession<R>(this.id, method, params);\n }\n\n on<P = unknown>(event: string, handler: (params: P) => void): void {\n this.root._onSessionEvent(this.id, event, handler as EventHandler);\n }\n\n off<P = unknown>(event: string, handler: (params: P) => void): void {\n this.root._offSessionEvent(this.id, event, handler as EventHandler);\n }\n\n async close(): Promise<void> {\n await this.root.send<void>(\"Target.detachFromTarget\", {\n sessionId: this.id,\n });\n }\n\n dispatch(event: string, params: unknown): void {\n this.root._dispatchToSession(this.id, event, params);\n }\n}\n"]}
|
|
@@ -45,6 +45,7 @@ export declare class V3Context {
|
|
|
45
45
|
env?: "LOCAL" | "BROWSERBASE";
|
|
46
46
|
apiClient?: StagehandAPIClient | null;
|
|
47
47
|
localBrowserLaunchOptions?: LocalBrowserLaunchOptions | null;
|
|
48
|
+
cdpHeaders?: Record<string, string>;
|
|
48
49
|
}): Promise<V3Context>;
|
|
49
50
|
private hasTopLevelPage;
|
|
50
51
|
private ensureFirstTopLevelPage;
|
|
@@ -111,7 +111,9 @@ class V3Context {
|
|
|
111
111
|
*/
|
|
112
112
|
static async create(wsUrl, opts) {
|
|
113
113
|
const connectTask = async () => {
|
|
114
|
-
const conn = await cdp_js_1.CdpConnection.connect(wsUrl
|
|
114
|
+
const conn = await cdp_js_1.CdpConnection.connect(wsUrl, {
|
|
115
|
+
headers: opts?.cdpHeaders,
|
|
116
|
+
});
|
|
115
117
|
const ctx = new V3Context(conn, opts?.env ?? "LOCAL", opts?.apiClient ?? null, opts?.localBrowserLaunchOptions ?? null);
|
|
116
118
|
await ctx.bootstrap();
|
|
117
119
|
await ctx.ensureFirstTopLevelPage(getFirstTopLevelPageTimeoutMs());
|
|
@@ -491,77 +493,148 @@ class V3Context {
|
|
|
491
493
|
// any "must happen before first document" work.
|
|
492
494
|
await session.send("Runtime.runIfWaitingForDebugger").catch(() => { });
|
|
493
495
|
};
|
|
494
|
-
//
|
|
495
|
-
//
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
.
|
|
496
|
+
// Attach lifecycle (per target session):
|
|
497
|
+
// 1) while paused, enable domains + child auto-attach and register init scripts;
|
|
498
|
+
// 2) resume target execution;
|
|
499
|
+
// 3) build/adopt Page ownership and frame bridges.
|
|
500
|
+
// Some CDP backends defer *.enable() responses until after resume, so we
|
|
501
|
+
// cannot await those responses before resuming. Instead we:
|
|
502
|
+
// - wait for transport-level dispatch of required pre-resume commands;
|
|
503
|
+
// - then dispatch resume;
|
|
504
|
+
// - then await responses.
|
|
505
|
+
const queuePreResume = (method, params, match) => {
|
|
506
|
+
const dispatched = this.conn
|
|
507
|
+
.waitForSessionDispatch(sessionId, method, match)
|
|
508
|
+
.then(() => true)
|
|
509
|
+
.catch(() => false);
|
|
510
|
+
const response = session
|
|
511
|
+
.send(method, params)
|
|
512
|
+
.then(() => true)
|
|
513
|
+
.catch(() => false);
|
|
514
|
+
return { dispatched, response };
|
|
515
|
+
};
|
|
516
|
+
const initScriptOps = [];
|
|
517
|
+
// Pre-resume ordering matters:
|
|
518
|
+
// - enable domains;
|
|
519
|
+
// - enable child auto-attach with waitForDebuggerOnStart;
|
|
520
|
+
// - register init scripts.
|
|
521
|
+
// Commands are sent in-order on the same session before resume.
|
|
522
|
+
const corePreResumeOps = [
|
|
523
|
+
queuePreResume("Page.enable"),
|
|
524
|
+
queuePreResume("Runtime.enable"),
|
|
525
|
+
queuePreResume("Target.setAutoAttach", {
|
|
506
526
|
autoAttach: true,
|
|
507
527
|
waitForDebuggerOnStart: true,
|
|
508
528
|
flatten: true,
|
|
509
|
-
})
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
529
|
+
}),
|
|
530
|
+
];
|
|
531
|
+
const headerPreResumeOps = [];
|
|
532
|
+
if (this.extraHttpHeaders) {
|
|
533
|
+
const headers = { ...this.extraHttpHeaders };
|
|
534
|
+
headerPreResumeOps.push(queuePreResume("Network.enable"));
|
|
535
|
+
headerPreResumeOps.push(queuePreResume("Network.setExtraHTTPHeaders", { headers }));
|
|
536
|
+
}
|
|
537
|
+
// Send init scripts only after auto-attach has been queued.
|
|
538
|
+
if (this.initScripts.length) {
|
|
539
|
+
for (const source of this.initScripts) {
|
|
540
|
+
initScriptOps.push(queuePreResume("Page.addScriptToEvaluateOnNewDocument", {
|
|
541
|
+
source,
|
|
542
|
+
runImmediately: true,
|
|
543
|
+
}, (sentParams) => sentParams?.source ===
|
|
544
|
+
source));
|
|
524
545
|
}
|
|
525
|
-
// register piercer (shadow-DOM hook) before resume so it runs
|
|
526
|
-
// before page scripts
|
|
527
|
-
installPromises.push(session
|
|
528
|
-
.send("Page.addScriptToEvaluateOnNewDocument", {
|
|
529
|
-
source: scriptV3Content_js_1.v3ScriptContent,
|
|
530
|
-
runImmediately: true,
|
|
531
|
-
})
|
|
532
|
-
.then(() => {
|
|
533
|
-
piercerPreRegistered = true;
|
|
534
|
-
})
|
|
535
|
-
.catch(() => { }));
|
|
536
|
-
installPromises.push(resume());
|
|
537
546
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
547
|
+
const piercerPreloadOp = queuePreResume("Page.addScriptToEvaluateOnNewDocument", {
|
|
548
|
+
source: scriptV3Content_js_1.v3ScriptContent,
|
|
549
|
+
runImmediately: true,
|
|
550
|
+
}, (sentParams) => sentParams?.source ===
|
|
551
|
+
scriptV3Content_js_1.v3ScriptContent);
|
|
552
|
+
const preResumeDispatched = (await Promise.all([
|
|
553
|
+
...corePreResumeOps.map((op) => op.dispatched),
|
|
554
|
+
...headerPreResumeOps.map((op) => op.dispatched),
|
|
555
|
+
...initScriptOps.map((op) => op.dispatched),
|
|
556
|
+
piercerPreloadOp.dispatched,
|
|
557
|
+
])).every(Boolean);
|
|
558
|
+
// Dispatch resume only after pre-resume setup has actually been sent.
|
|
559
|
+
const resumeOp = queuePreResume("Runtime.runIfWaitingForDebugger");
|
|
560
|
+
const [resumedDispatched, resumedOk] = await Promise.all([
|
|
561
|
+
resumeOp.dispatched,
|
|
562
|
+
resumeOp.response,
|
|
563
|
+
]);
|
|
564
|
+
const [coreResults, headerResults, initScriptResults, piercerPreRegistered,] = await Promise.all([
|
|
565
|
+
Promise.all(corePreResumeOps.map((op) => op.response)),
|
|
566
|
+
Promise.all(headerPreResumeOps.map((op) => op.response)),
|
|
567
|
+
Promise.all(initScriptOps.map((op) => op.response)),
|
|
568
|
+
piercerPreloadOp.response,
|
|
569
|
+
]);
|
|
570
|
+
// Header propagation is independent of init-script determinism but still
|
|
571
|
+
// part of pre-resume attach setup; awaited above for ordering/lifecycle.
|
|
572
|
+
void headerResults;
|
|
573
|
+
if (!preResumeDispatched || !resumedDispatched || !resumedOk) {
|
|
574
|
+
// Short-lived child targets can detach before resume is acknowledged.
|
|
575
|
+
// Keep this noisy only for top-level pages where missing attach is fatal.
|
|
576
|
+
if (isTopLevelPage(info)) {
|
|
577
|
+
(0, logger_js_1.v3Logger)({
|
|
578
|
+
category: "ctx",
|
|
579
|
+
message: "Failed target pre-resume setup ordering",
|
|
580
|
+
level: 2,
|
|
581
|
+
auxiliary: {
|
|
582
|
+
targetId: { value: String(info.targetId), type: "string" },
|
|
583
|
+
targetType: { value: String(info.type), type: "string" },
|
|
584
|
+
preResumeDispatched: {
|
|
585
|
+
value: String(preResumeDispatched),
|
|
586
|
+
type: "string",
|
|
587
|
+
},
|
|
588
|
+
resumedDispatched: {
|
|
589
|
+
value: String(resumedDispatched),
|
|
590
|
+
type: "string",
|
|
591
|
+
},
|
|
592
|
+
resumedOk: { value: String(resumedOk), type: "string" },
|
|
593
|
+
},
|
|
594
|
+
});
|
|
545
595
|
}
|
|
596
|
+
return;
|
|
546
597
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
// CDP round-trips that delay Page.create / installFrameEventBridges and
|
|
550
|
-
// cause same-process iframe frame-events to be missed) while still falling
|
|
551
|
-
// back to the full install path when registration failed.
|
|
552
|
-
if (piercerPreRegistered) {
|
|
553
|
-
this._piercerInstalled.add(sessionId);
|
|
554
|
-
}
|
|
598
|
+
resumed = true;
|
|
599
|
+
const scriptsInstalled = coreResults.every(Boolean) && initScriptResults.every(Boolean);
|
|
555
600
|
try {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
await session
|
|
601
|
+
// Best-effort lifecycle events; do not block top-level page registration
|
|
602
|
+
// on this optional signal stream.
|
|
603
|
+
void session
|
|
560
604
|
.send("Page.setLifecycleEventsEnabled", { enabled: true })
|
|
561
605
|
.catch(() => { });
|
|
562
606
|
// Top-level handling
|
|
563
607
|
if (isTopLevelPage(info)) {
|
|
564
|
-
|
|
608
|
+
let page = null;
|
|
609
|
+
let createError;
|
|
610
|
+
// Deterministic contract: never drop a newly attached top-level target
|
|
611
|
+
// because an arbitrary local timeout fired. We wait for Page.create and
|
|
612
|
+
// let it finish regardless of CDP call latency.
|
|
613
|
+
try {
|
|
614
|
+
page = await page_js_1.Page.create(this.conn, session, info.targetId, this.apiClient, this.localBrowserLaunchOptions, this.env === "BROWSERBASE");
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
createError = error;
|
|
618
|
+
}
|
|
619
|
+
if (!page) {
|
|
620
|
+
(0, logger_js_1.v3Logger)({
|
|
621
|
+
category: "ctx",
|
|
622
|
+
message: "Failed to create top-level Page",
|
|
623
|
+
level: 2,
|
|
624
|
+
auxiliary: {
|
|
625
|
+
targetId: { value: String(info.targetId), type: "string" },
|
|
626
|
+
targetType: { value: String(info.type), type: "string" },
|
|
627
|
+
targetUrl: { value: String(info.url ?? ""), type: "string" },
|
|
628
|
+
error: {
|
|
629
|
+
value: String(createError instanceof Error
|
|
630
|
+
? createError.message
|
|
631
|
+
: createError),
|
|
632
|
+
type: "string",
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
});
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
565
638
|
this.wireSessionToOwnerPage(sessionId, page);
|
|
566
639
|
this.pagesByTarget.set(info.targetId, page);
|
|
567
640
|
this.mainFrameToTarget.set(page.mainFrameId(), info.targetId);
|
|
@@ -576,13 +649,22 @@ class V3Context {
|
|
|
576
649
|
page.seedCurrentUrl(pendingSeedUrl ?? info.url ?? "");
|
|
577
650
|
this._pushActive(info.targetId);
|
|
578
651
|
this.installFrameEventBridges(sessionId, page);
|
|
652
|
+
if (piercerPreRegistered) {
|
|
653
|
+
this._piercerInstalled.add(sessionId);
|
|
654
|
+
}
|
|
579
655
|
// If we already installed scripts at the session level, only seed the
|
|
580
656
|
// Page's registry to avoid double-installing DOMContentLoaded handlers.
|
|
581
657
|
await this.applyInitScriptsToPage(page, {
|
|
582
658
|
seedOnly: scriptsInstalled,
|
|
583
659
|
});
|
|
660
|
+
if (!piercerPreRegistered) {
|
|
661
|
+
void this.ensurePiercer(session).catch(() => { });
|
|
662
|
+
}
|
|
584
663
|
return;
|
|
585
664
|
}
|
|
665
|
+
const piercerReady = await this.ensurePiercer(session).catch(() => false);
|
|
666
|
+
if (!piercerReady)
|
|
667
|
+
return;
|
|
586
668
|
// Child (iframe / OOPIF)
|
|
587
669
|
try {
|
|
588
670
|
const { frameTree } = await session.send("Page.getFrameTree");
|