@browserbasehq/orca 3.2.1-preview.3 → 3.4.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 -8
- package/dist/cjs/lib/inference.js.map +1 -1
- package/dist/cjs/lib/prompt.js +3 -1
- package/dist/cjs/lib/prompt.js.map +1 -1
- package/dist/cjs/lib/v3/agent/AgentProvider.js +3 -0
- package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js +16 -12
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
- package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
- package/dist/cjs/lib/v3/api.d.ts +1 -0
- package/dist/cjs/lib/v3/api.js +15 -3
- package/dist/cjs/lib/v3/api.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js +12 -12
- package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js +48 -48
- package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
- package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js +1 -1
- package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js +2 -2
- package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
- package/dist/cjs/lib/v3/dom/build/scriptV3Content.js +1 -1
- package/dist/cjs/lib/v3/dom/build/scriptV3Content.js.map +1 -1
- package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.d.ts +24 -0
- package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js +31 -0
- package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
- package/dist/cjs/lib/v3/handlers/extractHandler.js +3 -1
- package/dist/cjs/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/observeHandler.js +2 -1
- package/dist/cjs/lib/v3/handlers/observeHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +3 -5
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/cjs/lib/v3/index.d.ts +1 -1
- package/dist/cjs/lib/v3/llm/CerebrasClient.js +1 -1
- package/dist/cjs/lib/v3/llm/CerebrasClient.js.map +1 -1
- package/dist/cjs/lib/v3/llm/GroqClient.js +1 -1
- package/dist/cjs/lib/v3/llm/GroqClient.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/agent.d.ts +5 -0
- package/dist/cjs/lib/v3/types/private/agent.js +11 -0
- package/dist/cjs/lib/v3/types/private/agent.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/handlers.d.ts +2 -0
- package/dist/cjs/lib/v3/types/private/handlers.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/snapshot.d.ts +8 -0
- package/dist/cjs/lib/v3/types/private/snapshot.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/agent.d.ts +2 -3
- package/dist/cjs/lib/v3/types/public/agent.js +3 -0
- package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/api.d.ts +7 -1
- package/dist/cjs/lib/v3/types/public/api.js +22 -2
- package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/methods.d.ts +2 -0
- package/dist/cjs/lib/v3/types/public/methods.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js +268 -21
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
- package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/frameRegistry.js +16 -5
- package/dist/cjs/lib/v3/understudy/frameRegistry.js.map +1 -1
- package/dist/cjs/lib/v3/v3.d.ts +1 -0
- package/dist/cjs/lib/v3/v3.js +18 -14
- package/dist/cjs/lib/v3/v3.js.map +1 -1
- package/dist/cjs/lib/version.d.ts +1 -1
- package/dist/cjs/lib/version.js +1 -1
- package/dist/cjs/lib/version.js.map +1 -1
- package/dist/cjs/tests/integration/observe-element-id-format.spec.js +130 -0
- package/dist/cjs/tests/integration/observe-element-id-format.spec.js.map +1 -0
- package/dist/cjs/tests/unit/agent-mode-routing.test.js +88 -0
- package/dist/cjs/tests/unit/agent-mode-routing.test.js.map +1 -0
- package/dist/cjs/tests/unit/agent-temperature.test.d.ts +1 -0
- package/dist/cjs/tests/unit/agent-temperature.test.js +191 -0
- package/dist/cjs/tests/unit/agent-temperature.test.js.map +1 -0
- package/dist/cjs/tests/unit/agent-variables-validation.test.d.ts +1 -0
- package/dist/cjs/tests/unit/agent-variables-validation.test.js +43 -0
- package/dist/cjs/tests/unit/agent-variables-validation.test.js.map +1 -0
- package/dist/cjs/tests/unit/api-client-observe-variables.test.js +49 -0
- package/dist/cjs/tests/unit/api-client-observe-variables.test.js.map +1 -1
- package/dist/cjs/tests/unit/api-optional-model-api-key.test.js +60 -0
- package/dist/cjs/tests/unit/api-optional-model-api-key.test.js.map +1 -1
- package/dist/cjs/tests/unit/api-variables-schema.test.js +32 -0
- package/dist/cjs/tests/unit/api-variables-schema.test.js.map +1 -1
- package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
- package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js +60 -0
- package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
- package/dist/cjs/tests/unit/inference-temperature.test.d.ts +1 -0
- package/dist/cjs/tests/unit/inference-temperature.test.js +65 -0
- package/dist/cjs/tests/unit/inference-temperature.test.js.map +1 -0
- package/dist/cjs/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
- package/dist/cjs/tests/unit/openai-compatible-temperature.test.js +84 -0
- package/dist/cjs/tests/unit/openai-compatible-temperature.test.js.map +1 -0
- package/dist/cjs/tests/unit/prompt-observe-variables.test.js +6 -0
- package/dist/cjs/tests/unit/prompt-observe-variables.test.js.map +1 -1
- package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +3 -0
- 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/cjs/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
- package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
- package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
- package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
- package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js +119 -9
- package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
- package/dist/cjs/tests/unit/timeout-handlers.test.js +36 -0
- package/dist/cjs/tests/unit/timeout-handlers.test.js.map +1 -1
- package/dist/esm/lib/inference.js +1 -8
- package/dist/esm/lib/inference.js.map +1 -1
- package/dist/esm/lib/prompt.js +3 -1
- package/dist/esm/lib/prompt.js.map +1 -1
- package/dist/esm/lib/v3/agent/AgentProvider.js +3 -0
- package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js +16 -12
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
- package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
- package/dist/esm/lib/v3/api.d.ts +1 -0
- package/dist/esm/lib/v3/api.js +15 -3
- package/dist/esm/lib/v3/api.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js +12 -12
- package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js +48 -48
- package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
- package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js +1 -1
- package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js +2 -2
- package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
- package/dist/esm/lib/v3/dom/build/scriptV3Content.js +1 -1
- package/dist/esm/lib/v3/dom/build/scriptV3Content.js.map +1 -1
- package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.d.ts +24 -0
- package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js +28 -0
- package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
- package/dist/esm/lib/v3/handlers/extractHandler.js +3 -1
- package/dist/esm/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/observeHandler.js +2 -1
- package/dist/esm/lib/v3/handlers/observeHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js +3 -5
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/esm/lib/v3/index.d.ts +1 -1
- package/dist/esm/lib/v3/llm/CerebrasClient.js +1 -1
- package/dist/esm/lib/v3/llm/CerebrasClient.js.map +1 -1
- package/dist/esm/lib/v3/llm/GroqClient.js +1 -1
- package/dist/esm/lib/v3/llm/GroqClient.js.map +1 -1
- package/dist/esm/lib/v3/types/private/agent.d.ts +5 -0
- package/dist/esm/lib/v3/types/private/agent.js +10 -1
- package/dist/esm/lib/v3/types/private/agent.js.map +1 -1
- package/dist/esm/lib/v3/types/private/handlers.d.ts +2 -0
- package/dist/esm/lib/v3/types/private/handlers.js.map +1 -1
- package/dist/esm/lib/v3/types/private/snapshot.d.ts +8 -0
- package/dist/esm/lib/v3/types/private/snapshot.js.map +1 -1
- package/dist/esm/lib/v3/types/public/agent.d.ts +2 -3
- package/dist/esm/lib/v3/types/public/agent.js +3 -0
- package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
- package/dist/esm/lib/v3/types/public/api.d.ts +7 -1
- package/dist/esm/lib/v3/types/public/api.js +22 -2
- package/dist/esm/lib/v3/types/public/api.js.map +1 -1
- package/dist/esm/lib/v3/types/public/methods.d.ts +2 -0
- package/dist/esm/lib/v3/types/public/methods.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
- package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
- package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js +267 -22
- package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
- package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
- package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
- package/dist/esm/lib/v3/understudy/frameRegistry.js +16 -5
- package/dist/esm/lib/v3/understudy/frameRegistry.js.map +1 -1
- package/dist/esm/lib/v3/v3.d.ts +1 -0
- package/dist/esm/lib/v3/v3.js +18 -14
- package/dist/esm/lib/v3/v3.js.map +1 -1
- package/dist/esm/lib/version.d.ts +1 -1
- package/dist/esm/lib/version.js +1 -1
- package/dist/esm/lib/version.js.map +1 -1
- package/dist/esm/tests/integration/observe-element-id-format.spec.d.ts +1 -0
- package/dist/esm/tests/integration/observe-element-id-format.spec.js +128 -0
- package/dist/esm/tests/integration/observe-element-id-format.spec.js.map +1 -0
- package/dist/esm/tests/unit/agent-mode-routing.test.d.ts +1 -0
- package/dist/esm/tests/unit/agent-mode-routing.test.js +86 -0
- package/dist/esm/tests/unit/agent-mode-routing.test.js.map +1 -0
- package/dist/esm/tests/unit/agent-temperature.test.d.ts +1 -0
- package/dist/esm/tests/unit/agent-temperature.test.js +189 -0
- package/dist/esm/tests/unit/agent-temperature.test.js.map +1 -0
- package/dist/esm/tests/unit/agent-variables-validation.test.d.ts +1 -0
- package/dist/esm/tests/unit/agent-variables-validation.test.js +41 -0
- package/dist/esm/tests/unit/agent-variables-validation.test.js.map +1 -0
- package/dist/esm/tests/unit/api-client-observe-variables.test.js +49 -0
- package/dist/esm/tests/unit/api-client-observe-variables.test.js.map +1 -1
- package/dist/esm/tests/unit/api-optional-model-api-key.test.js +60 -0
- package/dist/esm/tests/unit/api-optional-model-api-key.test.js.map +1 -1
- package/dist/esm/tests/unit/api-variables-schema.test.js +32 -0
- package/dist/esm/tests/unit/api-variables-schema.test.js.map +1 -1
- package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
- package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js +58 -0
- package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
- package/dist/esm/tests/unit/inference-temperature.test.d.ts +1 -0
- package/dist/esm/tests/unit/inference-temperature.test.js +63 -0
- package/dist/esm/tests/unit/inference-temperature.test.js.map +1 -0
- package/dist/esm/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
- package/dist/esm/tests/unit/openai-compatible-temperature.test.js +82 -0
- package/dist/esm/tests/unit/openai-compatible-temperature.test.js.map +1 -0
- package/dist/esm/tests/unit/prompt-observe-variables.test.js +6 -0
- package/dist/esm/tests/unit/prompt-observe-variables.test.js.map +1 -1
- package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +3 -0
- 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/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
- package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
- package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
- package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
- package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js +119 -9
- package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
- package/dist/esm/tests/unit/timeout-handlers.test.js +36 -0
- package/dist/esm/tests/unit/timeout-handlers.test.js.map +1 -1
- package/package.json +3 -3
- package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js +0 -56
- package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
- package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js +0 -54
- package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
- /package/dist/cjs/tests/integration/{agent-captcha-autosolve.spec.d.ts → observe-element-id-format.spec.d.ts} +0 -0
- /package/dist/{esm/tests/integration/agent-captcha-autosolve.spec.d.ts → cjs/tests/unit/agent-mode-routing.test.d.ts} +0 -0
|
@@ -158,7 +158,7 @@ export async function domMapsForSession(session, frameId, pierce, encode, attemp
|
|
|
158
158
|
const { node, xpath } = stack.pop();
|
|
159
159
|
if (node.backendNodeId) {
|
|
160
160
|
const encId = encode(frameId, node.backendNodeId);
|
|
161
|
-
tagNameMap[encId] =
|
|
161
|
+
tagNameMap[encId] = enrichedTagName(node);
|
|
162
162
|
xpathMap[encId] = xpath || "/";
|
|
163
163
|
const isScrollable = node?.isScrollable === true;
|
|
164
164
|
if (isScrollable)
|
|
@@ -198,33 +198,61 @@ export async function buildSessionDomIndex(session, pierce) {
|
|
|
198
198
|
const scrollByBe = new Map();
|
|
199
199
|
const docRootOf = new Map();
|
|
200
200
|
const contentDocRootByIframe = new Map();
|
|
201
|
+
const enterByBe = new Map();
|
|
202
|
+
const exitByBe = new Map();
|
|
201
203
|
const rootBe = root.backendNodeId;
|
|
202
|
-
const stack = [
|
|
204
|
+
const stack = [
|
|
205
|
+
{ node: root, xp: "/", docRootBe: rootBe, phase: "enter" },
|
|
206
|
+
];
|
|
207
|
+
let dfsIndex = 0;
|
|
203
208
|
while (stack.length) {
|
|
204
|
-
const { node, xp, docRootBe } = stack.pop();
|
|
209
|
+
const { node, xp, docRootBe, phase } = stack.pop();
|
|
210
|
+
if (phase === "exit") {
|
|
211
|
+
if (node.backendNodeId) {
|
|
212
|
+
exitByBe.set(node.backendNodeId, dfsIndex++);
|
|
213
|
+
}
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
205
216
|
if (node.backendNodeId) {
|
|
217
|
+
enterByBe.set(node.backendNodeId, dfsIndex++);
|
|
206
218
|
absByBe.set(node.backendNodeId, xp || "/");
|
|
207
|
-
tagByBe.set(node.backendNodeId,
|
|
219
|
+
tagByBe.set(node.backendNodeId, enrichedTagName(node));
|
|
208
220
|
if (node?.isScrollable === true)
|
|
209
221
|
scrollByBe.set(node.backendNodeId, true);
|
|
210
222
|
docRootOf.set(node.backendNodeId, docRootBe);
|
|
211
223
|
}
|
|
224
|
+
stack.push({ node, xp, docRootBe, phase: "exit" });
|
|
212
225
|
const kids = node.children ?? [];
|
|
213
226
|
if (kids.length) {
|
|
214
227
|
const segs = buildChildXPathSegments(kids);
|
|
215
228
|
for (let i = kids.length - 1; i >= 0; i--) {
|
|
216
229
|
const child = kids[i];
|
|
217
230
|
const step = segs[i];
|
|
218
|
-
stack.push({
|
|
231
|
+
stack.push({
|
|
232
|
+
node: child,
|
|
233
|
+
xp: joinXPath(xp, step),
|
|
234
|
+
docRootBe,
|
|
235
|
+
phase: "enter",
|
|
236
|
+
});
|
|
219
237
|
}
|
|
220
238
|
}
|
|
221
239
|
for (const sr of node.shadowRoots ?? []) {
|
|
222
|
-
stack.push({
|
|
240
|
+
stack.push({
|
|
241
|
+
node: sr,
|
|
242
|
+
xp: joinXPath(xp, "//"),
|
|
243
|
+
docRootBe,
|
|
244
|
+
phase: "enter",
|
|
245
|
+
});
|
|
223
246
|
}
|
|
224
247
|
const cd = node.contentDocument;
|
|
225
248
|
if (cd && typeof cd.backendNodeId === "number") {
|
|
226
249
|
contentDocRootByIframe.set(node.backendNodeId, cd.backendNodeId);
|
|
227
|
-
stack.push({
|
|
250
|
+
stack.push({
|
|
251
|
+
node: cd,
|
|
252
|
+
xp,
|
|
253
|
+
docRootBe: cd.backendNodeId,
|
|
254
|
+
phase: "enter",
|
|
255
|
+
});
|
|
228
256
|
}
|
|
229
257
|
}
|
|
230
258
|
return {
|
|
@@ -234,6 +262,8 @@ export async function buildSessionDomIndex(session, pierce) {
|
|
|
234
262
|
scrollByBe,
|
|
235
263
|
docRootOf,
|
|
236
264
|
contentDocRootByIframe,
|
|
265
|
+
enterByBe,
|
|
266
|
+
exitByBe,
|
|
237
267
|
};
|
|
238
268
|
}
|
|
239
269
|
/**
|
|
@@ -255,6 +285,29 @@ export function relativizeXPath(baseAbs, nodeAbs) {
|
|
|
255
285
|
return abs;
|
|
256
286
|
return abs;
|
|
257
287
|
}
|
|
288
|
+
/**
|
|
289
|
+
* Extract an attribute value from a CDP DOM node's flat attributes array.
|
|
290
|
+
* Attributes are stored as [name1, value1, name2, value2, ...].
|
|
291
|
+
*/
|
|
292
|
+
function getAttr(attrs, name) {
|
|
293
|
+
if (!attrs)
|
|
294
|
+
return undefined;
|
|
295
|
+
for (let i = 0; i < attrs.length; i += 2) {
|
|
296
|
+
if (attrs[i] === name)
|
|
297
|
+
return attrs[i + 1];
|
|
298
|
+
}
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
301
|
+
/** Build an enriched tag name that includes the type attribute for inputs. */
|
|
302
|
+
function enrichedTagName(node) {
|
|
303
|
+
const tag = String(node.nodeName).toLowerCase();
|
|
304
|
+
if (tag === "input") {
|
|
305
|
+
const type = getAttr(node.attributes, "type");
|
|
306
|
+
if (type)
|
|
307
|
+
return `input, ${type}`;
|
|
308
|
+
}
|
|
309
|
+
return tag;
|
|
310
|
+
}
|
|
258
311
|
/** Find a node by backendNodeId inside a DOM.getDocument tree. */
|
|
259
312
|
export function findNodeByBackendId(root, backendNodeId) {
|
|
260
313
|
const stack = [root];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domTree.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/domTree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport { StagehandDomProcessError } from \"../../../types/public/sdkErrors.js\";\nimport type { SessionDomIndex } from \"../../../types/private/snapshot.js\";\nimport {\n buildChildXPathSegments,\n joinXPath,\n normalizeXPath,\n} from \"./xpathUtils.js\";\n\n// starting from infinite depth (-1), exponentially shrink down to 1\nconst DOM_DEPTH_ATTEMPTS = [-1, 256, 128, 64, 32, 16, 8, 4, 2, 1];\nconst DESCRIBE_DEPTH_ATTEMPTS = [-1, 64, 32, 16, 8, 4, 2, 1];\n\n/** Identify CDP failures caused by deep DOM trees blowing the CBOR encoder stack. */\nfunction isCborStackError(message: string): boolean {\n return message.includes(\"CBOR: stack limit exceeded\");\n}\n\n/**\n * Determine if CDP truncated a node's children when streaming the DOM tree.\n * childNodeCount stays accurate even when `children` are omitted; we use this to\n * decide whether DOM.describeNode must be re-run for that node.\n */\nexport function shouldExpandNode(node: Protocol.DOM.Node): boolean {\n const declaredChildren = node.childNodeCount ?? 0;\n const realizedChildren = node.children?.length ?? 0;\n return declaredChildren > realizedChildren;\n}\n\n/** Merge an expanded DescribeNode payload back into the original shallow node. */\nexport function mergeDomNodes(\n target: Protocol.DOM.Node,\n source: Protocol.DOM.Node,\n): void {\n target.childNodeCount = source.childNodeCount ?? target.childNodeCount;\n target.children = source.children ?? target.children;\n target.shadowRoots = source.shadowRoots ?? target.shadowRoots;\n target.contentDocument = source.contentDocument ?? target.contentDocument;\n}\n\n/** Helper that returns every nested collection we recurse through uniformly. */\nexport function collectDomTraversalTargets(\n node: Protocol.DOM.Node,\n): Protocol.DOM.Node[] {\n const targets: Protocol.DOM.Node[] = [];\n if (node.children) targets.push(...node.children);\n if (node.shadowRoots) targets.push(...node.shadowRoots);\n if (node.contentDocument) targets.push(node.contentDocument);\n return targets;\n}\n\n/**\n * Rehydrate a truncated DOM tree by repeatedly calling DOM.describeNode with\n * decreasing depths. Any non-CBOR failure is surfaced as a StagehandDomProcessError.\n */\nexport async function hydrateDomTree(\n session: CDPSessionLike,\n root: Protocol.DOM.Node,\n pierce: boolean,\n): Promise<void> {\n const stack: Protocol.DOM.Node[] = [root];\n const expandedNodeIds = new Set<number>();\n const expandedBackendIds = new Set<number>();\n\n while (stack.length) {\n const node = stack.pop()!;\n const nodeId =\n typeof node.nodeId === \"number\" && node.nodeId > 0\n ? node.nodeId\n : undefined;\n const backendId =\n typeof node.backendNodeId === \"number\" && node.backendNodeId > 0\n ? node.backendNodeId\n : undefined;\n\n const seenByNode = nodeId ? expandedNodeIds.has(nodeId) : false;\n const seenByBackend =\n !nodeId && backendId ? expandedBackendIds.has(backendId) : false;\n if (seenByNode || seenByBackend) continue;\n if (nodeId) expandedNodeIds.add(nodeId);\n else if (backendId) expandedBackendIds.add(backendId);\n\n const needsExpansion = shouldExpandNode(node);\n if (needsExpansion && (nodeId || backendId)) {\n const describeParamsBase = nodeId\n ? { nodeId }\n : { backendNodeId: backendId! };\n let expanded = false;\n for (const depth of DESCRIBE_DEPTH_ATTEMPTS) {\n try {\n const described =\n await session.send<Protocol.DOM.DescribeNodeResponse>(\n \"DOM.describeNode\",\n {\n ...describeParamsBase,\n depth,\n pierce,\n },\n );\n mergeDomNodes(node, described.node);\n if (!nodeId && described.node.nodeId && described.node.nodeId > 0) {\n node.nodeId = described.node.nodeId;\n expandedNodeIds.add(described.node.nodeId);\n }\n expanded = true;\n break;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (isCborStackError(message)) {\n continue;\n }\n const identifier = nodeId ?? backendId ?? \"unknown\";\n throw new StagehandDomProcessError(\n `Failed to expand DOM node ${identifier}: ${String(err)}`,\n );\n }\n }\n if (!expanded) {\n const identifier = nodeId ?? backendId ?? \"unknown\";\n throw new StagehandDomProcessError(\n `Unable to expand DOM node ${identifier} after describeNode depth retries`,\n );\n }\n }\n\n for (const child of collectDomTraversalTargets(node)) {\n stack.push(child);\n }\n }\n}\n\n/**\n * Attempt DOM.getDocument with progressively shallower depths until CBOR stops\n * complaining. When a shallower snapshot is returned we hydrate the missing\n * branches so downstream DOM traversals see the full tree shape.\n */\nexport async function getDomTreeWithFallback(\n session: CDPSessionLike,\n pierce: boolean,\n): Promise<Protocol.DOM.Node> {\n let lastCborMessage = \"\";\n\n for (const depth of DOM_DEPTH_ATTEMPTS) {\n try {\n const { root } = await session.send<{ root: Protocol.DOM.Node }>(\n \"DOM.getDocument\",\n { depth, pierce },\n );\n\n if (depth !== -1) {\n await hydrateDomTree(session, root, pierce);\n }\n\n return root;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (isCborStackError(message)) {\n lastCborMessage = message;\n continue;\n }\n throw err;\n }\n }\n\n throw new StagehandDomProcessError(\n lastCborMessage\n ? `CDP DOM.getDocument failed after adaptive depth retries: ${lastCborMessage}`\n : \"CDP DOM.getDocument failed after adaptive depth retries.\",\n );\n}\n\n/**\n * Build tag name and XPath maps for a single frame session.\n * EncodedId is produced by a frame-aware encoder provided by the caller.\n */\nexport async function domMapsForSession(\n session: CDPSessionLike,\n frameId: string,\n pierce: boolean,\n encode: (fid: string, backendNodeId: number) => string,\n attemptOwnerLookup = true,\n): Promise<{\n tagNameMap: Record<string, string>;\n xpathMap: Record<string, string>;\n scrollableMap: Record<string, boolean>;\n}> {\n await session.send(\"DOM.enable\").catch(() => {});\n const root = await getDomTreeWithFallback(session, pierce);\n\n let startNode: Protocol.DOM.Node = root;\n if (attemptOwnerLookup) {\n try {\n const owner = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n const ownerBackendId = owner.backendNodeId;\n if (typeof ownerBackendId === \"number\") {\n const ownerEl = findNodeByBackendId(root, ownerBackendId);\n if (ownerEl?.contentDocument) {\n startNode = ownerEl.contentDocument;\n }\n }\n } catch {\n // OOPIF or race → keep startNode = root\n }\n }\n\n const tagNameMap: Record<string, string> = {};\n const xpathMap: Record<string, string> = {};\n const scrollableMap: Record<string, boolean> = {};\n\n type StackEntry = { node: Protocol.DOM.Node; xpath: string };\n const stack: StackEntry[] = [{ node: startNode, xpath: \"\" }];\n\n while (stack.length) {\n const { node, xpath } = stack.pop()!;\n\n if (node.backendNodeId) {\n const encId = encode(frameId, node.backendNodeId);\n tagNameMap[encId] = String(node.nodeName).toLowerCase();\n xpathMap[encId] = xpath || \"/\";\n const isScrollable = node?.isScrollable === true;\n if (isScrollable) scrollableMap[encId] = true;\n }\n\n const kids = node.children ?? [];\n if (kids.length) {\n const segs = buildChildXPathSegments(kids);\n for (let i = kids.length - 1; i >= 0; i--) {\n const child = kids[i]!;\n const step = segs[i]!;\n stack.push({\n node: child,\n xpath: joinXPath(xpath, step),\n });\n }\n }\n\n for (const sr of node.shadowRoots ?? []) {\n stack.push({\n node: sr,\n xpath: joinXPath(xpath, \"//\"),\n });\n }\n }\n\n return { tagNameMap, xpathMap, scrollableMap };\n}\n\n/**\n * Build an index of absolute XPath/tag metadata for an entire CDP session.\n * Once the index is cached, per-frame slices are derived without extra DOM\n * calls, which keeps snapshot capture linear in the number of frames.\n */\nexport async function buildSessionDomIndex(\n session: CDPSessionLike,\n pierce: boolean,\n): Promise<SessionDomIndex> {\n await session.send(\"DOM.enable\").catch(() => {});\n const root = await getDomTreeWithFallback(session, pierce);\n\n const absByBe = new Map<number, string>();\n const tagByBe = new Map<number, string>();\n const scrollByBe = new Map<number, boolean>();\n const docRootOf = new Map<number, number>();\n const contentDocRootByIframe = new Map<number, number>();\n\n type Entry = { node: Protocol.DOM.Node; xp: string; docRootBe: number };\n const rootBe = root.backendNodeId!;\n const stack: Entry[] = [{ node: root, xp: \"/\", docRootBe: rootBe }];\n\n while (stack.length) {\n const { node, xp, docRootBe } = stack.pop()!;\n if (node.backendNodeId) {\n absByBe.set(node.backendNodeId, xp || \"/\");\n tagByBe.set(node.backendNodeId, String(node.nodeName).toLowerCase());\n if (node?.isScrollable === true) scrollByBe.set(node.backendNodeId, true);\n docRootOf.set(node.backendNodeId, docRootBe);\n }\n\n const kids = node.children ?? [];\n if (kids.length) {\n const segs = buildChildXPathSegments(kids);\n for (let i = kids.length - 1; i >= 0; i--) {\n const child = kids[i]!;\n const step = segs[i]!;\n stack.push({ node: child, xp: joinXPath(xp, step), docRootBe });\n }\n }\n\n for (const sr of node.shadowRoots ?? []) {\n stack.push({ node: sr, xp: joinXPath(xp, \"//\"), docRootBe });\n }\n\n const cd = node.contentDocument as Protocol.DOM.Node | undefined;\n if (cd && typeof cd.backendNodeId === \"number\") {\n contentDocRootByIframe.set(node.backendNodeId!, cd.backendNodeId);\n stack.push({ node: cd, xp, docRootBe: cd.backendNodeId });\n }\n }\n\n return {\n rootBackend: rootBe,\n absByBe,\n tagByBe,\n scrollByBe,\n docRootOf,\n contentDocRootByIframe,\n };\n}\n\n/**\n * Relativize an absolute XPath against a document root's absolute path.\n * When the node lives outside the document we return the absolute path as-is.\n */\nexport function relativizeXPath(baseAbs: string, nodeAbs: string): string {\n const base = normalizeXPath(baseAbs);\n const abs = normalizeXPath(nodeAbs);\n if (abs === base) return \"/\";\n if (abs.startsWith(base)) {\n const tail = abs.slice(base.length);\n if (!tail) return \"/\";\n return tail.startsWith(\"/\") || tail.startsWith(\"//\") ? tail : `/${tail}`;\n }\n if (base === \"/\") return abs;\n return abs;\n}\n\n/** Find a node by backendNodeId inside a DOM.getDocument tree. */\nexport function findNodeByBackendId(\n root: Protocol.DOM.Node,\n backendNodeId: number,\n): Protocol.DOM.Node | undefined {\n const stack: Protocol.DOM.Node[] = [root];\n while (stack.length) {\n const n = stack.pop()!;\n if (n.backendNodeId === backendNodeId) return n;\n if (n.children) for (const c of n.children) stack.push(c);\n if (n.shadowRoots) for (const s of n.shadowRoots) stack.push(s);\n }\n return undefined;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"domTree.js","sourceRoot":"","sources":["../../../../../../../lib/v3/understudy/a11y/snapshot/domTree.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Protocol } from \"devtools-protocol\";\nimport type { CDPSessionLike } from \"../../cdp.js\";\nimport { StagehandDomProcessError } from \"../../../types/public/sdkErrors.js\";\nimport type { SessionDomIndex } from \"../../../types/private/snapshot.js\";\nimport {\n buildChildXPathSegments,\n joinXPath,\n normalizeXPath,\n} from \"./xpathUtils.js\";\n\n// starting from infinite depth (-1), exponentially shrink down to 1\nconst DOM_DEPTH_ATTEMPTS = [-1, 256, 128, 64, 32, 16, 8, 4, 2, 1];\nconst DESCRIBE_DEPTH_ATTEMPTS = [-1, 64, 32, 16, 8, 4, 2, 1];\n\n/** Identify CDP failures caused by deep DOM trees blowing the CBOR encoder stack. */\nfunction isCborStackError(message: string): boolean {\n return message.includes(\"CBOR: stack limit exceeded\");\n}\n\n/**\n * Determine if CDP truncated a node's children when streaming the DOM tree.\n * childNodeCount stays accurate even when `children` are omitted; we use this to\n * decide whether DOM.describeNode must be re-run for that node.\n */\nexport function shouldExpandNode(node: Protocol.DOM.Node): boolean {\n const declaredChildren = node.childNodeCount ?? 0;\n const realizedChildren = node.children?.length ?? 0;\n return declaredChildren > realizedChildren;\n}\n\n/** Merge an expanded DescribeNode payload back into the original shallow node. */\nexport function mergeDomNodes(\n target: Protocol.DOM.Node,\n source: Protocol.DOM.Node,\n): void {\n target.childNodeCount = source.childNodeCount ?? target.childNodeCount;\n target.children = source.children ?? target.children;\n target.shadowRoots = source.shadowRoots ?? target.shadowRoots;\n target.contentDocument = source.contentDocument ?? target.contentDocument;\n}\n\n/** Helper that returns every nested collection we recurse through uniformly. */\nexport function collectDomTraversalTargets(\n node: Protocol.DOM.Node,\n): Protocol.DOM.Node[] {\n const targets: Protocol.DOM.Node[] = [];\n if (node.children) targets.push(...node.children);\n if (node.shadowRoots) targets.push(...node.shadowRoots);\n if (node.contentDocument) targets.push(node.contentDocument);\n return targets;\n}\n\n/**\n * Rehydrate a truncated DOM tree by repeatedly calling DOM.describeNode with\n * decreasing depths. Any non-CBOR failure is surfaced as a StagehandDomProcessError.\n */\nexport async function hydrateDomTree(\n session: CDPSessionLike,\n root: Protocol.DOM.Node,\n pierce: boolean,\n): Promise<void> {\n const stack: Protocol.DOM.Node[] = [root];\n const expandedNodeIds = new Set<number>();\n const expandedBackendIds = new Set<number>();\n\n while (stack.length) {\n const node = stack.pop()!;\n const nodeId =\n typeof node.nodeId === \"number\" && node.nodeId > 0\n ? node.nodeId\n : undefined;\n const backendId =\n typeof node.backendNodeId === \"number\" && node.backendNodeId > 0\n ? node.backendNodeId\n : undefined;\n\n const seenByNode = nodeId ? expandedNodeIds.has(nodeId) : false;\n const seenByBackend =\n !nodeId && backendId ? expandedBackendIds.has(backendId) : false;\n if (seenByNode || seenByBackend) continue;\n if (nodeId) expandedNodeIds.add(nodeId);\n else if (backendId) expandedBackendIds.add(backendId);\n\n const needsExpansion = shouldExpandNode(node);\n if (needsExpansion && (nodeId || backendId)) {\n const describeParamsBase = nodeId\n ? { nodeId }\n : { backendNodeId: backendId! };\n let expanded = false;\n for (const depth of DESCRIBE_DEPTH_ATTEMPTS) {\n try {\n const described =\n await session.send<Protocol.DOM.DescribeNodeResponse>(\n \"DOM.describeNode\",\n {\n ...describeParamsBase,\n depth,\n pierce,\n },\n );\n mergeDomNodes(node, described.node);\n if (!nodeId && described.node.nodeId && described.node.nodeId > 0) {\n node.nodeId = described.node.nodeId;\n expandedNodeIds.add(described.node.nodeId);\n }\n expanded = true;\n break;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (isCborStackError(message)) {\n continue;\n }\n const identifier = nodeId ?? backendId ?? \"unknown\";\n throw new StagehandDomProcessError(\n `Failed to expand DOM node ${identifier}: ${String(err)}`,\n );\n }\n }\n if (!expanded) {\n const identifier = nodeId ?? backendId ?? \"unknown\";\n throw new StagehandDomProcessError(\n `Unable to expand DOM node ${identifier} after describeNode depth retries`,\n );\n }\n }\n\n for (const child of collectDomTraversalTargets(node)) {\n stack.push(child);\n }\n }\n}\n\n/**\n * Attempt DOM.getDocument with progressively shallower depths until CBOR stops\n * complaining. When a shallower snapshot is returned we hydrate the missing\n * branches so downstream DOM traversals see the full tree shape.\n */\nexport async function getDomTreeWithFallback(\n session: CDPSessionLike,\n pierce: boolean,\n): Promise<Protocol.DOM.Node> {\n let lastCborMessage = \"\";\n\n for (const depth of DOM_DEPTH_ATTEMPTS) {\n try {\n const { root } = await session.send<{ root: Protocol.DOM.Node }>(\n \"DOM.getDocument\",\n { depth, pierce },\n );\n\n if (depth !== -1) {\n await hydrateDomTree(session, root, pierce);\n }\n\n return root;\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (isCborStackError(message)) {\n lastCborMessage = message;\n continue;\n }\n throw err;\n }\n }\n\n throw new StagehandDomProcessError(\n lastCborMessage\n ? `CDP DOM.getDocument failed after adaptive depth retries: ${lastCborMessage}`\n : \"CDP DOM.getDocument failed after adaptive depth retries.\",\n );\n}\n\n/**\n * Build tag name and XPath maps for a single frame session.\n * EncodedId is produced by a frame-aware encoder provided by the caller.\n */\nexport async function domMapsForSession(\n session: CDPSessionLike,\n frameId: string,\n pierce: boolean,\n encode: (fid: string, backendNodeId: number) => string,\n attemptOwnerLookup = true,\n): Promise<{\n tagNameMap: Record<string, string>;\n xpathMap: Record<string, string>;\n scrollableMap: Record<string, boolean>;\n}> {\n await session.send(\"DOM.enable\").catch(() => {});\n const root = await getDomTreeWithFallback(session, pierce);\n\n let startNode: Protocol.DOM.Node = root;\n if (attemptOwnerLookup) {\n try {\n const owner = await session.send<{ backendNodeId?: number }>(\n \"DOM.getFrameOwner\",\n { frameId },\n );\n const ownerBackendId = owner.backendNodeId;\n if (typeof ownerBackendId === \"number\") {\n const ownerEl = findNodeByBackendId(root, ownerBackendId);\n if (ownerEl?.contentDocument) {\n startNode = ownerEl.contentDocument;\n }\n }\n } catch {\n // OOPIF or race → keep startNode = root\n }\n }\n\n const tagNameMap: Record<string, string> = {};\n const xpathMap: Record<string, string> = {};\n const scrollableMap: Record<string, boolean> = {};\n\n type StackEntry = { node: Protocol.DOM.Node; xpath: string };\n const stack: StackEntry[] = [{ node: startNode, xpath: \"\" }];\n\n while (stack.length) {\n const { node, xpath } = stack.pop()!;\n\n if (node.backendNodeId) {\n const encId = encode(frameId, node.backendNodeId);\n tagNameMap[encId] = enrichedTagName(node);\n xpathMap[encId] = xpath || \"/\";\n const isScrollable = node?.isScrollable === true;\n if (isScrollable) scrollableMap[encId] = true;\n }\n\n const kids = node.children ?? [];\n if (kids.length) {\n const segs = buildChildXPathSegments(kids);\n for (let i = kids.length - 1; i >= 0; i--) {\n const child = kids[i]!;\n const step = segs[i]!;\n stack.push({\n node: child,\n xpath: joinXPath(xpath, step),\n });\n }\n }\n\n for (const sr of node.shadowRoots ?? []) {\n stack.push({\n node: sr,\n xpath: joinXPath(xpath, \"//\"),\n });\n }\n }\n\n return { tagNameMap, xpathMap, scrollableMap };\n}\n\n/**\n * Build an index of absolute XPath/tag metadata for an entire CDP session.\n * Once the index is cached, per-frame slices are derived without extra DOM\n * calls, which keeps snapshot capture linear in the number of frames.\n */\nexport async function buildSessionDomIndex(\n session: CDPSessionLike,\n pierce: boolean,\n): Promise<SessionDomIndex> {\n await session.send(\"DOM.enable\").catch(() => {});\n const root = await getDomTreeWithFallback(session, pierce);\n\n const absByBe = new Map<number, string>();\n const tagByBe = new Map<number, string>();\n const scrollByBe = new Map<number, boolean>();\n const docRootOf = new Map<number, number>();\n const contentDocRootByIframe = new Map<number, number>();\n const enterByBe = new Map<number, number>();\n const exitByBe = new Map<number, number>();\n\n type Entry = {\n node: Protocol.DOM.Node;\n xp: string;\n docRootBe: number;\n phase: \"enter\" | \"exit\";\n };\n const rootBe = root.backendNodeId!;\n const stack: Entry[] = [\n { node: root, xp: \"/\", docRootBe: rootBe, phase: \"enter\" },\n ];\n let dfsIndex = 0;\n\n while (stack.length) {\n const { node, xp, docRootBe, phase } = stack.pop()!;\n if (phase === \"exit\") {\n if (node.backendNodeId) {\n exitByBe.set(node.backendNodeId, dfsIndex++);\n }\n continue;\n }\n\n if (node.backendNodeId) {\n enterByBe.set(node.backendNodeId, dfsIndex++);\n absByBe.set(node.backendNodeId, xp || \"/\");\n tagByBe.set(node.backendNodeId, enrichedTagName(node));\n if (node?.isScrollable === true) scrollByBe.set(node.backendNodeId, true);\n docRootOf.set(node.backendNodeId, docRootBe);\n }\n\n stack.push({ node, xp, docRootBe, phase: \"exit\" });\n\n const kids = node.children ?? [];\n if (kids.length) {\n const segs = buildChildXPathSegments(kids);\n for (let i = kids.length - 1; i >= 0; i--) {\n const child = kids[i]!;\n const step = segs[i]!;\n stack.push({\n node: child,\n xp: joinXPath(xp, step),\n docRootBe,\n phase: \"enter\",\n });\n }\n }\n\n for (const sr of node.shadowRoots ?? []) {\n stack.push({\n node: sr,\n xp: joinXPath(xp, \"//\"),\n docRootBe,\n phase: \"enter\",\n });\n }\n\n const cd = node.contentDocument as Protocol.DOM.Node | undefined;\n if (cd && typeof cd.backendNodeId === \"number\") {\n contentDocRootByIframe.set(node.backendNodeId!, cd.backendNodeId);\n stack.push({\n node: cd,\n xp,\n docRootBe: cd.backendNodeId,\n phase: \"enter\",\n });\n }\n }\n\n return {\n rootBackend: rootBe,\n absByBe,\n tagByBe,\n scrollByBe,\n docRootOf,\n contentDocRootByIframe,\n enterByBe,\n exitByBe,\n };\n}\n\n/**\n * Relativize an absolute XPath against a document root's absolute path.\n * When the node lives outside the document we return the absolute path as-is.\n */\nexport function relativizeXPath(baseAbs: string, nodeAbs: string): string {\n const base = normalizeXPath(baseAbs);\n const abs = normalizeXPath(nodeAbs);\n if (abs === base) return \"/\";\n if (abs.startsWith(base)) {\n const tail = abs.slice(base.length);\n if (!tail) return \"/\";\n return tail.startsWith(\"/\") || tail.startsWith(\"//\") ? tail : `/${tail}`;\n }\n if (base === \"/\") return abs;\n return abs;\n}\n\n/**\n * Extract an attribute value from a CDP DOM node's flat attributes array.\n * Attributes are stored as [name1, value1, name2, value2, ...].\n */\nfunction getAttr(\n attrs: string[] | undefined,\n name: string,\n): string | undefined {\n if (!attrs) return undefined;\n for (let i = 0; i < attrs.length; i += 2) {\n if (attrs[i] === name) return attrs[i + 1];\n }\n return undefined;\n}\n\n/** Build an enriched tag name that includes the type attribute for inputs. */\nfunction enrichedTagName(node: Protocol.DOM.Node): string {\n const tag = String(node.nodeName).toLowerCase();\n if (tag === \"input\") {\n const type = getAttr(node.attributes, \"type\");\n if (type) return `input, ${type}`;\n }\n return tag;\n}\n\n/** Find a node by backendNodeId inside a DOM.getDocument tree. */\nexport function findNodeByBackendId(\n root: Protocol.DOM.Node,\n backendNodeId: number,\n): Protocol.DOM.Node | undefined {\n const stack: Protocol.DOM.Node[] = [root];\n while (stack.length) {\n const n = stack.pop()!;\n if (n.backendNodeId === backendNodeId) return n;\n if (n.children) for (const c of n.children) stack.push(c);\n if (n.shadowRoots) for (const s of n.shadowRoots) stack.push(s);\n }\n return undefined;\n}\n"]}
|
|
@@ -141,14 +141,25 @@ export class FrameRegistry {
|
|
|
141
141
|
seedFromFrameTree(sessionId, frameTree) {
|
|
142
142
|
const walk = (tree, parent) => {
|
|
143
143
|
this.ensureNode(tree.frame.id);
|
|
144
|
+
const info = this.frames.get(tree.frame.id);
|
|
145
|
+
const previousParent = info.parentId;
|
|
146
|
+
const nextParent = parent ?? tree.frame.parentId ?? previousParent ?? null;
|
|
144
147
|
// topology
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
+
if (previousParent && previousParent !== nextParent) {
|
|
149
|
+
this.frames.get(previousParent)?.children.delete(tree.frame.id);
|
|
150
|
+
}
|
|
151
|
+
info.parentId = nextParent;
|
|
152
|
+
if (nextParent) {
|
|
153
|
+
this.ensureNode(nextParent);
|
|
154
|
+
this.frames.get(nextParent).children.add(tree.frame.id);
|
|
155
|
+
}
|
|
148
156
|
// last-seen frame
|
|
149
|
-
|
|
157
|
+
info.lastSeen =
|
|
158
|
+
nextParent && !tree.frame.parentId
|
|
159
|
+
? { ...tree.frame, parentId: nextParent }
|
|
160
|
+
: tree.frame;
|
|
150
161
|
// ownership (only if unknown)
|
|
151
|
-
if (!
|
|
162
|
+
if (!info.ownerSessionId) {
|
|
152
163
|
this.setOwnerSessionIdInternal(tree.frame.id, sessionId);
|
|
153
164
|
}
|
|
154
165
|
for (const c of tree.childFrames ?? [])
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frameRegistry.js","sourceRoot":"","sources":["../../../../../lib/v3/understudy/frameRegistry.ts"],"names":[],"mappings":"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","sourcesContent":["// lib/v3/understudy/frameRegistry.ts\nimport type { Protocol } from \"devtools-protocol\";\n\n/**\n * FrameRegistry\n *\n * Purpose:\n * A single, authoritative source of truth for **both**:\n * 1) Frame topology (parent/children, current main/root id, last-seen CDP `Frame`)\n * 2) Frame → Session ownership (which CDP session owns a given frameId)\n * 3) Optional iframe-owner metadata (backendNodeId of the <iframe> element in the parent doc)\n *\n *\n * Model:\n * - This class is **CDP-agnostic**; it stores **sessionId strings** (not session objects).\n * - Context bridges (wiring Target/Page events) must call the mutators below (onAttached,\n * onNavigated, onDetached, adoptChildSession, seedFromFrameTree, setOwnerBackendNodeId).\n * - Consumers ask read APIs (getOwnerSessionId, getParent, asProtocolFrameTree, listAll, …)\n * and never probe ownership at run time.\n */\n\ntype FrameId = string;\ntype SessionId = string;\n\ntype FrameInfo = {\n /** Parent frame id, or null for root */\n parentId: FrameId | null;\n /** Children frame ids (direct) */\n children: Set<FrameId>;\n /** Last-seen CDP Frame metadata for this id (may be a shell if never seen) */\n lastSeen?: Protocol.Page.Frame;\n\n /** Owning session id (CDP child session for OOPIF, top-level session for same-process) */\n ownerSessionId?: SessionId;\n\n /**\n * The backendNodeId of the <iframe> element **in the parent document** that hosts this frame.\n * Useful for building absolute XPath prefixes or DOM scoping in the parent session.\n */\n ownerBackendNodeId?: number;\n};\n\n/** Minimal “shell” CDP frame used when we haven’t yet seen a real Frame from events. */\nfunction shellFrame(id: FrameId): Protocol.Page.Frame {\n return {\n id,\n loaderId: \"\",\n url: \"\",\n domainAndRegistry: \"\",\n securityOrigin: \"\",\n mimeType: \"text/html\",\n secureContextType: \"InsecureScheme\",\n crossOriginIsolatedContextType: \"NotIsolated\",\n gatedAPIFeatures: [],\n } as Protocol.Page.Frame;\n}\n\nexport class FrameRegistry {\n /** Owner target id (top-level target); informational only */\n private readonly ownerTargetId: string;\n\n /** Current main/root frame id (changes on root swaps) */\n private rootFrameId: FrameId;\n\n /** frameId → FrameInfo */\n private frames = new Map<FrameId, FrameInfo>();\n\n /** sessionId → Set<frameId> (inverse map for diagnostics/fast membership checks) */\n private framesBySession = new Map<SessionId, Set<FrameId>>();\n\n constructor(ownerTargetId: string, mainFrameId: FrameId) {\n this.ownerTargetId = ownerTargetId;\n this.rootFrameId = mainFrameId;\n this.ensureNode(mainFrameId);\n }\n\n // ---------------------- Mutators (called by Context/Page bridges) ----------------------\n\n /**\n * Record that a frame attached. If `parentId` is null and `frameId` differs from the current\n * root, this is a root swap and we rename the root id.\n *\n * IMPORTANT: The emitter's `sessionId` is the **owner** for the new/attached frame.\n */\n onFrameAttached(\n frameId: FrameId,\n parentId: FrameId | null,\n sessionId: SessionId,\n ): void {\n // Root swap (parentId === null for main frames).\n if (!parentId && frameId !== this.rootFrameId) {\n this.renameNodeId(this.rootFrameId, frameId);\n this.rootFrameId = frameId;\n // ownership moves to this session as well\n this.setOwnerSessionIdInternal(frameId, sessionId);\n return;\n }\n\n // Normal attach\n this.ensureNode(frameId);\n if (parentId) this.ensureNode(parentId);\n\n const info = this.frames.get(frameId)!;\n info.parentId = parentId ?? null;\n\n if (parentId) {\n this.frames.get(parentId)!.children.add(frameId);\n }\n\n // Ownership: the session that emitted frameAttached owns this frame.\n this.setOwnerSessionIdInternal(frameId, sessionId);\n }\n\n /**\n * Record a navigation with the full CDP `Frame`. Also updates ownership based on the emitting\n * session id. Handles root swap if the navigated frame is the new main (no parentId).\n */\n onFrameNavigated(frame: Protocol.Page.Frame, sessionId: SessionId): void {\n this.ensureNode(frame.id);\n const info = this.frames.get(frame.id)!;\n info.lastSeen = frame;\n\n // Ownership follows the session that reported the navigation\n this.setOwnerSessionIdInternal(frame.id, sessionId);\n\n // If this frame has no parent, it might be the (new) main/root\n if (!(\"parentId\" in frame) || !frame.parentId) {\n if (frame.id !== this.rootFrameId) {\n // carry ordinal semantics by renaming the root id\n this.renameNodeId(this.rootFrameId, frame.id);\n this.rootFrameId = frame.id;\n }\n }\n }\n\n onNavigatedWithinDocument(\n frameId: FrameId,\n url: string,\n sessionId: SessionId,\n ): void {\n this.ensureNode(frameId);\n const info = this.frames.get(frameId)!;\n const lastSeen = info.lastSeen ?? shellFrame(frameId);\n info.lastSeen = { ...lastSeen, url };\n this.setOwnerSessionIdInternal(frameId, sessionId);\n }\n\n /**\n * Record that a frame detached. If `reason !== \"swap\"`, remove the subtree from the graph,\n * and clean the inverse maps. For “swap” we keep the node to preserve continuity.\n */\n onFrameDetached(\n frameId: FrameId,\n reason: \"remove\" | \"swap\" | string = \"remove\",\n ): void {\n if (reason === \"swap\") return;\n\n // Collect subtree starting from frameId.\n const toRemove: FrameId[] = [];\n const collect = (fid: FrameId) => {\n toRemove.push(fid);\n const kids = this.frames.get(fid)?.children ?? new Set<FrameId>();\n for (const k of kids) collect(k);\n };\n collect(frameId);\n\n // Remove nodes, fix parents and inverse maps\n for (const fid of toRemove) {\n const info = this.frames.get(fid);\n if (!info) continue;\n\n // unlink from parent\n if (info.parentId) {\n const p = this.frames.get(info.parentId);\n p?.children.delete(fid);\n }\n\n // unlink inverse session map\n if (info.ownerSessionId) {\n const bag = this.framesBySession.get(info.ownerSessionId);\n bag?.delete(fid);\n if (bag && bag.size === 0)\n this.framesBySession.delete(info.ownerSessionId);\n }\n\n this.frames.delete(fid);\n }\n\n // Guard root if we removed it; assign a placeholder root if needed\n if (!this.frames.has(this.rootFrameId)) {\n // Choose an arbitrary remaining node as root\n const iter = this.frames.keys().next();\n if (!iter.done) this.rootFrameId = iter.value;\n }\n }\n\n /**\n * An adopted OOPIF child session was created whose **main** frame id equals the parent iframe’s frameId.\n * We mark the entire child subtree as owned by `childSessionId`.\n * (Topology edges remain aligned by the parent session’s `frameAttached` events.)\n */\n adoptChildSession(\n childSessionId: SessionId,\n childMainFrameId: FrameId,\n ): void {\n // The child session will emit its own navigations/attachments; as a seed,\n // mark the root frame as owned by the child session.\n this.setOwnerSessionIdInternal(childMainFrameId, childSessionId);\n }\n\n /**\n * Seed topology and ownership from an existing `Page.getFrameTree` snapshot, typically right after\n * a session is attached. This is a best-effort: we record frames and set the provided `sessionId`\n * as owner for the subtree **if** an owner isn't already set.\n */\n seedFromFrameTree(\n sessionId: SessionId,\n frameTree: Protocol.Page.FrameTree,\n ): void {\n const walk = (tree: Protocol.Page.FrameTree, parent: FrameId | null) => {\n this.ensureNode(tree.frame.id);\n // topology\n this.frames.get(tree.frame.id)!.parentId = parent;\n if (parent) this.frames.get(parent)!.children.add(tree.frame.id);\n // last-seen frame\n this.frames.get(tree.frame.id)!.lastSeen = tree.frame;\n // ownership (only if unknown)\n if (!this.frames.get(tree.frame.id)!.ownerSessionId) {\n this.setOwnerSessionIdInternal(tree.frame.id, sessionId);\n }\n for (const c of tree.childFrames ?? []) walk(c, tree.frame.id);\n };\n walk(frameTree, null);\n }\n\n /**\n * Set the backendNodeId of the `<iframe>` element for a child frame **as seen from its parent**.\n * This is useful for building absolute XPath prefixes later (from the parent document).\n */\n setOwnerBackendNodeId(childFrameId: FrameId, backendNodeId: number): void {\n this.ensureNode(childFrameId);\n this.frames.get(childFrameId)!.ownerBackendNodeId = backendNodeId;\n }\n\n // ---------------------- Readers (consumed by Page/snapshot/locators) ----------------------\n\n mainFrameId(): FrameId {\n return this.rootFrameId;\n }\n\n /**\n * Return the owner session id for this frame. If unknown, returns `undefined`.\n */\n getOwnerSessionId(frameId: FrameId): SessionId | undefined {\n return this.frames.get(frameId)?.ownerSessionId;\n }\n\n /**\n * Return the owner backendNodeId (iframe element) if recorded.\n * This is in the **parent** document; pair it with `getParent`.\n */\n getOwnerBackendNodeId(frameId: FrameId): number | undefined {\n return this.frames.get(frameId)?.ownerBackendNodeId;\n }\n\n /**\n * Return the parent frame id, or null for root/unknown.\n */\n getParent(frameId: FrameId): FrameId | null {\n return this.frames.get(frameId)?.parentId ?? null;\n }\n\n /**\n * List frame ids in root-first DFS order (same shape as CDP’s FrameTree traversal).\n */\n listAllFrames(): FrameId[] {\n const out: FrameId[] = [];\n const dfs = (fid: FrameId) => {\n out.push(fid);\n const kids = this.frames.get(fid)?.children ?? new Set<FrameId>();\n for (const k of kids) dfs(k);\n };\n if (this.frames.has(this.rootFrameId)) dfs(this.rootFrameId);\n return out;\n }\n\n /**\n * Serialize to `Protocol.Page.FrameTree` starting at the given root id (typically mainFrameId()).\n */\n asProtocolFrameTree(rootId: FrameId): Protocol.Page.FrameTree {\n const build = (fid: FrameId): Protocol.Page.FrameTree => {\n const info = this.frames.get(fid);\n const frame = info?.lastSeen ?? shellFrame(fid);\n\n const kids = info?.children ?? new Set<FrameId>();\n const childFrames = kids.size\n ? [...kids].map((k) => build(k))\n : undefined;\n\n return childFrames ? { frame, childFrames } : { frame };\n };\n\n return build(rootId);\n }\n\n /**\n * For diagnostics: return the current owner sessions for a frame id (0..n),\n * usually 0 or 1, but helpful to see potential inconsistencies during wiring.\n */\n sessionsForFrame(frameId: FrameId): SessionId[] {\n const info = this.frames.get(frameId);\n return info?.ownerSessionId ? [info.ownerSessionId] : [];\n }\n\n /**\n * For diagnostics: return current frame set per session.\n */\n framesForSession(sessionId: SessionId): FrameId[] {\n return [...(this.framesBySession.get(sessionId) ?? new Set())];\n }\n\n // ---------------------- Internal helpers ----------------------\n\n private ensureNode(fid: FrameId): void {\n if (this.frames.has(fid)) return;\n this.frames.set(fid, {\n parentId: null,\n children: new Set<FrameId>(),\n lastSeen: shellFrame(fid),\n ownerSessionId: undefined,\n ownerBackendNodeId: undefined,\n });\n }\n\n private renameNodeId(oldId: FrameId, newId: FrameId): void {\n if (oldId === newId) return;\n this.ensureNode(oldId);\n\n const info = this.frames.get(oldId)!;\n\n // Move info under new id\n this.frames.delete(oldId);\n this.frames.set(newId, { ...info });\n\n // Fix parent’s children set\n if (info.parentId) {\n const p = this.frames.get(info.parentId);\n if (p) {\n p.children.delete(oldId);\n p.children.add(newId);\n }\n }\n\n // Fix children’s parent pointers\n for (const c of info.children) {\n const ci = this.frames.get(c);\n if (ci) ci.parentId = newId;\n }\n\n // Fix inverse map (session -> frames)\n if (info.ownerSessionId) {\n const bag = this.framesBySession.get(info.ownerSessionId);\n if (bag) {\n bag.delete(oldId);\n bag.add(newId);\n }\n }\n\n // If root moved, keep the root id updated is handled by caller\n }\n\n private setOwnerSessionIdInternal(\n frameId: FrameId,\n sessionId: SessionId,\n ): void {\n this.ensureNode(frameId);\n const info = this.frames.get(frameId)!;\n\n // If the owner is unchanged, do nothing\n if (info.ownerSessionId === sessionId) return;\n\n // Remove from previous owner bag\n if (info.ownerSessionId) {\n const prev = this.framesBySession.get(info.ownerSessionId);\n prev?.delete(frameId);\n if (prev && prev.size === 0)\n this.framesBySession.delete(info.ownerSessionId);\n }\n\n // Set new owner and update bag\n info.ownerSessionId = sessionId;\n const bag = this.framesBySession.get(sessionId) ?? new Set<FrameId>();\n bag.add(frameId);\n this.framesBySession.set(sessionId, bag);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"frameRegistry.js","sourceRoot":"","sources":["../../../../../lib/v3/understudy/frameRegistry.ts"],"names":[],"mappings":"AA0CA,wFAAwF;AACxF,SAAS,UAAU,CAAC,EAAW;IAC7B,OAAO;QACL,EAAE;QACF,QAAQ,EAAE,EAAE;QACZ,GAAG,EAAE,EAAE;QACP,iBAAiB,EAAE,EAAE;QACrB,cAAc,EAAE,EAAE;QAClB,QAAQ,EAAE,WAAW;QACrB,iBAAiB,EAAE,gBAAgB;QACnC,8BAA8B,EAAE,aAAa;QAC7C,gBAAgB,EAAE,EAAE;KACE,CAAC;AAC3B,CAAC;AAED,MAAM,OAAO,aAAa;IACxB,6DAA6D;IAC5C,aAAa,CAAS;IAEvC,yDAAyD;IACjD,WAAW,CAAU;IAE7B,0BAA0B;IAClB,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE/C,oFAAoF;IAC5E,eAAe,GAAG,IAAI,GAAG,EAA2B,CAAC;IAE7D,YAAY,aAAqB,EAAE,WAAoB;QACrD,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC/B,CAAC;IAED,0FAA0F;IAE1F;;;;;OAKG;IACH,eAAe,CACb,OAAgB,EAChB,QAAwB,EACxB,SAAoB;QAEpB,iDAAiD;QACjD,IAAI,CAAC,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YAC9C,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YAC7C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC;YAC3B,0CAA0C;YAC1C,IAAI,CAAC,yBAAyB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;YACnD,OAAO;QACT,CAAC;QAED,gBAAgB;QAChB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,QAAQ;YAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAExC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC;QACvC,IAAI,CAAC,QAAQ,GAAG,QAAQ,IAAI,IAAI,CAAC;QAEjC,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnD,CAAC;QAED,qEAAqE;QACrE,IAAI,CAAC,yBAAyB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACrD,CAAC;IAED;;;OAGG;IACH,gBAAgB,CAAC,KAA0B,EAAE,SAAoB;QAC/D,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAE,CAAC;QACxC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QAEtB,6DAA6D;QAC7D,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAEpD,+DAA+D;QAC/D,IAAI,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC9C,IAAI,KAAK,CAAC,EAAE,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;gBAClC,kDAAkD;gBAClD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;gBAC9C,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC,EAAE,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,yBAAyB,CACvB,OAAgB,EAChB,GAAW,EACX,SAAoB;QAEpB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,GAAG,EAAE,GAAG,QAAQ,EAAE,GAAG,EAAE,CAAC;QACrC,IAAI,CAAC,yBAAyB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACrD,CAAC;IAED;;;OAGG;IACH,eAAe,CACb,OAAgB,EAChB,SAAqC,QAAQ;QAE7C,IAAI,MAAM,KAAK,MAAM;YAAE,OAAO;QAE9B,yCAAyC;QACzC,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,CAAC,GAAY,EAAE,EAAE;YAC/B,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,QAAQ,IAAI,IAAI,GAAG,EAAW,CAAC;YAClE,KAAK,MAAM,CAAC,IAAI,IAAI;gBAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC;QACF,OAAO,CAAC,OAAO,CAAC,CAAC;QAEjB,6CAA6C;QAC7C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,IAAI;gBAAE,SAAS;YAEpB,qBAAqB;YACrB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACzC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1B,CAAC;YAED,6BAA6B;YAC7B,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBACxB,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC1D,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjB,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC;oBACvB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACrD,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QAED,mEAAmE;QACnE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YACvC,6CAA6C;YAC7C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,IAAI;gBAAE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC;QAChD,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CACf,cAAyB,EACzB,gBAAyB;QAEzB,0EAA0E;QAC1E,qDAAqD;QACrD,IAAI,CAAC,yBAAyB,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;IACnE,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CACf,SAAoB,EACpB,SAAkC;QAElC,MAAM,IAAI,GAAG,CAAC,IAA6B,EAAE,MAAsB,EAAE,EAAE;YACrE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAE,CAAC;YAC7C,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC;YACrC,MAAM,UAAU,GACd,MAAM,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,IAAI,cAAc,IAAI,IAAI,CAAC;YAE1D,WAAW;YACX,IAAI,cAAc,IAAI,cAAc,KAAK,UAAU,EAAE,CAAC;gBACpD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClE,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,UAAU,CAAC;YAC3B,IAAI,UAAU,EAAE,CAAC;gBACf,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;gBAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAC3D,CAAC;YACD,kBAAkB;YAClB,IAAI,CAAC,QAAQ;gBACX,UAAU,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ;oBAChC,CAAC,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE;oBACzC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;YACjB,8BAA8B;YAC9B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACzB,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;YAC3D,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,IAAI,EAAE;gBAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjE,CAAC,CAAC;QACF,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACxB,CAAC;IAED;;;OAGG;IACH,qBAAqB,CAAC,YAAqB,EAAE,aAAqB;QAChE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAE,CAAC,kBAAkB,GAAG,aAAa,CAAC;IACpE,CAAC;IAED,6FAA6F;IAE7F,WAAW;QACT,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,iBAAiB,CAAC,OAAgB;QAChC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,cAAc,CAAC;IAClD,CAAC;IAED;;;OAGG;IACH,qBAAqB,CAAC,OAAgB;QACpC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,OAAgB;QACxB,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,QAAQ,IAAI,IAAI,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,aAAa;QACX,MAAM,GAAG,GAAc,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,CAAC,GAAY,EAAE,EAAE;YAC3B,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACd,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,QAAQ,IAAI,IAAI,GAAG,EAAW,CAAC;YAClE,KAAK,MAAM,CAAC,IAAI,IAAI;gBAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC,CAAC;QACF,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC7D,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,MAAe;QACjC,MAAM,KAAK,GAAG,CAAC,GAAY,EAA2B,EAAE;YACtD,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,KAAK,GAAG,IAAI,EAAE,QAAQ,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;YAEhD,MAAM,IAAI,GAAG,IAAI,EAAE,QAAQ,IAAI,IAAI,GAAG,EAAW,CAAC;YAClD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI;gBAC3B,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAChC,CAAC,CAAC,SAAS,CAAC;YAEd,OAAO,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QAC1D,CAAC,CAAC;QAEF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,gBAAgB,CAAC,OAAgB;QAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtC,OAAO,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3D,CAAC;IAED;;OAEG;IACH,gBAAgB,CAAC,SAAoB;QACnC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,iEAAiE;IAEzD,UAAU,CAAC,GAAY;QAC7B,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QACjC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;YACnB,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,IAAI,GAAG,EAAW;YAC5B,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC;YACzB,cAAc,EAAE,SAAS;YACzB,kBAAkB,EAAE,SAAS;SAC9B,CAAC,CAAC;IACL,CAAC;IAEO,YAAY,CAAC,KAAc,EAAE,KAAc;QACjD,IAAI,KAAK,KAAK,KAAK;YAAE,OAAO;QAC5B,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAEvB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC;QAErC,yBAAyB;QACzB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;QAEpC,4BAA4B;QAC5B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACzC,IAAI,CAAC,EAAE,CAAC;gBACN,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACzB,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,iCAAiC;QACjC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,EAAE;gBAAE,EAAE,CAAC,QAAQ,GAAG,KAAK,CAAC;QAC9B,CAAC;QAED,sCAAsC;QACtC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC1D,IAAI,GAAG,EAAE,CAAC;gBACR,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAClB,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;QAED,+DAA+D;IACjE,CAAC;IAEO,yBAAyB,CAC/B,OAAgB,EAChB,SAAoB;QAEpB,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAE,CAAC;QAEvC,wCAAwC;QACxC,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS;YAAE,OAAO;QAE9C,iCAAiC;QACjC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC3D,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YACtB,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;gBACzB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACrD,CAAC;QAED,+BAA+B;QAC/B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAAW,CAAC;QACtE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACjB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IAC3C,CAAC;CACF","sourcesContent":["// lib/v3/understudy/frameRegistry.ts\nimport type { Protocol } from \"devtools-protocol\";\n\n/**\n * FrameRegistry\n *\n * Purpose:\n * A single, authoritative source of truth for **both**:\n * 1) Frame topology (parent/children, current main/root id, last-seen CDP `Frame`)\n * 2) Frame → Session ownership (which CDP session owns a given frameId)\n * 3) Optional iframe-owner metadata (backendNodeId of the <iframe> element in the parent doc)\n *\n *\n * Model:\n * - This class is **CDP-agnostic**; it stores **sessionId strings** (not session objects).\n * - Context bridges (wiring Target/Page events) must call the mutators below (onAttached,\n * onNavigated, onDetached, adoptChildSession, seedFromFrameTree, setOwnerBackendNodeId).\n * - Consumers ask read APIs (getOwnerSessionId, getParent, asProtocolFrameTree, listAll, …)\n * and never probe ownership at run time.\n */\n\ntype FrameId = string;\ntype SessionId = string;\n\ntype FrameInfo = {\n /** Parent frame id, or null for root */\n parentId: FrameId | null;\n /** Children frame ids (direct) */\n children: Set<FrameId>;\n /** Last-seen CDP Frame metadata for this id (may be a shell if never seen) */\n lastSeen?: Protocol.Page.Frame;\n\n /** Owning session id (CDP child session for OOPIF, top-level session for same-process) */\n ownerSessionId?: SessionId;\n\n /**\n * The backendNodeId of the <iframe> element **in the parent document** that hosts this frame.\n * Useful for building absolute XPath prefixes or DOM scoping in the parent session.\n */\n ownerBackendNodeId?: number;\n};\n\n/** Minimal “shell” CDP frame used when we haven’t yet seen a real Frame from events. */\nfunction shellFrame(id: FrameId): Protocol.Page.Frame {\n return {\n id,\n loaderId: \"\",\n url: \"\",\n domainAndRegistry: \"\",\n securityOrigin: \"\",\n mimeType: \"text/html\",\n secureContextType: \"InsecureScheme\",\n crossOriginIsolatedContextType: \"NotIsolated\",\n gatedAPIFeatures: [],\n } as Protocol.Page.Frame;\n}\n\nexport class FrameRegistry {\n /** Owner target id (top-level target); informational only */\n private readonly ownerTargetId: string;\n\n /** Current main/root frame id (changes on root swaps) */\n private rootFrameId: FrameId;\n\n /** frameId → FrameInfo */\n private frames = new Map<FrameId, FrameInfo>();\n\n /** sessionId → Set<frameId> (inverse map for diagnostics/fast membership checks) */\n private framesBySession = new Map<SessionId, Set<FrameId>>();\n\n constructor(ownerTargetId: string, mainFrameId: FrameId) {\n this.ownerTargetId = ownerTargetId;\n this.rootFrameId = mainFrameId;\n this.ensureNode(mainFrameId);\n }\n\n // ---------------------- Mutators (called by Context/Page bridges) ----------------------\n\n /**\n * Record that a frame attached. If `parentId` is null and `frameId` differs from the current\n * root, this is a root swap and we rename the root id.\n *\n * IMPORTANT: The emitter's `sessionId` is the **owner** for the new/attached frame.\n */\n onFrameAttached(\n frameId: FrameId,\n parentId: FrameId | null,\n sessionId: SessionId,\n ): void {\n // Root swap (parentId === null for main frames).\n if (!parentId && frameId !== this.rootFrameId) {\n this.renameNodeId(this.rootFrameId, frameId);\n this.rootFrameId = frameId;\n // ownership moves to this session as well\n this.setOwnerSessionIdInternal(frameId, sessionId);\n return;\n }\n\n // Normal attach\n this.ensureNode(frameId);\n if (parentId) this.ensureNode(parentId);\n\n const info = this.frames.get(frameId)!;\n info.parentId = parentId ?? null;\n\n if (parentId) {\n this.frames.get(parentId)!.children.add(frameId);\n }\n\n // Ownership: the session that emitted frameAttached owns this frame.\n this.setOwnerSessionIdInternal(frameId, sessionId);\n }\n\n /**\n * Record a navigation with the full CDP `Frame`. Also updates ownership based on the emitting\n * session id. Handles root swap if the navigated frame is the new main (no parentId).\n */\n onFrameNavigated(frame: Protocol.Page.Frame, sessionId: SessionId): void {\n this.ensureNode(frame.id);\n const info = this.frames.get(frame.id)!;\n info.lastSeen = frame;\n\n // Ownership follows the session that reported the navigation\n this.setOwnerSessionIdInternal(frame.id, sessionId);\n\n // If this frame has no parent, it might be the (new) main/root\n if (!(\"parentId\" in frame) || !frame.parentId) {\n if (frame.id !== this.rootFrameId) {\n // carry ordinal semantics by renaming the root id\n this.renameNodeId(this.rootFrameId, frame.id);\n this.rootFrameId = frame.id;\n }\n }\n }\n\n onNavigatedWithinDocument(\n frameId: FrameId,\n url: string,\n sessionId: SessionId,\n ): void {\n this.ensureNode(frameId);\n const info = this.frames.get(frameId)!;\n const lastSeen = info.lastSeen ?? shellFrame(frameId);\n info.lastSeen = { ...lastSeen, url };\n this.setOwnerSessionIdInternal(frameId, sessionId);\n }\n\n /**\n * Record that a frame detached. If `reason !== \"swap\"`, remove the subtree from the graph,\n * and clean the inverse maps. For “swap” we keep the node to preserve continuity.\n */\n onFrameDetached(\n frameId: FrameId,\n reason: \"remove\" | \"swap\" | string = \"remove\",\n ): void {\n if (reason === \"swap\") return;\n\n // Collect subtree starting from frameId.\n const toRemove: FrameId[] = [];\n const collect = (fid: FrameId) => {\n toRemove.push(fid);\n const kids = this.frames.get(fid)?.children ?? new Set<FrameId>();\n for (const k of kids) collect(k);\n };\n collect(frameId);\n\n // Remove nodes, fix parents and inverse maps\n for (const fid of toRemove) {\n const info = this.frames.get(fid);\n if (!info) continue;\n\n // unlink from parent\n if (info.parentId) {\n const p = this.frames.get(info.parentId);\n p?.children.delete(fid);\n }\n\n // unlink inverse session map\n if (info.ownerSessionId) {\n const bag = this.framesBySession.get(info.ownerSessionId);\n bag?.delete(fid);\n if (bag && bag.size === 0)\n this.framesBySession.delete(info.ownerSessionId);\n }\n\n this.frames.delete(fid);\n }\n\n // Guard root if we removed it; assign a placeholder root if needed\n if (!this.frames.has(this.rootFrameId)) {\n // Choose an arbitrary remaining node as root\n const iter = this.frames.keys().next();\n if (!iter.done) this.rootFrameId = iter.value;\n }\n }\n\n /**\n * An adopted OOPIF child session was created whose **main** frame id equals the parent iframe’s frameId.\n * We mark the entire child subtree as owned by `childSessionId`.\n * (Topology edges remain aligned by the parent session’s `frameAttached` events.)\n */\n adoptChildSession(\n childSessionId: SessionId,\n childMainFrameId: FrameId,\n ): void {\n // The child session will emit its own navigations/attachments; as a seed,\n // mark the root frame as owned by the child session.\n this.setOwnerSessionIdInternal(childMainFrameId, childSessionId);\n }\n\n /**\n * Seed topology and ownership from an existing `Page.getFrameTree` snapshot, typically right after\n * a session is attached. This is a best-effort: we record frames and set the provided `sessionId`\n * as owner for the subtree **if** an owner isn't already set.\n */\n seedFromFrameTree(\n sessionId: SessionId,\n frameTree: Protocol.Page.FrameTree,\n ): void {\n const walk = (tree: Protocol.Page.FrameTree, parent: FrameId | null) => {\n this.ensureNode(tree.frame.id);\n const info = this.frames.get(tree.frame.id)!;\n const previousParent = info.parentId;\n const nextParent =\n parent ?? tree.frame.parentId ?? previousParent ?? null;\n\n // topology\n if (previousParent && previousParent !== nextParent) {\n this.frames.get(previousParent)?.children.delete(tree.frame.id);\n }\n info.parentId = nextParent;\n if (nextParent) {\n this.ensureNode(nextParent);\n this.frames.get(nextParent)!.children.add(tree.frame.id);\n }\n // last-seen frame\n info.lastSeen =\n nextParent && !tree.frame.parentId\n ? { ...tree.frame, parentId: nextParent }\n : tree.frame;\n // ownership (only if unknown)\n if (!info.ownerSessionId) {\n this.setOwnerSessionIdInternal(tree.frame.id, sessionId);\n }\n for (const c of tree.childFrames ?? []) walk(c, tree.frame.id);\n };\n walk(frameTree, null);\n }\n\n /**\n * Set the backendNodeId of the `<iframe>` element for a child frame **as seen from its parent**.\n * This is useful for building absolute XPath prefixes later (from the parent document).\n */\n setOwnerBackendNodeId(childFrameId: FrameId, backendNodeId: number): void {\n this.ensureNode(childFrameId);\n this.frames.get(childFrameId)!.ownerBackendNodeId = backendNodeId;\n }\n\n // ---------------------- Readers (consumed by Page/snapshot/locators) ----------------------\n\n mainFrameId(): FrameId {\n return this.rootFrameId;\n }\n\n /**\n * Return the owner session id for this frame. If unknown, returns `undefined`.\n */\n getOwnerSessionId(frameId: FrameId): SessionId | undefined {\n return this.frames.get(frameId)?.ownerSessionId;\n }\n\n /**\n * Return the owner backendNodeId (iframe element) if recorded.\n * This is in the **parent** document; pair it with `getParent`.\n */\n getOwnerBackendNodeId(frameId: FrameId): number | undefined {\n return this.frames.get(frameId)?.ownerBackendNodeId;\n }\n\n /**\n * Return the parent frame id, or null for root/unknown.\n */\n getParent(frameId: FrameId): FrameId | null {\n return this.frames.get(frameId)?.parentId ?? null;\n }\n\n /**\n * List frame ids in root-first DFS order (same shape as CDP’s FrameTree traversal).\n */\n listAllFrames(): FrameId[] {\n const out: FrameId[] = [];\n const dfs = (fid: FrameId) => {\n out.push(fid);\n const kids = this.frames.get(fid)?.children ?? new Set<FrameId>();\n for (const k of kids) dfs(k);\n };\n if (this.frames.has(this.rootFrameId)) dfs(this.rootFrameId);\n return out;\n }\n\n /**\n * Serialize to `Protocol.Page.FrameTree` starting at the given root id (typically mainFrameId()).\n */\n asProtocolFrameTree(rootId: FrameId): Protocol.Page.FrameTree {\n const build = (fid: FrameId): Protocol.Page.FrameTree => {\n const info = this.frames.get(fid);\n const frame = info?.lastSeen ?? shellFrame(fid);\n\n const kids = info?.children ?? new Set<FrameId>();\n const childFrames = kids.size\n ? [...kids].map((k) => build(k))\n : undefined;\n\n return childFrames ? { frame, childFrames } : { frame };\n };\n\n return build(rootId);\n }\n\n /**\n * For diagnostics: return the current owner sessions for a frame id (0..n),\n * usually 0 or 1, but helpful to see potential inconsistencies during wiring.\n */\n sessionsForFrame(frameId: FrameId): SessionId[] {\n const info = this.frames.get(frameId);\n return info?.ownerSessionId ? [info.ownerSessionId] : [];\n }\n\n /**\n * For diagnostics: return current frame set per session.\n */\n framesForSession(sessionId: SessionId): FrameId[] {\n return [...(this.framesBySession.get(sessionId) ?? new Set())];\n }\n\n // ---------------------- Internal helpers ----------------------\n\n private ensureNode(fid: FrameId): void {\n if (this.frames.has(fid)) return;\n this.frames.set(fid, {\n parentId: null,\n children: new Set<FrameId>(),\n lastSeen: shellFrame(fid),\n ownerSessionId: undefined,\n ownerBackendNodeId: undefined,\n });\n }\n\n private renameNodeId(oldId: FrameId, newId: FrameId): void {\n if (oldId === newId) return;\n this.ensureNode(oldId);\n\n const info = this.frames.get(oldId)!;\n\n // Move info under new id\n this.frames.delete(oldId);\n this.frames.set(newId, { ...info });\n\n // Fix parent’s children set\n if (info.parentId) {\n const p = this.frames.get(info.parentId);\n if (p) {\n p.children.delete(oldId);\n p.children.add(newId);\n }\n }\n\n // Fix children’s parent pointers\n for (const c of info.children) {\n const ci = this.frames.get(c);\n if (ci) ci.parentId = newId;\n }\n\n // Fix inverse map (session -> frames)\n if (info.ownerSessionId) {\n const bag = this.framesBySession.get(info.ownerSessionId);\n if (bag) {\n bag.delete(oldId);\n bag.add(newId);\n }\n }\n\n // If root moved, keep the root id updated is handled by caller\n }\n\n private setOwnerSessionIdInternal(\n frameId: FrameId,\n sessionId: SessionId,\n ): void {\n this.ensureNode(frameId);\n const info = this.frames.get(frameId)!;\n\n // If the owner is unchanged, do nothing\n if (info.ownerSessionId === sessionId) return;\n\n // Remove from previous owner bag\n if (info.ownerSessionId) {\n const prev = this.framesBySession.get(info.ownerSessionId);\n prev?.delete(frameId);\n if (prev && prev.size === 0)\n this.framesBySession.delete(info.ownerSessionId);\n }\n\n // Set new owner and update bag\n info.ownerSessionId = sessionId;\n const bag = this.framesBySession.get(sessionId) ?? new Set<FrameId>();\n bag.add(frameId);\n this.framesBySession.set(sessionId, bag);\n }\n}\n"]}
|
package/dist/esm/lib/v3/v3.d.ts
CHANGED
|
@@ -111,6 +111,7 @@ export declare class V3 {
|
|
|
111
111
|
private mergeAgentMetricsWithLocalFallback;
|
|
112
112
|
private updateAgentMetricsFromUsage;
|
|
113
113
|
private resolveLlmClient;
|
|
114
|
+
private resolveDefaultAgentMode;
|
|
114
115
|
private beginAgentReplayRecording;
|
|
115
116
|
private endAgentReplayRecording;
|
|
116
117
|
private discardAgentReplayRecording;
|
package/dist/esm/lib/v3/v3.js
CHANGED
|
@@ -57,6 +57,7 @@ import { bindInstanceLogger, unbindInstanceLogger, withInstanceLogContext, } fro
|
|
|
57
57
|
import { cleanupLocalBrowser } from "./shutdown/cleanupLocal.js";
|
|
58
58
|
import { startShutdownSupervisor } from "./shutdown/supervisorClient.js";
|
|
59
59
|
import { resolveTools } from "./mcp/utils.js";
|
|
60
|
+
import { HYBRID_CAPABLE_MODEL_PATTERNS } from "./types/private/agent.js";
|
|
60
61
|
import { AVAILABLE_CUA_MODELS, defaultExtractSchema, V3FunctionName, CuaModelRequiredError, StagehandInvalidArgumentError, StagehandNotInitializedError, MissingEnvironmentVariableError, StagehandInitError, } from "./types/public/index.js";
|
|
61
62
|
import { V3Context } from "./understudy/context.js";
|
|
62
63
|
import { resolveModel } from "../modelUtils.js";
|
|
@@ -511,6 +512,11 @@ let V3 = (() => {
|
|
|
511
512
|
this.overrideLlmClients.set(cacheKey, client);
|
|
512
513
|
return client;
|
|
513
514
|
}
|
|
515
|
+
resolveDefaultAgentMode(model) {
|
|
516
|
+
const modelName = extractModelName(model) ?? this.modelName;
|
|
517
|
+
const matchedPattern = HYBRID_CAPABLE_MODEL_PATTERNS.find((pattern) => modelName.includes(pattern));
|
|
518
|
+
return matchedPattern ? "hybrid" : "dom";
|
|
519
|
+
}
|
|
514
520
|
beginAgentReplayRecording() {
|
|
515
521
|
this.agentCache.beginRecording();
|
|
516
522
|
}
|
|
@@ -1095,6 +1101,7 @@ let V3 = (() => {
|
|
|
1095
1101
|
model: options?.model,
|
|
1096
1102
|
timeout: options?.timeout,
|
|
1097
1103
|
selector: options?.selector,
|
|
1104
|
+
ignoreSelectors: options?.ignoreSelectors,
|
|
1098
1105
|
page,
|
|
1099
1106
|
};
|
|
1100
1107
|
let result;
|
|
@@ -1117,6 +1124,7 @@ let V3 = (() => {
|
|
|
1117
1124
|
this.addToHistory("extract", {
|
|
1118
1125
|
instruction,
|
|
1119
1126
|
selector: options?.selector,
|
|
1127
|
+
ignoreSelectors: options?.ignoreSelectors,
|
|
1120
1128
|
timeout: options?.timeout,
|
|
1121
1129
|
schema: historySchemaDescriptor,
|
|
1122
1130
|
}, result);
|
|
@@ -1146,6 +1154,7 @@ let V3 = (() => {
|
|
|
1146
1154
|
variables: options?.variables,
|
|
1147
1155
|
timeout: options?.timeout,
|
|
1148
1156
|
selector: options?.selector,
|
|
1157
|
+
ignoreSelectors: options?.ignoreSelectors,
|
|
1149
1158
|
page: page,
|
|
1150
1159
|
};
|
|
1151
1160
|
let results;
|
|
@@ -1164,6 +1173,8 @@ let V3 = (() => {
|
|
|
1164
1173
|
this.addToHistory("observe", {
|
|
1165
1174
|
instruction,
|
|
1166
1175
|
variables: options?.variables,
|
|
1176
|
+
selector: options?.selector,
|
|
1177
|
+
ignoreSelectors: options?.ignoreSelectors,
|
|
1167
1178
|
timeout: options?.timeout,
|
|
1168
1179
|
}, results);
|
|
1169
1180
|
return results;
|
|
@@ -1416,14 +1427,6 @@ let V3 = (() => {
|
|
|
1416
1427
|
*/
|
|
1417
1428
|
async prepareAgentExecution(options, instructionOrOptions, agentConfigSignature) {
|
|
1418
1429
|
// Note: experimental validation is done at the call site before this method
|
|
1419
|
-
// Warn if mode is not explicitly set (defaults to "dom")
|
|
1420
|
-
if (options?.mode === undefined) {
|
|
1421
|
-
this.logger({
|
|
1422
|
-
category: "agent",
|
|
1423
|
-
message: "Using agent in default DOM mode (legacy). Agent will default to 'hybrid' on an upcoming release for improved performance.\n → https://docs.stagehand.dev/v3/basics/agent\n",
|
|
1424
|
-
level: 0,
|
|
1425
|
-
});
|
|
1426
|
-
}
|
|
1427
1430
|
const tools = options?.integrations
|
|
1428
1431
|
? await resolveTools(options.integrations, options.tools)
|
|
1429
1432
|
: (options?.tools ?? {});
|
|
@@ -1431,7 +1434,8 @@ let V3 = (() => {
|
|
|
1431
1434
|
? this.resolveLlmClient(options.model)
|
|
1432
1435
|
: this.llmClient;
|
|
1433
1436
|
const resolvedExecutionModel = options?.executionModel ?? options?.model;
|
|
1434
|
-
const
|
|
1437
|
+
const resolvedMode = options?.mode ?? this.resolveDefaultAgentMode(options?.model);
|
|
1438
|
+
const handler = new V3AgentHandler(this, this.logger, agentLlmClient, resolvedExecutionModel, options?.systemPrompt, tools, resolvedMode, this.isCaptchaAutoSolveEnabled);
|
|
1435
1439
|
const resolvedOptions = typeof instructionOrOptions === "string"
|
|
1436
1440
|
? {
|
|
1437
1441
|
instruction: instructionOrOptions,
|
|
@@ -1470,10 +1474,8 @@ let V3 = (() => {
|
|
|
1470
1474
|
};
|
|
1471
1475
|
}
|
|
1472
1476
|
agent(options) {
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
? options.mode === "cua"
|
|
1476
|
-
: options?.cua === true;
|
|
1477
|
+
const isCuaMode = options?.mode === "cua" ||
|
|
1478
|
+
(options?.mode === undefined && options?.cua === true);
|
|
1477
1479
|
// Emit deprecation warning for cua: true
|
|
1478
1480
|
if (options?.cua === true) {
|
|
1479
1481
|
this.logger({
|
|
@@ -1483,13 +1485,15 @@ let V3 = (() => {
|
|
|
1483
1485
|
});
|
|
1484
1486
|
console.warn('[Stagehand] DEPRECATED: The "cua: true" option is deprecated. Use "mode: \'cua\'" instead.');
|
|
1485
1487
|
}
|
|
1488
|
+
const loggedMode = options?.mode ??
|
|
1489
|
+
(isCuaMode ? "cua" : this.resolveDefaultAgentMode(options?.model));
|
|
1486
1490
|
this.logger({
|
|
1487
1491
|
category: "agent",
|
|
1488
1492
|
message: "Creating v3 agent instance",
|
|
1489
1493
|
level: 1,
|
|
1490
1494
|
auxiliary: {
|
|
1491
1495
|
cua: { value: isCuaMode ? "true" : "false", type: "boolean" },
|
|
1492
|
-
mode: { value:
|
|
1496
|
+
mode: { value: loggedMode, type: "string" },
|
|
1493
1497
|
model: {
|
|
1494
1498
|
value: extractModelName(options?.model) ?? this.llmClient.modelName,
|
|
1495
1499
|
type: "string",
|