@browserbasehq/orca 3.2.1-preview.3 → 3.4.0-preview-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/dist/cjs/lib/inference.js +1 -8
  2. package/dist/cjs/lib/inference.js.map +1 -1
  3. package/dist/cjs/lib/prompt.js +3 -1
  4. package/dist/cjs/lib/prompt.js.map +1 -1
  5. package/dist/cjs/lib/v3/agent/AgentProvider.js +3 -0
  6. package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
  7. package/dist/cjs/lib/v3/agent/tools/fillFormVision.js +16 -12
  8. package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  9. package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
  10. package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
  11. package/dist/cjs/lib/v3/api.d.ts +1 -0
  12. package/dist/cjs/lib/v3/api.js +15 -3
  13. package/dist/cjs/lib/v3/api.js.map +1 -1
  14. package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js +12 -12
  15. package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
  16. package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js +48 -48
  17. package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
  18. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
  19. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js +1 -1
  20. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
  21. package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js +2 -2
  22. package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
  23. package/dist/cjs/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
  24. package/dist/cjs/lib/v3/dom/build/scriptV3Content.js +1 -1
  25. package/dist/cjs/lib/v3/dom/build/scriptV3Content.js.map +1 -1
  26. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.d.ts +24 -0
  27. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js +31 -0
  28. package/dist/cjs/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
  29. package/dist/cjs/lib/v3/handlers/extractHandler.js +3 -1
  30. package/dist/cjs/lib/v3/handlers/extractHandler.js.map +1 -1
  31. package/dist/cjs/lib/v3/handlers/observeHandler.js +2 -1
  32. package/dist/cjs/lib/v3/handlers/observeHandler.js.map +1 -1
  33. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +3 -5
  34. package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  35. package/dist/cjs/lib/v3/index.d.ts +1 -1
  36. package/dist/cjs/lib/v3/llm/CerebrasClient.js +1 -1
  37. package/dist/cjs/lib/v3/llm/CerebrasClient.js.map +1 -1
  38. package/dist/cjs/lib/v3/llm/GroqClient.js +1 -1
  39. package/dist/cjs/lib/v3/llm/GroqClient.js.map +1 -1
  40. package/dist/cjs/lib/v3/types/private/agent.d.ts +5 -0
  41. package/dist/cjs/lib/v3/types/private/agent.js +11 -0
  42. package/dist/cjs/lib/v3/types/private/agent.js.map +1 -1
  43. package/dist/cjs/lib/v3/types/private/handlers.d.ts +2 -0
  44. package/dist/cjs/lib/v3/types/private/handlers.js.map +1 -1
  45. package/dist/cjs/lib/v3/types/private/snapshot.d.ts +8 -0
  46. package/dist/cjs/lib/v3/types/private/snapshot.js.map +1 -1
  47. package/dist/cjs/lib/v3/types/public/agent.d.ts +2 -3
  48. package/dist/cjs/lib/v3/types/public/agent.js +3 -0
  49. package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
  50. package/dist/cjs/lib/v3/types/public/api.d.ts +7 -1
  51. package/dist/cjs/lib/v3/types/public/api.js +22 -2
  52. package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
  53. package/dist/cjs/lib/v3/types/public/methods.d.ts +2 -0
  54. package/dist/cjs/lib/v3/types/public/methods.js.map +1 -1
  55. package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
  56. package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
  57. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
  58. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js +268 -21
  59. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
  60. package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
  61. package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
  62. package/dist/cjs/lib/v3/understudy/frameRegistry.js +16 -5
  63. package/dist/cjs/lib/v3/understudy/frameRegistry.js.map +1 -1
  64. package/dist/cjs/lib/v3/v3.d.ts +1 -0
  65. package/dist/cjs/lib/v3/v3.js +18 -14
  66. package/dist/cjs/lib/v3/v3.js.map +1 -1
  67. package/dist/cjs/lib/version.d.ts +1 -1
  68. package/dist/cjs/lib/version.js +1 -1
  69. package/dist/cjs/lib/version.js.map +1 -1
  70. package/dist/cjs/tests/integration/observe-element-id-format.spec.js +130 -0
  71. package/dist/cjs/tests/integration/observe-element-id-format.spec.js.map +1 -0
  72. package/dist/cjs/tests/unit/agent-mode-routing.test.js +88 -0
  73. package/dist/cjs/tests/unit/agent-mode-routing.test.js.map +1 -0
  74. package/dist/cjs/tests/unit/agent-temperature.test.d.ts +1 -0
  75. package/dist/cjs/tests/unit/agent-temperature.test.js +191 -0
  76. package/dist/cjs/tests/unit/agent-temperature.test.js.map +1 -0
  77. package/dist/cjs/tests/unit/agent-variables-validation.test.d.ts +1 -0
  78. package/dist/cjs/tests/unit/agent-variables-validation.test.js +43 -0
  79. package/dist/cjs/tests/unit/agent-variables-validation.test.js.map +1 -0
  80. package/dist/cjs/tests/unit/api-client-observe-variables.test.js +49 -0
  81. package/dist/cjs/tests/unit/api-client-observe-variables.test.js.map +1 -1
  82. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js +60 -0
  83. package/dist/cjs/tests/unit/api-optional-model-api-key.test.js.map +1 -1
  84. package/dist/cjs/tests/unit/api-variables-schema.test.js +32 -0
  85. package/dist/cjs/tests/unit/api-variables-schema.test.js.map +1 -1
  86. package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
  87. package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js +60 -0
  88. package/dist/cjs/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
  89. package/dist/cjs/tests/unit/inference-temperature.test.d.ts +1 -0
  90. package/dist/cjs/tests/unit/inference-temperature.test.js +65 -0
  91. package/dist/cjs/tests/unit/inference-temperature.test.js.map +1 -0
  92. package/dist/cjs/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
  93. package/dist/cjs/tests/unit/openai-compatible-temperature.test.js +84 -0
  94. package/dist/cjs/tests/unit/openai-compatible-temperature.test.js.map +1 -0
  95. package/dist/cjs/tests/unit/prompt-observe-variables.test.js +6 -0
  96. package/dist/cjs/tests/unit/prompt-observe-variables.test.js.map +1 -1
  97. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +3 -0
  98. package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  99. package/dist/cjs/tests/unit/public-api/public-types.test.js.map +1 -1
  100. package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
  101. package/dist/cjs/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
  102. package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
  103. package/dist/cjs/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
  104. package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js +119 -9
  105. package/dist/cjs/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
  106. package/dist/cjs/tests/unit/timeout-handlers.test.js +36 -0
  107. package/dist/cjs/tests/unit/timeout-handlers.test.js.map +1 -1
  108. package/dist/esm/lib/inference.js +1 -8
  109. package/dist/esm/lib/inference.js.map +1 -1
  110. package/dist/esm/lib/prompt.js +3 -1
  111. package/dist/esm/lib/prompt.js.map +1 -1
  112. package/dist/esm/lib/v3/agent/AgentProvider.js +3 -0
  113. package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
  114. package/dist/esm/lib/v3/agent/tools/fillFormVision.js +16 -12
  115. package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
  116. package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js +0 -4
  117. package/dist/esm/lib/v3/agent/utils/validateExperimentalFeatures.js.map +1 -1
  118. package/dist/esm/lib/v3/api.d.ts +1 -0
  119. package/dist/esm/lib/v3/api.js +15 -3
  120. package/dist/esm/lib/v3/api.js.map +1 -1
  121. package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js +12 -12
  122. package/dist/esm/lib/v3/dom/build/a11yScripts.generated.js.map +1 -1
  123. package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js +48 -48
  124. package/dist/esm/lib/v3/dom/build/locatorScripts.generated.js.map +1 -1
  125. package/dist/esm/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -1
  126. package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js +1 -1
  127. package/dist/esm/lib/v3/dom/build/reRenderScriptContent.js.map +1 -1
  128. package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js +2 -2
  129. package/dist/esm/lib/v3/dom/build/screenshotScripts.generated.js.map +1 -1
  130. package/dist/esm/lib/v3/dom/build/scriptV3Content.d.ts +1 -1
  131. package/dist/esm/lib/v3/dom/build/scriptV3Content.js +1 -1
  132. package/dist/esm/lib/v3/dom/build/scriptV3Content.js.map +1 -1
  133. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.d.ts +24 -0
  134. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js +28 -0
  135. package/dist/esm/lib/v3/dom/build/selectorRuntime.generated.js.map +1 -0
  136. package/dist/esm/lib/v3/handlers/extractHandler.js +3 -1
  137. package/dist/esm/lib/v3/handlers/extractHandler.js.map +1 -1
  138. package/dist/esm/lib/v3/handlers/observeHandler.js +2 -1
  139. package/dist/esm/lib/v3/handlers/observeHandler.js.map +1 -1
  140. package/dist/esm/lib/v3/handlers/v3AgentHandler.js +3 -5
  141. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  142. package/dist/esm/lib/v3/index.d.ts +1 -1
  143. package/dist/esm/lib/v3/llm/CerebrasClient.js +1 -1
  144. package/dist/esm/lib/v3/llm/CerebrasClient.js.map +1 -1
  145. package/dist/esm/lib/v3/llm/GroqClient.js +1 -1
  146. package/dist/esm/lib/v3/llm/GroqClient.js.map +1 -1
  147. package/dist/esm/lib/v3/types/private/agent.d.ts +5 -0
  148. package/dist/esm/lib/v3/types/private/agent.js +10 -1
  149. package/dist/esm/lib/v3/types/private/agent.js.map +1 -1
  150. package/dist/esm/lib/v3/types/private/handlers.d.ts +2 -0
  151. package/dist/esm/lib/v3/types/private/handlers.js.map +1 -1
  152. package/dist/esm/lib/v3/types/private/snapshot.d.ts +8 -0
  153. package/dist/esm/lib/v3/types/private/snapshot.js.map +1 -1
  154. package/dist/esm/lib/v3/types/public/agent.d.ts +2 -3
  155. package/dist/esm/lib/v3/types/public/agent.js +3 -0
  156. package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
  157. package/dist/esm/lib/v3/types/public/api.d.ts +7 -1
  158. package/dist/esm/lib/v3/types/public/api.js +22 -2
  159. package/dist/esm/lib/v3/types/public/api.js.map +1 -1
  160. package/dist/esm/lib/v3/types/public/methods.d.ts +2 -0
  161. package/dist/esm/lib/v3/types/public/methods.js.map +1 -1
  162. package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js +21 -12
  163. package/dist/esm/lib/v3/understudy/a11y/snapshot/a11yTree.js.map +1 -1
  164. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.d.ts +11 -2
  165. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js +267 -22
  166. package/dist/esm/lib/v3/understudy/a11y/snapshot/capture.js.map +1 -1
  167. package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js +60 -7
  168. package/dist/esm/lib/v3/understudy/a11y/snapshot/domTree.js.map +1 -1
  169. package/dist/esm/lib/v3/understudy/frameRegistry.js +16 -5
  170. package/dist/esm/lib/v3/understudy/frameRegistry.js.map +1 -1
  171. package/dist/esm/lib/v3/v3.d.ts +1 -0
  172. package/dist/esm/lib/v3/v3.js +18 -14
  173. package/dist/esm/lib/v3/v3.js.map +1 -1
  174. package/dist/esm/lib/version.d.ts +1 -1
  175. package/dist/esm/lib/version.js +1 -1
  176. package/dist/esm/lib/version.js.map +1 -1
  177. package/dist/esm/tests/integration/observe-element-id-format.spec.d.ts +1 -0
  178. package/dist/esm/tests/integration/observe-element-id-format.spec.js +128 -0
  179. package/dist/esm/tests/integration/observe-element-id-format.spec.js.map +1 -0
  180. package/dist/esm/tests/unit/agent-mode-routing.test.d.ts +1 -0
  181. package/dist/esm/tests/unit/agent-mode-routing.test.js +86 -0
  182. package/dist/esm/tests/unit/agent-mode-routing.test.js.map +1 -0
  183. package/dist/esm/tests/unit/agent-temperature.test.d.ts +1 -0
  184. package/dist/esm/tests/unit/agent-temperature.test.js +189 -0
  185. package/dist/esm/tests/unit/agent-temperature.test.js.map +1 -0
  186. package/dist/esm/tests/unit/agent-variables-validation.test.d.ts +1 -0
  187. package/dist/esm/tests/unit/agent-variables-validation.test.js +41 -0
  188. package/dist/esm/tests/unit/agent-variables-validation.test.js.map +1 -0
  189. package/dist/esm/tests/unit/api-client-observe-variables.test.js +49 -0
  190. package/dist/esm/tests/unit/api-client-observe-variables.test.js.map +1 -1
  191. package/dist/esm/tests/unit/api-optional-model-api-key.test.js +60 -0
  192. package/dist/esm/tests/unit/api-optional-model-api-key.test.js.map +1 -1
  193. package/dist/esm/tests/unit/api-variables-schema.test.js +32 -0
  194. package/dist/esm/tests/unit/api-variables-schema.test.js.map +1 -1
  195. package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.d.ts +1 -0
  196. package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js +58 -0
  197. package/dist/esm/tests/unit/frame-registry-oopif-adoption.test.js.map +1 -0
  198. package/dist/esm/tests/unit/inference-temperature.test.d.ts +1 -0
  199. package/dist/esm/tests/unit/inference-temperature.test.js +63 -0
  200. package/dist/esm/tests/unit/inference-temperature.test.js.map +1 -0
  201. package/dist/esm/tests/unit/openai-compatible-temperature.test.d.ts +1 -0
  202. package/dist/esm/tests/unit/openai-compatible-temperature.test.js +82 -0
  203. package/dist/esm/tests/unit/openai-compatible-temperature.test.js.map +1 -0
  204. package/dist/esm/tests/unit/prompt-observe-variables.test.js +6 -0
  205. package/dist/esm/tests/unit/prompt-observe-variables.test.js.map +1 -1
  206. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +3 -0
  207. package/dist/esm/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
  208. package/dist/esm/tests/unit/public-api/public-types.test.js.map +1 -1
  209. package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js +106 -5
  210. package/dist/esm/tests/unit/snapshot-a11y-resolvers.test.js.map +1 -1
  211. package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js +20 -0
  212. package/dist/esm/tests/unit/snapshot-a11y-tree-utils.test.js.map +1 -1
  213. package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js +119 -9
  214. package/dist/esm/tests/unit/snapshot-capture-orchestration.test.js.map +1 -1
  215. package/dist/esm/tests/unit/timeout-handlers.test.js +36 -0
  216. package/dist/esm/tests/unit/timeout-handlers.test.js.map +1 -1
  217. package/package.json +10 -10
  218. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js +0 -56
  219. package/dist/cjs/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
  220. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js +0 -54
  221. package/dist/esm/tests/integration/agent-captcha-autosolve.spec.js.map +0 -1
  222. /package/dist/cjs/tests/integration/{agent-captcha-autosolve.spec.d.ts → observe-element-id-format.spec.d.ts} +0 -0
  223. /package/dist/{esm/tests/integration/agent-captcha-autosolve.spec.d.ts → cjs/tests/unit/agent-mode-routing.test.d.ts} +0 -0
@@ -169,7 +169,7 @@ async function domMapsForSession(session, frameId, pierce, encode, attemptOwnerL
169
169
  const { node, xpath } = stack.pop();
170
170
  if (node.backendNodeId) {
171
171
  const encId = encode(frameId, node.backendNodeId);
172
- tagNameMap[encId] = String(node.nodeName).toLowerCase();
172
+ tagNameMap[encId] = enrichedTagName(node);
173
173
  xpathMap[encId] = xpath || "/";
174
174
  const isScrollable = node?.isScrollable === true;
175
175
  if (isScrollable)
@@ -209,33 +209,61 @@ async function buildSessionDomIndex(session, pierce) {
209
209
  const scrollByBe = new Map();
210
210
  const docRootOf = new Map();
211
211
  const contentDocRootByIframe = new Map();
212
+ const enterByBe = new Map();
213
+ const exitByBe = new Map();
212
214
  const rootBe = root.backendNodeId;
213
- const stack = [{ node: root, xp: "/", docRootBe: rootBe }];
215
+ const stack = [
216
+ { node: root, xp: "/", docRootBe: rootBe, phase: "enter" },
217
+ ];
218
+ let dfsIndex = 0;
214
219
  while (stack.length) {
215
- const { node, xp, docRootBe } = stack.pop();
220
+ const { node, xp, docRootBe, phase } = stack.pop();
221
+ if (phase === "exit") {
222
+ if (node.backendNodeId) {
223
+ exitByBe.set(node.backendNodeId, dfsIndex++);
224
+ }
225
+ continue;
226
+ }
216
227
  if (node.backendNodeId) {
228
+ enterByBe.set(node.backendNodeId, dfsIndex++);
217
229
  absByBe.set(node.backendNodeId, xp || "/");
218
- tagByBe.set(node.backendNodeId, String(node.nodeName).toLowerCase());
230
+ tagByBe.set(node.backendNodeId, enrichedTagName(node));
219
231
  if (node?.isScrollable === true)
220
232
  scrollByBe.set(node.backendNodeId, true);
221
233
  docRootOf.set(node.backendNodeId, docRootBe);
222
234
  }
235
+ stack.push({ node, xp, docRootBe, phase: "exit" });
223
236
  const kids = node.children ?? [];
224
237
  if (kids.length) {
225
238
  const segs = (0, xpathUtils_js_1.buildChildXPathSegments)(kids);
226
239
  for (let i = kids.length - 1; i >= 0; i--) {
227
240
  const child = kids[i];
228
241
  const step = segs[i];
229
- stack.push({ node: child, xp: (0, xpathUtils_js_1.joinXPath)(xp, step), docRootBe });
242
+ stack.push({
243
+ node: child,
244
+ xp: (0, xpathUtils_js_1.joinXPath)(xp, step),
245
+ docRootBe,
246
+ phase: "enter",
247
+ });
230
248
  }
231
249
  }
232
250
  for (const sr of node.shadowRoots ?? []) {
233
- stack.push({ node: sr, xp: (0, xpathUtils_js_1.joinXPath)(xp, "//"), docRootBe });
251
+ stack.push({
252
+ node: sr,
253
+ xp: (0, xpathUtils_js_1.joinXPath)(xp, "//"),
254
+ docRootBe,
255
+ phase: "enter",
256
+ });
234
257
  }
235
258
  const cd = node.contentDocument;
236
259
  if (cd && typeof cd.backendNodeId === "number") {
237
260
  contentDocRootByIframe.set(node.backendNodeId, cd.backendNodeId);
238
- stack.push({ node: cd, xp, docRootBe: cd.backendNodeId });
261
+ stack.push({
262
+ node: cd,
263
+ xp,
264
+ docRootBe: cd.backendNodeId,
265
+ phase: "enter",
266
+ });
239
267
  }
240
268
  }
241
269
  return {
@@ -245,6 +273,8 @@ async function buildSessionDomIndex(session, pierce) {
245
273
  scrollByBe,
246
274
  docRootOf,
247
275
  contentDocRootByIframe,
276
+ enterByBe,
277
+ exitByBe,
248
278
  };
249
279
  }
250
280
  /**
@@ -266,6 +296,29 @@ function relativizeXPath(baseAbs, nodeAbs) {
266
296
  return abs;
267
297
  return abs;
268
298
  }
299
+ /**
300
+ * Extract an attribute value from a CDP DOM node's flat attributes array.
301
+ * Attributes are stored as [name1, value1, name2, value2, ...].
302
+ */
303
+ function getAttr(attrs, name) {
304
+ if (!attrs)
305
+ return undefined;
306
+ for (let i = 0; i < attrs.length; i += 2) {
307
+ if (attrs[i] === name)
308
+ return attrs[i + 1];
309
+ }
310
+ return undefined;
311
+ }
312
+ /** Build an enriched tag name that includes the type attribute for inputs. */
313
+ function enrichedTagName(node) {
314
+ const tag = String(node.nodeName).toLowerCase();
315
+ if (tag === "input") {
316
+ const type = getAttr(node.attributes, "type");
317
+ if (type)
318
+ return `input, ${type}`;
319
+ }
320
+ return tag;
321
+ }
269
322
  /** Find a node by backendNodeId inside a DOM.getDocument tree. */
270
323
  function findNodeByBackendId(root, backendNodeId) {
271
324
  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"]}
@@ -144,14 +144,25 @@ class FrameRegistry {
144
144
  seedFromFrameTree(sessionId, frameTree) {
145
145
  const walk = (tree, parent) => {
146
146
  this.ensureNode(tree.frame.id);
147
+ const info = this.frames.get(tree.frame.id);
148
+ const previousParent = info.parentId;
149
+ const nextParent = parent ?? tree.frame.parentId ?? previousParent ?? null;
147
150
  // topology
148
- this.frames.get(tree.frame.id).parentId = parent;
149
- if (parent)
150
- this.frames.get(parent).children.add(tree.frame.id);
151
+ if (previousParent && previousParent !== nextParent) {
152
+ this.frames.get(previousParent)?.children.delete(tree.frame.id);
153
+ }
154
+ info.parentId = nextParent;
155
+ if (nextParent) {
156
+ this.ensureNode(nextParent);
157
+ this.frames.get(nextParent).children.add(tree.frame.id);
158
+ }
151
159
  // last-seen frame
152
- this.frames.get(tree.frame.id).lastSeen = tree.frame;
160
+ info.lastSeen =
161
+ nextParent && !tree.frame.parentId
162
+ ? { ...tree.frame, parentId: nextParent }
163
+ : tree.frame;
153
164
  // ownership (only if unknown)
154
- if (!this.frames.get(tree.frame.id).ownerSessionId) {
165
+ if (!info.ownerSessionId) {
155
166
  this.setOwnerSessionIdInternal(tree.frame.id, sessionId);
156
167
  }
157
168
  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":"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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 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"]}
@@ -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;
@@ -97,6 +97,7 @@ const logger_js_2 = require("./logger.js");
97
97
  const cleanupLocal_js_1 = require("./shutdown/cleanupLocal.js");
98
98
  const supervisorClient_js_1 = require("./shutdown/supervisorClient.js");
99
99
  const utils_js_2 = require("./mcp/utils.js");
100
+ const agent_js_1 = require("./types/private/agent.js");
100
101
  const index_js_1 = require("./types/public/index.js");
101
102
  const context_js_1 = require("./understudy/context.js");
102
103
  const modelUtils_js_2 = require("../modelUtils.js");
@@ -551,6 +552,11 @@ let V3 = (() => {
551
552
  this.overrideLlmClients.set(cacheKey, client);
552
553
  return client;
553
554
  }
555
+ resolveDefaultAgentMode(model) {
556
+ const modelName = (0, modelUtils_js_1.extractModelName)(model) ?? this.modelName;
557
+ const matchedPattern = agent_js_1.HYBRID_CAPABLE_MODEL_PATTERNS.find((pattern) => modelName.includes(pattern));
558
+ return matchedPattern ? "hybrid" : "dom";
559
+ }
554
560
  beginAgentReplayRecording() {
555
561
  this.agentCache.beginRecording();
556
562
  }
@@ -1135,6 +1141,7 @@ let V3 = (() => {
1135
1141
  model: options?.model,
1136
1142
  timeout: options?.timeout,
1137
1143
  selector: options?.selector,
1144
+ ignoreSelectors: options?.ignoreSelectors,
1138
1145
  page,
1139
1146
  };
1140
1147
  let result;
@@ -1157,6 +1164,7 @@ let V3 = (() => {
1157
1164
  this.addToHistory("extract", {
1158
1165
  instruction,
1159
1166
  selector: options?.selector,
1167
+ ignoreSelectors: options?.ignoreSelectors,
1160
1168
  timeout: options?.timeout,
1161
1169
  schema: historySchemaDescriptor,
1162
1170
  }, result);
@@ -1186,6 +1194,7 @@ let V3 = (() => {
1186
1194
  variables: options?.variables,
1187
1195
  timeout: options?.timeout,
1188
1196
  selector: options?.selector,
1197
+ ignoreSelectors: options?.ignoreSelectors,
1189
1198
  page: page,
1190
1199
  };
1191
1200
  let results;
@@ -1204,6 +1213,8 @@ let V3 = (() => {
1204
1213
  this.addToHistory("observe", {
1205
1214
  instruction,
1206
1215
  variables: options?.variables,
1216
+ selector: options?.selector,
1217
+ ignoreSelectors: options?.ignoreSelectors,
1207
1218
  timeout: options?.timeout,
1208
1219
  }, results);
1209
1220
  return results;
@@ -1456,14 +1467,6 @@ let V3 = (() => {
1456
1467
  */
1457
1468
  async prepareAgentExecution(options, instructionOrOptions, agentConfigSignature) {
1458
1469
  // Note: experimental validation is done at the call site before this method
1459
- // Warn if mode is not explicitly set (defaults to "dom")
1460
- if (options?.mode === undefined) {
1461
- this.logger({
1462
- category: "agent",
1463
- 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",
1464
- level: 0,
1465
- });
1466
- }
1467
1470
  const tools = options?.integrations
1468
1471
  ? await (0, utils_js_2.resolveTools)(options.integrations, options.tools)
1469
1472
  : (options?.tools ?? {});
@@ -1471,7 +1474,8 @@ let V3 = (() => {
1471
1474
  ? this.resolveLlmClient(options.model)
1472
1475
  : this.llmClient;
1473
1476
  const resolvedExecutionModel = options?.executionModel ?? options?.model;
1474
- const handler = new v3AgentHandler_js_1.V3AgentHandler(this, this.logger, agentLlmClient, resolvedExecutionModel, options?.systemPrompt, tools, options?.mode, this.isCaptchaAutoSolveEnabled);
1477
+ const resolvedMode = options?.mode ?? this.resolveDefaultAgentMode(options?.model);
1478
+ const handler = new v3AgentHandler_js_1.V3AgentHandler(this, this.logger, agentLlmClient, resolvedExecutionModel, options?.systemPrompt, tools, resolvedMode, this.isCaptchaAutoSolveEnabled);
1475
1479
  const resolvedOptions = typeof instructionOrOptions === "string"
1476
1480
  ? {
1477
1481
  instruction: instructionOrOptions,
@@ -1510,10 +1514,8 @@ let V3 = (() => {
1510
1514
  };
1511
1515
  }
1512
1516
  agent(options) {
1513
- // Determine if CUA mode is enabled (via mode: "cua" or deprecated cua: true)
1514
- const isCuaMode = options?.mode !== undefined
1515
- ? options.mode === "cua"
1516
- : options?.cua === true;
1517
+ const isCuaMode = options?.mode === "cua" ||
1518
+ (options?.mode === undefined && options?.cua === true);
1517
1519
  // Emit deprecation warning for cua: true
1518
1520
  if (options?.cua === true) {
1519
1521
  this.logger({
@@ -1523,13 +1525,15 @@ let V3 = (() => {
1523
1525
  });
1524
1526
  console.warn('[Stagehand] DEPRECATED: The "cua: true" option is deprecated. Use "mode: \'cua\'" instead.');
1525
1527
  }
1528
+ const loggedMode = options?.mode ??
1529
+ (isCuaMode ? "cua" : this.resolveDefaultAgentMode(options?.model));
1526
1530
  this.logger({
1527
1531
  category: "agent",
1528
1532
  message: "Creating v3 agent instance",
1529
1533
  level: 1,
1530
1534
  auxiliary: {
1531
1535
  cua: { value: isCuaMode ? "true" : "false", type: "boolean" },
1532
- mode: { value: options?.mode ?? "dom", type: "string" },
1536
+ mode: { value: loggedMode, type: "string" },
1533
1537
  model: {
1534
1538
  value: (0, modelUtils_js_1.extractModelName)(options?.model) ?? this.llmClient.modelName,
1535
1539
  type: "string",