@browserbasehq/stagehand 2.5.4 → 2.5.6

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/index.d.ts CHANGED
@@ -52,7 +52,7 @@ interface LLMTool {
52
52
  parameters: Record<string, unknown>;
53
53
  }
54
54
 
55
- declare const AvailableModelSchema: z.ZodEnum<["gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "o4-mini", "o3", "o3-mini", "o1", "o1-mini", "gpt-4o", "gpt-4o-mini", "gpt-4o-2024-08-06", "gpt-4.5-preview", "o1-preview", "claude-3-5-sonnet-latest", "claude-3-5-sonnet-20241022", "claude-3-5-sonnet-20240620", "claude-3-7-sonnet-latest", "claude-3-7-sonnet-20250219", "cerebras-llama-3.3-70b", "cerebras-llama-3.1-8b", "groq-llama-3.3-70b-versatile", "groq-llama-3.3-70b-specdec", "gemini-1.5-flash", "gemini-1.5-pro", "gemini-1.5-flash-8b", "gemini-2.0-flash-lite", "gemini-2.0-flash", "gemini-2.5-flash-preview-04-17", "gemini-2.5-pro-preview-03-25"]>;
55
+ declare const AvailableModelSchema: z.ZodEnum<["gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "o4-mini", "o3", "o3-mini", "o1", "o1-mini", "gpt-4o", "gpt-4o-mini", "gpt-4o-2024-08-06", "gpt-4.5-preview", "o1-preview", "claude-haiku-4-5", "claude-3-7-sonnet-latest", "claude-3-7-sonnet-20250219", "cerebras-llama-3.3-70b", "cerebras-llama-3.1-8b", "groq-llama-3.3-70b-versatile", "groq-llama-3.3-70b-specdec", "gemini-1.5-flash", "gemini-1.5-pro", "gemini-1.5-flash-8b", "gemini-2.0-flash-lite", "gemini-2.0-flash", "gemini-2.5-flash-preview-04-17", "gemini-2.5-pro-preview-03-25"]>;
56
56
  type AvailableModel = z.infer<typeof AvailableModelSchema> | string;
57
57
  type ModelProvider = "openai" | "anthropic" | "cerebras" | "groq" | "google" | "aisdk";
58
58
  type ClientOptions = ClientOptions$1 | ClientOptions$2;
@@ -314,6 +314,9 @@ interface ObserveOptions {
314
314
  * @deprecated The `onlyVisible` parameter has no effect in this version of Stagehand and will be removed in later versions.
315
315
  */
316
316
  onlyVisible?: boolean;
317
+ /**
318
+ * @deprecated The `drawOverlay` parameter has no effect in this version of Stagehand and will be removed in later versions.
319
+ */
317
320
  drawOverlay?: boolean;
318
321
  iframes?: boolean;
319
322
  frameId?: string;
@@ -796,6 +799,7 @@ declare class StagehandContext {
796
799
  private pageMap;
797
800
  private activeStagehandPage;
798
801
  private readonly frameIdMap;
802
+ private static readonly contextsWithInitScript;
799
803
  private constructor();
800
804
  private createStagehandPage;
801
805
  static init(context: BrowserContext$1, stagehand: Stagehand): Promise<StagehandContext>;
@@ -835,7 +839,6 @@ declare class StagehandPage {
835
839
  ordinalForFrameId(fid: string | undefined): number;
836
840
  encodeWithFrameId(fid: string | undefined, backendId: number): EncodedId;
837
841
  resetFrameOrdinals(): void;
838
- private ensureStagehandScript;
839
842
  /** Register the custom selector engine that pierces open/closed shadow roots. */
840
843
  private ensureStagehandSelectorEngine;
841
844
  /**
package/dist/index.js CHANGED
@@ -494,7 +494,7 @@ var StagehandFunctionName = /* @__PURE__ */ ((StagehandFunctionName2) => {
494
494
  })(StagehandFunctionName || {});
495
495
 
496
496
  // lib/version.ts
497
- var STAGEHAND_VERSION = "2.5.4";
497
+ var STAGEHAND_VERSION = "2.5.6";
498
498
 
499
499
  // types/stagehandErrors.ts
500
500
  var StagehandError = class extends Error {
@@ -2161,57 +2161,6 @@ function validateZodSchema(schema, data) {
2161
2161
  }
2162
2162
  throw new ZodSchemaValidationError(data, result.error.format());
2163
2163
  }
2164
- function drawObserveOverlay(page, results) {
2165
- return __async(this, null, function* () {
2166
- const xpathList = results.map((result) => result.selector);
2167
- const validXpaths = xpathList.filter((xpath) => xpath !== "xpath=");
2168
- yield page.evaluate((selectors2) => {
2169
- selectors2.forEach((selector) => {
2170
- let element;
2171
- if (selector.startsWith("xpath=")) {
2172
- const xpath = selector.substring(6);
2173
- element = document.evaluate(
2174
- xpath,
2175
- document,
2176
- null,
2177
- XPathResult.FIRST_ORDERED_NODE_TYPE,
2178
- null
2179
- ).singleNodeValue;
2180
- } else {
2181
- element = document.querySelector(selector);
2182
- }
2183
- if (element instanceof HTMLElement) {
2184
- const overlay = document.createElement("div");
2185
- overlay.setAttribute("stagehandObserve", "true");
2186
- const rect = element.getBoundingClientRect();
2187
- overlay.style.position = "absolute";
2188
- overlay.style.left = rect.left + "px";
2189
- overlay.style.top = rect.top + "px";
2190
- overlay.style.width = rect.width + "px";
2191
- overlay.style.height = rect.height + "px";
2192
- overlay.style.backgroundColor = "rgba(255, 255, 0, 0.3)";
2193
- overlay.style.pointerEvents = "none";
2194
- overlay.style.zIndex = "10000";
2195
- document.body.appendChild(overlay);
2196
- }
2197
- });
2198
- }, validXpaths);
2199
- });
2200
- }
2201
- function clearOverlays(page) {
2202
- return __async(this, null, function* () {
2203
- yield page.evaluate(() => {
2204
- const elements = document.querySelectorAll('[stagehandObserve="true"]');
2205
- elements.forEach((el) => {
2206
- const parent = el.parentNode;
2207
- while (el.firstChild) {
2208
- parent == null ? void 0 : parent.insertBefore(el.firstChild, el);
2209
- }
2210
- parent == null ? void 0 : parent.removeChild(el);
2211
- });
2212
- });
2213
- });
2214
- }
2215
2164
  function isRunningInBun() {
2216
2165
  return typeof process !== "undefined" && typeof process.versions !== "undefined" && "bun" in process.versions;
2217
2166
  }
@@ -2609,6 +2558,115 @@ var PUA_START = 57344;
2609
2558
  var PUA_END = 63743;
2610
2559
  var NBSP_CHARS = /* @__PURE__ */ new Set([160, 8239, 8199, 65279]);
2611
2560
  var WORLD_NAME = "stagehand-world";
2561
+ var DOM_DEPTH_ATTEMPTS = [-1, 256, 128, 64, 32, 16, 8, 4, 2, 1];
2562
+ var DESCRIBE_DEPTH_ATTEMPTS = [-1, 64, 32, 16, 8, 4, 2, 1];
2563
+ function isCborStackError(message) {
2564
+ return message.includes("CBOR: stack limit exceeded");
2565
+ }
2566
+ function shouldExpandNode(node) {
2567
+ var _a15, _b, _c;
2568
+ const declaredChildren = (_a15 = node.childNodeCount) != null ? _a15 : 0;
2569
+ const realizedChildren = (_c = (_b = node.children) == null ? void 0 : _b.length) != null ? _c : 0;
2570
+ return declaredChildren > realizedChildren;
2571
+ }
2572
+ function mergeDomNodes(target, source) {
2573
+ var _a15, _b, _c, _d;
2574
+ target.childNodeCount = (_a15 = source.childNodeCount) != null ? _a15 : target.childNodeCount;
2575
+ target.children = (_b = source.children) != null ? _b : target.children;
2576
+ target.shadowRoots = (_c = source.shadowRoots) != null ? _c : target.shadowRoots;
2577
+ target.contentDocument = (_d = source.contentDocument) != null ? _d : target.contentDocument;
2578
+ }
2579
+ function collectDomTraversalTargets(node) {
2580
+ const targets = [];
2581
+ if (node.children) targets.push(...node.children);
2582
+ if (node.shadowRoots) targets.push(...node.shadowRoots);
2583
+ if (node.contentDocument) targets.push(node.contentDocument);
2584
+ return targets;
2585
+ }
2586
+ function hydrateDomTree(session, root) {
2587
+ return __async(this, null, function* () {
2588
+ var _a15, _b;
2589
+ const stack = [root];
2590
+ const expandedNodeIds = /* @__PURE__ */ new Set();
2591
+ const expandedBackendIds = /* @__PURE__ */ new Set();
2592
+ let describeCalls = 0;
2593
+ while (stack.length) {
2594
+ const node = stack.pop();
2595
+ const nodeId = typeof node.nodeId === "number" && node.nodeId > 0 ? node.nodeId : void 0;
2596
+ const backendId = typeof node.backendNodeId === "number" && node.backendNodeId > 0 ? node.backendNodeId : void 0;
2597
+ const seenByNode = nodeId ? expandedNodeIds.has(nodeId) : false;
2598
+ const seenByBackend = !nodeId && backendId ? expandedBackendIds.has(backendId) : false;
2599
+ if (seenByNode || seenByBackend) continue;
2600
+ if (nodeId) expandedNodeIds.add(nodeId);
2601
+ else if (backendId) expandedBackendIds.add(backendId);
2602
+ const needsExpansion = shouldExpandNode(node);
2603
+ if (needsExpansion && (nodeId || backendId)) {
2604
+ const describeParamsBase = nodeId ? { nodeId } : { backendNodeId: backendId };
2605
+ let expanded = false;
2606
+ for (const depth of DESCRIBE_DEPTH_ATTEMPTS) {
2607
+ try {
2608
+ const described = yield session.send("DOM.describeNode", __spreadProps(__spreadValues({}, describeParamsBase), {
2609
+ depth,
2610
+ pierce: true
2611
+ }));
2612
+ mergeDomNodes(node, described.node);
2613
+ if (!nodeId && described.node.nodeId && described.node.nodeId > 0) {
2614
+ node.nodeId = described.node.nodeId;
2615
+ expandedNodeIds.add(described.node.nodeId);
2616
+ }
2617
+ describeCalls++;
2618
+ expanded = true;
2619
+ break;
2620
+ } catch (err) {
2621
+ const message = err instanceof Error ? err.message : String(err);
2622
+ if (isCborStackError(message)) {
2623
+ continue;
2624
+ }
2625
+ const identifier = (_a15 = nodeId != null ? nodeId : backendId) != null ? _a15 : "unknown";
2626
+ throw new StagehandDomProcessError(
2627
+ `Failed to expand DOM node ${identifier}: ${String(err)}`
2628
+ );
2629
+ }
2630
+ }
2631
+ if (!expanded) {
2632
+ const identifier = (_b = nodeId != null ? nodeId : backendId) != null ? _b : "unknown";
2633
+ throw new StagehandDomProcessError(
2634
+ `Unable to expand DOM node ${identifier} after describeNode depth retries`
2635
+ );
2636
+ }
2637
+ }
2638
+ for (const child of collectDomTraversalTargets(node)) {
2639
+ stack.push(child);
2640
+ }
2641
+ }
2642
+ return describeCalls;
2643
+ });
2644
+ }
2645
+ function getDomTreeWithFallback(session) {
2646
+ return __async(this, null, function* () {
2647
+ let lastCborMessage = "";
2648
+ for (const depth of DOM_DEPTH_ATTEMPTS) {
2649
+ try {
2650
+ const params = { depth, pierce: true };
2651
+ const { root } = yield session.send("DOM.getDocument", params);
2652
+ if (depth !== -1) {
2653
+ yield hydrateDomTree(session, root);
2654
+ }
2655
+ return root;
2656
+ } catch (err) {
2657
+ const message = err instanceof Error ? err.message : String(err);
2658
+ if (isCborStackError(message)) {
2659
+ lastCborMessage = message;
2660
+ continue;
2661
+ }
2662
+ throw err;
2663
+ }
2664
+ }
2665
+ throw new StagehandDomProcessError(
2666
+ lastCborMessage ? `CDP DOM.getDocument failed after adaptive depth retries: ${lastCborMessage}` : "CDP DOM.getDocument failed after adaptive depth retries."
2667
+ );
2668
+ });
2669
+ }
2612
2670
  function cleanText(input) {
2613
2671
  let out = "";
2614
2672
  let prevWasSpace = false;
@@ -2666,10 +2724,7 @@ function buildBackendIdMaps(experimental, sp, targetFrame) {
2666
2724
  session === (yield sp.getCDPClient()) ? void 0 : targetFrame
2667
2725
  );
2668
2726
  try {
2669
- const { root } = yield session.send("DOM.getDocument", {
2670
- depth: -1,
2671
- pierce: true
2672
- });
2727
+ const root = yield getDomTreeWithFallback(session);
2673
2728
  let startNode = root;
2674
2729
  let rootFid = targetFrame && (yield getCDPFrameId(sp, targetFrame));
2675
2730
  if (targetFrame && targetFrame !== sp.page.mainFrame() && session === (yield sp.getCDPClient())) {
@@ -3603,6 +3658,13 @@ var StagehandObserveHandler = class {
3603
3658
  level: 1
3604
3659
  });
3605
3660
  }
3661
+ if (drawOverlay !== void 0) {
3662
+ this.logger({
3663
+ category: "observation",
3664
+ message: "Warning: the drawOverlay parameter has been deprecated and this parameter is now a no-op.",
3665
+ level: 1
3666
+ });
3667
+ }
3606
3668
  yield this.stagehandPage._waitForSettledDom();
3607
3669
  this.logger({
3608
3670
  category: "observation",
@@ -3730,9 +3792,6 @@ var StagehandObserveHandler = class {
3730
3792
  }
3731
3793
  }
3732
3794
  });
3733
- if (drawOverlay) {
3734
- yield drawObserveOverlay(this.stagehandPage.page, elementsWithSelectors);
3735
- }
3736
3795
  return elementsWithSelectors;
3737
3796
  });
3738
3797
  }
@@ -3771,9 +3830,6 @@ var StagehandResponseParseError = class extends StagehandAPIError {
3771
3830
  }
3772
3831
  };
3773
3832
 
3774
- // lib/dom/build/scriptContent.ts
3775
- var scriptContent = '(() => {\n // lib/dom/elementCheckUtils.ts\n function isElementNode(node) {\n return node.nodeType === Node.ELEMENT_NODE;\n }\n function isTextNode(node) {\n return node.nodeType === Node.TEXT_NODE && Boolean(node.textContent?.trim());\n }\n\n // lib/dom/xpathUtils.ts\n function getParentElement(node) {\n return isElementNode(node) ? node.parentElement : node.parentNode;\n }\n function getCombinations(attributes, size) {\n const results = [];\n function helper(start, combo) {\n if (combo.length === size) {\n results.push([...combo]);\n return;\n }\n for (let i = start; i < attributes.length; i++) {\n combo.push(attributes[i]);\n helper(i + 1, combo);\n combo.pop();\n }\n }\n helper(0, []);\n return results;\n }\n function isXPathFirstResultElement(xpath, target) {\n try {\n const result = document.evaluate(\n xpath,\n document.documentElement,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n );\n return result.snapshotItem(0) === target;\n } catch (error) {\n console.warn(`Invalid XPath expression: ${xpath}`, error);\n return false;\n }\n }\n function escapeXPathString(value) {\n if (value.includes("\'")) {\n if (value.includes(\'"\')) {\n return "concat(" + value.split(/(\'+)/).map((part) => {\n if (part === "\'") {\n return `"\'"`;\n } else if (part.startsWith("\'") && part.endsWith("\'")) {\n return `"${part}"`;\n } else {\n return `\'${part}\'`;\n }\n }).join(",") + ")";\n } else {\n return `"${value}"`;\n }\n } else {\n return `\'${value}\'`;\n }\n }\n async function generateXPathsForElement(element) {\n if (!element) return [];\n const [complexXPath, standardXPath, idBasedXPath] = await Promise.all([\n generateComplexXPath(element),\n generateStandardXPath(element),\n generatedIdBasedXPath(element)\n ]);\n return [standardXPath, ...idBasedXPath ? [idBasedXPath] : [], complexXPath];\n }\n async function generateComplexXPath(element) {\n const parts = [];\n let currentElement = element;\n while (currentElement && (isTextNode(currentElement) || isElementNode(currentElement))) {\n if (isElementNode(currentElement)) {\n const el = currentElement;\n let selector = el.tagName.toLowerCase();\n const attributePriority = [\n "data-qa",\n "data-component",\n "data-role",\n "role",\n "aria-role",\n "type",\n "name",\n "aria-label",\n "placeholder",\n "title",\n "alt"\n ];\n const attributes = attributePriority.map((attr) => {\n let value = el.getAttribute(attr);\n if (attr === "href-full" && value) {\n value = el.getAttribute("href");\n }\n return value ? { attr: attr === "href-full" ? "href" : attr, value } : null;\n }).filter((attr) => attr !== null);\n let uniqueSelector = "";\n for (let i = 1; i <= attributes.length; i++) {\n const combinations = getCombinations(attributes, i);\n for (const combo of combinations) {\n const conditions = combo.map((a) => `@${a.attr}=${escapeXPathString(a.value)}`).join(" and ");\n const xpath2 = `//${selector}[${conditions}]`;\n if (isXPathFirstResultElement(xpath2, el)) {\n uniqueSelector = xpath2;\n break;\n }\n }\n if (uniqueSelector) break;\n }\n if (uniqueSelector) {\n parts.unshift(uniqueSelector.replace("//", ""));\n break;\n } else {\n const parent = getParentElement(el);\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (sibling) => sibling.tagName === el.tagName\n );\n const index = siblings.indexOf(el) + 1;\n selector += siblings.length > 1 ? `[${index}]` : "";\n }\n parts.unshift(selector);\n }\n }\n currentElement = getParentElement(currentElement);\n }\n const xpath = "//" + parts.join("/");\n return xpath;\n }\n async function generateStandardXPath(element) {\n const parts = [];\n while (element && (isTextNode(element) || isElementNode(element))) {\n let index = 0;\n let hasSameTypeSiblings = false;\n const siblings = element.parentElement ? Array.from(element.parentElement.childNodes) : [];\n for (let i = 0; i < siblings.length; i++) {\n const sibling = siblings[i];\n if (sibling.nodeType === element.nodeType && sibling.nodeName === element.nodeName) {\n index = index + 1;\n hasSameTypeSiblings = true;\n if (sibling.isSameNode(element)) {\n break;\n }\n }\n }\n if (element.nodeName !== "#text") {\n const tagName = element.nodeName.toLowerCase();\n const pathIndex = hasSameTypeSiblings ? `[${index}]` : "";\n parts.unshift(`${tagName}${pathIndex}`);\n }\n element = element.parentElement;\n }\n return parts.length ? `/${parts.join("/")}` : "";\n }\n async function generatedIdBasedXPath(element) {\n if (isElementNode(element) && element.id) {\n return `//*[@id=\'${element.id}\']`;\n }\n return null;\n }\n\n // types/stagehandErrors.ts\n var StagehandError = class extends Error {\n constructor(message) {\n super(message);\n this.name = this.constructor.name;\n }\n };\n var StagehandDomProcessError = class extends StagehandError {\n constructor(message) {\n super(`Error Processing Dom: ${message}`);\n }\n };\n\n // lib/dom/utils.ts\n function canElementScroll(elem) {\n if (typeof elem.scrollTo !== "function") {\n console.warn("canElementScroll: .scrollTo is not a function.");\n return false;\n }\n try {\n const originalTop = elem.scrollTop;\n elem.scrollTo({\n top: originalTop + 100,\n left: 0,\n behavior: "instant"\n });\n if (elem.scrollTop === originalTop) {\n throw new StagehandDomProcessError("scrollTop did not change");\n }\n elem.scrollTo({\n top: originalTop,\n left: 0,\n behavior: "instant"\n });\n return true;\n } catch (error) {\n console.warn("canElementScroll error:", error.message || error);\n return false;\n }\n }\n function getNodeFromXpath(xpath) {\n return document.evaluate(\n xpath,\n document.documentElement,\n null,\n XPathResult.FIRST_ORDERED_NODE_TYPE,\n null\n ).singleNodeValue;\n }\n function waitForElementScrollEnd(element, idleMs = 100) {\n return new Promise((resolve) => {\n let scrollEndTimer;\n const handleScroll = () => {\n clearTimeout(scrollEndTimer);\n scrollEndTimer = window.setTimeout(() => {\n element.removeEventListener("scroll", handleScroll);\n resolve();\n }, idleMs);\n };\n element.addEventListener("scroll", handleScroll, { passive: true });\n handleScroll();\n });\n }\n\n // lib/dom/process.ts\n function getScrollableElements(topN) {\n const docEl = document.documentElement;\n const scrollableElements = [docEl];\n const allElements = document.querySelectorAll("*");\n for (const elem of allElements) {\n const style = window.getComputedStyle(elem);\n const overflowY = style.overflowY;\n const isPotentiallyScrollable = overflowY === "auto" || overflowY === "scroll" || overflowY === "overlay";\n if (isPotentiallyScrollable) {\n const candidateScrollDiff = elem.scrollHeight - elem.clientHeight;\n if (candidateScrollDiff > 0 && canElementScroll(elem)) {\n scrollableElements.push(elem);\n }\n }\n }\n scrollableElements.sort((a, b) => b.scrollHeight - a.scrollHeight);\n if (topN !== void 0) {\n return scrollableElements.slice(0, topN);\n }\n return scrollableElements;\n }\n async function getScrollableElementXpaths(topN) {\n const scrollableElems = getScrollableElements(topN);\n const xpaths = [];\n for (const elem of scrollableElems) {\n const allXPaths = await generateXPathsForElement(elem);\n const firstXPath = allXPaths?.[0] || "";\n xpaths.push(firstXPath);\n }\n return xpaths;\n }\n (() => {\n const closedRoots = /* @__PURE__ */ new WeakMap();\n const nativeAttachShadow = Element.prototype.attachShadow;\n Element.prototype.attachShadow = function(init) {\n const root = nativeAttachShadow.call(this, init);\n if (init.mode === "closed") closedRoots.set(this, root);\n return root;\n };\n const backdoor = {\n getClosedRoot: (host) => closedRoots.get(host),\n queryClosed: (host, selector) => {\n const root = closedRoots.get(host);\n return root ? Array.from(root.querySelectorAll(selector)) : [];\n },\n xpathClosed: (host, xp) => {\n const root = closedRoots.get(host);\n if (!root) return [];\n const it = document.evaluate(\n xp,\n root,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n );\n const out = [];\n for (let i = 0; i < it.snapshotLength; ++i) {\n const n = it.snapshotItem(i);\n if (n) out.push(n);\n }\n return out;\n }\n };\n if (!("__stagehand__" in window)) {\n Object.defineProperty(window, "__stagehand__", {\n value: backdoor,\n enumerable: false,\n writable: false,\n configurable: false\n });\n }\n })();\n window.getScrollableElementXpaths = getScrollableElementXpaths;\n window.getNodeFromXpath = getNodeFromXpath;\n window.waitForElementScrollEnd = waitForElementScrollEnd;\n})();\n';
3776
-
3777
3833
  // lib/StagehandPage.ts
3778
3834
  function getCurrentRootFrameId(session) {
3779
3835
  return __async(this, null, function* () {
@@ -3858,32 +3914,6 @@ var StagehandPage = class _StagehandPage {
3858
3914
  resetFrameOrdinals() {
3859
3915
  this.fidOrdinals = /* @__PURE__ */ new Map([[void 0, 0]]);
3860
3916
  }
3861
- ensureStagehandScript() {
3862
- return __async(this, null, function* () {
3863
- try {
3864
- const injected = yield this.rawPage.evaluate(
3865
- () => !!window.__stagehandInjected
3866
- );
3867
- if (injected) return;
3868
- const guardedScript = `if (!window.__stagehandInjected) { window.__stagehandInjected = true; ${scriptContent} }`;
3869
- yield this.rawPage.addInitScript({ content: guardedScript });
3870
- yield this.rawPage.evaluate(guardedScript);
3871
- } catch (err) {
3872
- if (!this.stagehand.isClosed) {
3873
- this.stagehand.log({
3874
- category: "dom",
3875
- message: "Failed to inject Stagehand helper script",
3876
- level: 1,
3877
- auxiliary: {
3878
- error: { value: err.message, type: "string" },
3879
- trace: { value: err.stack, type: "string" }
3880
- }
3881
- });
3882
- throw err;
3883
- }
3884
- }
3885
- });
3886
- }
3887
3917
  /** Register the custom selector engine that pierces open/closed shadow roots. */
3888
3918
  ensureStagehandSelectorEngine() {
3889
3919
  return __async(this, null, function* () {
@@ -4039,7 +4069,6 @@ var StagehandPage = class _StagehandPage {
4039
4069
  const value = target[prop];
4040
4070
  if (prop === "evaluate" || prop === "evaluateHandle" || prop === "$eval" || prop === "$$eval") {
4041
4071
  return (...args) => __async(this, null, function* () {
4042
- yield this.ensureStagehandScript();
4043
4072
  return value.apply(
4044
4073
  target,
4045
4074
  args
@@ -4313,7 +4342,6 @@ var StagehandPage = class _StagehandPage {
4313
4342
  if (!this.actHandler) {
4314
4343
  throw new HandlerNotInitializedError("Act");
4315
4344
  }
4316
- yield clearOverlays(this.page);
4317
4345
  if (typeof actionOrOptions === "object" && actionOrOptions !== null) {
4318
4346
  if ("selector" in actionOrOptions && "method" in actionOrOptions) {
4319
4347
  const observeResult = actionOrOptions;
@@ -4392,7 +4420,6 @@ var StagehandPage = class _StagehandPage {
4392
4420
  if (!this.extractHandler) {
4393
4421
  throw new HandlerNotInitializedError("Extract");
4394
4422
  }
4395
- yield clearOverlays(this.page);
4396
4423
  if (!instructionOrOptions) {
4397
4424
  let result2;
4398
4425
  if (this.api) {
@@ -4495,7 +4522,6 @@ var StagehandPage = class _StagehandPage {
4495
4522
  if (!this.observeHandler) {
4496
4523
  throw new HandlerNotInitializedError("Observe");
4497
4524
  }
4498
- yield clearOverlays(this.page);
4499
4525
  const options = typeof instructionOrOptions === "string" ? { instruction: instructionOrOptions } : instructionOrOptions || {};
4500
4526
  const {
4501
4527
  instruction,
@@ -4646,8 +4672,17 @@ var StagehandPage = class _StagehandPage {
4646
4672
  }
4647
4673
  };
4648
4674
 
4675
+ // lib/dom/build/scriptContent.ts
4676
+ var scriptContent = '(() => {\n // lib/dom/process.ts\n (() => {\n const closedRoots = /* @__PURE__ */ new WeakMap();\n const nativeAttachShadow = Element.prototype.attachShadow;\n Element.prototype.attachShadow = function(init) {\n const root = nativeAttachShadow.call(this, init);\n if (init.mode === "closed") closedRoots.set(this, root);\n return root;\n };\n const backdoor = {\n getClosedRoot: (host) => closedRoots.get(host),\n queryClosed: (host, selector) => {\n const root = closedRoots.get(host);\n return root ? Array.from(root.querySelectorAll(selector)) : [];\n },\n xpathClosed: (host, xp) => {\n const root = closedRoots.get(host);\n if (!root) return [];\n const it = document.evaluate(\n xp,\n root,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n );\n const out = [];\n for (let i = 0; i < it.snapshotLength; ++i) {\n const n = it.snapshotItem(i);\n if (n) out.push(n);\n }\n return out;\n }\n };\n if (!("__stagehand__" in window)) {\n Object.defineProperty(window, "__stagehand__", {\n value: backdoor,\n enumerable: false,\n writable: false,\n configurable: false\n });\n }\n })();\n})();\n';
4677
+
4649
4678
  // lib/StagehandContext.ts
4650
- var StagehandContext = class _StagehandContext {
4679
+ var stagehandInitScript = `
4680
+ if (!window.__stagehandInjected) {
4681
+ window.__stagehandInjected = true;
4682
+ ${scriptContent}
4683
+ }
4684
+ `;
4685
+ var _StagehandContext = class _StagehandContext {
4651
4686
  constructor(context, stagehand) {
4652
4687
  this.activeStagehandPage = null;
4653
4688
  this.frameIdMap = /* @__PURE__ */ new Map();
@@ -4706,6 +4741,10 @@ var StagehandContext = class _StagehandContext {
4706
4741
  }
4707
4742
  static init(context, stagehand) {
4708
4743
  return __async(this, null, function* () {
4744
+ if (!_StagehandContext.contextsWithInitScript.has(context)) {
4745
+ yield context.addInitScript({ content: stagehandInitScript });
4746
+ _StagehandContext.contextsWithInitScript.add(context);
4747
+ }
4709
4748
  const instance = new _StagehandContext(context, stagehand);
4710
4749
  context.on("page", (pwPage) => __async(null, null, function* () {
4711
4750
  yield instance.handleNewPlaywrightPage(pwPage);
@@ -4808,6 +4847,8 @@ var StagehandContext = class _StagehandContext {
4808
4847
  });
4809
4848
  }
4810
4849
  };
4850
+ _StagehandContext.contextsWithInitScript = /* @__PURE__ */ new WeakSet();
4851
+ var StagehandContext = _StagehandContext;
4811
4852
 
4812
4853
  // lib/api.ts
4813
4854
  var import_zod_to_json_schema = __toESM(require("zod-to-json-schema"));
@@ -20273,9 +20314,7 @@ var modelToProviderMap = {
20273
20314
  "gpt-4o-2024-08-06": "openai",
20274
20315
  "gpt-4.5-preview": "openai",
20275
20316
  "o1-preview": "openai",
20276
- "claude-3-5-sonnet-latest": "anthropic",
20277
- "claude-3-5-sonnet-20240620": "anthropic",
20278
- "claude-3-5-sonnet-20241022": "anthropic",
20317
+ "claude-haiku-4-5": "anthropic",
20279
20318
  "claude-3-7-sonnet-20250219": "anthropic",
20280
20319
  "claude-3-7-sonnet-latest": "anthropic",
20281
20320
  "cerebras-llama-3.3-70b": "cerebras",
@@ -24073,9 +24112,7 @@ var AvailableModelSchema = import_v315.z.enum([
24073
24112
  "gpt-4o-2024-08-06",
24074
24113
  "gpt-4.5-preview",
24075
24114
  "o1-preview",
24076
- "claude-3-5-sonnet-latest",
24077
- "claude-3-5-sonnet-20241022",
24078
- "claude-3-5-sonnet-20240620",
24115
+ "claude-haiku-4-5",
24079
24116
  "claude-3-7-sonnet-latest",
24080
24117
  "claude-3-7-sonnet-20250219",
24081
24118
  "cerebras-llama-3.3-70b",
@@ -8,6 +8,7 @@ export declare class StagehandContext {
8
8
  private pageMap;
9
9
  private activeStagehandPage;
10
10
  private readonly frameIdMap;
11
+ private static readonly contextsWithInitScript;
11
12
  private constructor();
12
13
  private createStagehandPage;
13
14
  static init(context: PlaywrightContext, stagehand: Stagehand): Promise<StagehandContext>;
@@ -30,7 +30,6 @@ export declare class StagehandPage {
30
30
  ordinalForFrameId(fid: string | undefined): number;
31
31
  encodeWithFrameId(fid: string | undefined, backendId: number): EncodedId;
32
32
  resetFrameOrdinals(): void;
33
- private ensureStagehandScript;
34
33
  /** Register the custom selector engine that pierces open/closed shadow roots. */
35
34
  private ensureStagehandSelectorEngine;
36
35
  /**
@@ -1 +1 @@
1
- export declare const scriptContent = "(() => {\n // lib/dom/elementCheckUtils.ts\n function isElementNode(node) {\n return node.nodeType === Node.ELEMENT_NODE;\n }\n function isTextNode(node) {\n return node.nodeType === Node.TEXT_NODE && Boolean(node.textContent?.trim());\n }\n\n // lib/dom/xpathUtils.ts\n function getParentElement(node) {\n return isElementNode(node) ? node.parentElement : node.parentNode;\n }\n function getCombinations(attributes, size) {\n const results = [];\n function helper(start, combo) {\n if (combo.length === size) {\n results.push([...combo]);\n return;\n }\n for (let i = start; i < attributes.length; i++) {\n combo.push(attributes[i]);\n helper(i + 1, combo);\n combo.pop();\n }\n }\n helper(0, []);\n return results;\n }\n function isXPathFirstResultElement(xpath, target) {\n try {\n const result = document.evaluate(\n xpath,\n document.documentElement,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n );\n return result.snapshotItem(0) === target;\n } catch (error) {\n console.warn(`Invalid XPath expression: ${xpath}`, error);\n return false;\n }\n }\n function escapeXPathString(value) {\n if (value.includes(\"'\")) {\n if (value.includes('\"')) {\n return \"concat(\" + value.split(/('+)/).map((part) => {\n if (part === \"'\") {\n return `\"'\"`;\n } else if (part.startsWith(\"'\") && part.endsWith(\"'\")) {\n return `\"${part}\"`;\n } else {\n return `'${part}'`;\n }\n }).join(\",\") + \")\";\n } else {\n return `\"${value}\"`;\n }\n } else {\n return `'${value}'`;\n }\n }\n async function generateXPathsForElement(element) {\n if (!element) return [];\n const [complexXPath, standardXPath, idBasedXPath] = await Promise.all([\n generateComplexXPath(element),\n generateStandardXPath(element),\n generatedIdBasedXPath(element)\n ]);\n return [standardXPath, ...idBasedXPath ? [idBasedXPath] : [], complexXPath];\n }\n async function generateComplexXPath(element) {\n const parts = [];\n let currentElement = element;\n while (currentElement && (isTextNode(currentElement) || isElementNode(currentElement))) {\n if (isElementNode(currentElement)) {\n const el = currentElement;\n let selector = el.tagName.toLowerCase();\n const attributePriority = [\n \"data-qa\",\n \"data-component\",\n \"data-role\",\n \"role\",\n \"aria-role\",\n \"type\",\n \"name\",\n \"aria-label\",\n \"placeholder\",\n \"title\",\n \"alt\"\n ];\n const attributes = attributePriority.map((attr) => {\n let value = el.getAttribute(attr);\n if (attr === \"href-full\" && value) {\n value = el.getAttribute(\"href\");\n }\n return value ? { attr: attr === \"href-full\" ? \"href\" : attr, value } : null;\n }).filter((attr) => attr !== null);\n let uniqueSelector = \"\";\n for (let i = 1; i <= attributes.length; i++) {\n const combinations = getCombinations(attributes, i);\n for (const combo of combinations) {\n const conditions = combo.map((a) => `@${a.attr}=${escapeXPathString(a.value)}`).join(\" and \");\n const xpath2 = `//${selector}[${conditions}]`;\n if (isXPathFirstResultElement(xpath2, el)) {\n uniqueSelector = xpath2;\n break;\n }\n }\n if (uniqueSelector) break;\n }\n if (uniqueSelector) {\n parts.unshift(uniqueSelector.replace(\"//\", \"\"));\n break;\n } else {\n const parent = getParentElement(el);\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (sibling) => sibling.tagName === el.tagName\n );\n const index = siblings.indexOf(el) + 1;\n selector += siblings.length > 1 ? `[${index}]` : \"\";\n }\n parts.unshift(selector);\n }\n }\n currentElement = getParentElement(currentElement);\n }\n const xpath = \"//\" + parts.join(\"/\");\n return xpath;\n }\n async function generateStandardXPath(element) {\n const parts = [];\n while (element && (isTextNode(element) || isElementNode(element))) {\n let index = 0;\n let hasSameTypeSiblings = false;\n const siblings = element.parentElement ? Array.from(element.parentElement.childNodes) : [];\n for (let i = 0; i < siblings.length; i++) {\n const sibling = siblings[i];\n if (sibling.nodeType === element.nodeType && sibling.nodeName === element.nodeName) {\n index = index + 1;\n hasSameTypeSiblings = true;\n if (sibling.isSameNode(element)) {\n break;\n }\n }\n }\n if (element.nodeName !== \"#text\") {\n const tagName = element.nodeName.toLowerCase();\n const pathIndex = hasSameTypeSiblings ? `[${index}]` : \"\";\n parts.unshift(`${tagName}${pathIndex}`);\n }\n element = element.parentElement;\n }\n return parts.length ? `/${parts.join(\"/\")}` : \"\";\n }\n async function generatedIdBasedXPath(element) {\n if (isElementNode(element) && element.id) {\n return `//*[@id='${element.id}']`;\n }\n return null;\n }\n\n // types/stagehandErrors.ts\n var StagehandError = class extends Error {\n constructor(message) {\n super(message);\n this.name = this.constructor.name;\n }\n };\n var StagehandDomProcessError = class extends StagehandError {\n constructor(message) {\n super(`Error Processing Dom: ${message}`);\n }\n };\n\n // lib/dom/utils.ts\n function canElementScroll(elem) {\n if (typeof elem.scrollTo !== \"function\") {\n console.warn(\"canElementScroll: .scrollTo is not a function.\");\n return false;\n }\n try {\n const originalTop = elem.scrollTop;\n elem.scrollTo({\n top: originalTop + 100,\n left: 0,\n behavior: \"instant\"\n });\n if (elem.scrollTop === originalTop) {\n throw new StagehandDomProcessError(\"scrollTop did not change\");\n }\n elem.scrollTo({\n top: originalTop,\n left: 0,\n behavior: \"instant\"\n });\n return true;\n } catch (error) {\n console.warn(\"canElementScroll error:\", error.message || error);\n return false;\n }\n }\n function getNodeFromXpath(xpath) {\n return document.evaluate(\n xpath,\n document.documentElement,\n null,\n XPathResult.FIRST_ORDERED_NODE_TYPE,\n null\n ).singleNodeValue;\n }\n function waitForElementScrollEnd(element, idleMs = 100) {\n return new Promise((resolve) => {\n let scrollEndTimer;\n const handleScroll = () => {\n clearTimeout(scrollEndTimer);\n scrollEndTimer = window.setTimeout(() => {\n element.removeEventListener(\"scroll\", handleScroll);\n resolve();\n }, idleMs);\n };\n element.addEventListener(\"scroll\", handleScroll, { passive: true });\n handleScroll();\n });\n }\n\n // lib/dom/process.ts\n function getScrollableElements(topN) {\n const docEl = document.documentElement;\n const scrollableElements = [docEl];\n const allElements = document.querySelectorAll(\"*\");\n for (const elem of allElements) {\n const style = window.getComputedStyle(elem);\n const overflowY = style.overflowY;\n const isPotentiallyScrollable = overflowY === \"auto\" || overflowY === \"scroll\" || overflowY === \"overlay\";\n if (isPotentiallyScrollable) {\n const candidateScrollDiff = elem.scrollHeight - elem.clientHeight;\n if (candidateScrollDiff > 0 && canElementScroll(elem)) {\n scrollableElements.push(elem);\n }\n }\n }\n scrollableElements.sort((a, b) => b.scrollHeight - a.scrollHeight);\n if (topN !== void 0) {\n return scrollableElements.slice(0, topN);\n }\n return scrollableElements;\n }\n async function getScrollableElementXpaths(topN) {\n const scrollableElems = getScrollableElements(topN);\n const xpaths = [];\n for (const elem of scrollableElems) {\n const allXPaths = await generateXPathsForElement(elem);\n const firstXPath = allXPaths?.[0] || \"\";\n xpaths.push(firstXPath);\n }\n return xpaths;\n }\n (() => {\n const closedRoots = /* @__PURE__ */ new WeakMap();\n const nativeAttachShadow = Element.prototype.attachShadow;\n Element.prototype.attachShadow = function(init) {\n const root = nativeAttachShadow.call(this, init);\n if (init.mode === \"closed\") closedRoots.set(this, root);\n return root;\n };\n const backdoor = {\n getClosedRoot: (host) => closedRoots.get(host),\n queryClosed: (host, selector) => {\n const root = closedRoots.get(host);\n return root ? Array.from(root.querySelectorAll(selector)) : [];\n },\n xpathClosed: (host, xp) => {\n const root = closedRoots.get(host);\n if (!root) return [];\n const it = document.evaluate(\n xp,\n root,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n );\n const out = [];\n for (let i = 0; i < it.snapshotLength; ++i) {\n const n = it.snapshotItem(i);\n if (n) out.push(n);\n }\n return out;\n }\n };\n if (!(\"__stagehand__\" in window)) {\n Object.defineProperty(window, \"__stagehand__\", {\n value: backdoor,\n enumerable: false,\n writable: false,\n configurable: false\n });\n }\n })();\n window.getScrollableElementXpaths = getScrollableElementXpaths;\n window.getNodeFromXpath = getNodeFromXpath;\n window.waitForElementScrollEnd = waitForElementScrollEnd;\n})();\n";
1
+ export declare const scriptContent = "(() => {\n // lib/dom/process.ts\n (() => {\n const closedRoots = /* @__PURE__ */ new WeakMap();\n const nativeAttachShadow = Element.prototype.attachShadow;\n Element.prototype.attachShadow = function(init) {\n const root = nativeAttachShadow.call(this, init);\n if (init.mode === \"closed\") closedRoots.set(this, root);\n return root;\n };\n const backdoor = {\n getClosedRoot: (host) => closedRoots.get(host),\n queryClosed: (host, selector) => {\n const root = closedRoots.get(host);\n return root ? Array.from(root.querySelectorAll(selector)) : [];\n },\n xpathClosed: (host, xp) => {\n const root = closedRoots.get(host);\n if (!root) return [];\n const it = document.evaluate(\n xp,\n root,\n null,\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\n null\n );\n const out = [];\n for (let i = 0; i < it.snapshotLength; ++i) {\n const n = it.snapshotItem(i);\n if (n) out.push(n);\n }\n return out;\n }\n };\n if (!(\"__stagehand__\" in window)) {\n Object.defineProperty(window, \"__stagehand__\", {\n value: backdoor,\n enumerable: false,\n writable: false,\n configurable: false\n });\n }\n })();\n})();\n";
@@ -1,2 +1 @@
1
- export * from "./process";
2
- export * from "./utils";
1
+ import "./process";
@@ -1,17 +0,0 @@
1
- /**
2
- * Finds and returns a list of scrollable elements on the page,
3
- * ordered from the element with the largest scrollHeight to the smallest.
4
- *
5
- * @param topN Optional maximum number of scrollable elements to return.
6
- * If not provided, all found scrollable elements are returned.
7
- * @returns An array of HTMLElements sorted by descending scrollHeight.
8
- */
9
- export declare function getScrollableElements(topN?: number): HTMLElement[];
10
- /**
11
- * Calls getScrollableElements, then for each element calls generateXPaths,
12
- * and returns the first XPath for each.
13
- *
14
- * @param topN (optional) integer limit on how many scrollable elements to process
15
- * @returns string[] list of XPaths (1 for each scrollable element)
16
- */
17
- export declare function getScrollableElementXpaths(topN?: number): Promise<string[]>;
@@ -25,6 +25,9 @@ export declare class StagehandObserveHandler {
25
25
  * @deprecated The `onlyVisible` parameter has no effect in this version of Stagehand and will be removed in later versions.
26
26
  */
27
27
  onlyVisible?: boolean;
28
+ /**
29
+ * @deprecated The `drawOverlay` parameter has no effect in this version of Stagehand and will be removed in later versions.
30
+ */
28
31
  drawOverlay?: boolean;
29
32
  fromAct?: boolean;
30
33
  iframes?: boolean;
@@ -1,12 +1,9 @@
1
1
  import { Schema } from "@google/genai";
2
2
  import { z, ZodTypeAny } from "zod/v3";
3
- import { ObserveResult, Page } from ".";
4
3
  import { LogLine } from "../types/log";
5
4
  import { ModelProvider } from "../types/model";
6
5
  import { ZodPathSegments } from "../types/stagehand";
7
6
  export declare function validateZodSchema(schema: z.ZodTypeAny, data: unknown): boolean;
8
- export declare function drawObserveOverlay(page: Page, results: ObserveResult[]): Promise<void>;
9
- export declare function clearOverlays(page: Page): Promise<void>;
10
7
  /**
11
8
  * Detects if the code is running in the Bun runtime environment.
12
9
  * @returns {boolean} True if running in Bun, false otherwise.
@@ -2,4 +2,4 @@
2
2
  * AUTO-GENERATED — DO NOT EDIT BY HAND
3
3
  * Run `pnpm run gen-version` to refresh.
4
4
  */
5
- export declare const STAGEHAND_VERSION: "2.5.4";
5
+ export declare const STAGEHAND_VERSION: "2.5.6";
@@ -51,6 +51,7 @@ export interface TreeResult {
51
51
  xpathMap: Record<EncodedId, string>;
52
52
  }
53
53
  export type DOMNode = {
54
+ nodeId?: number;
54
55
  backendNodeId?: number;
55
56
  nodeName?: string;
56
57
  children?: DOMNode[];
@@ -59,6 +60,7 @@ export type DOMNode = {
59
60
  nodeType: number;
60
61
  frameId?: string;
61
62
  isScrollable?: boolean;
63
+ childNodeCount?: number;
62
64
  };
63
65
  export type BackendIdMaps = {
64
66
  tagNameMap: Record<number, string>;
@@ -1,7 +1,7 @@
1
1
  import type { ClientOptions as AnthropicClientOptions } from "@anthropic-ai/sdk";
2
2
  import type { ClientOptions as OpenAIClientOptions } from "openai";
3
3
  import { z } from "zod/v3";
4
- export declare const AvailableModelSchema: z.ZodEnum<["gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "o4-mini", "o3", "o3-mini", "o1", "o1-mini", "gpt-4o", "gpt-4o-mini", "gpt-4o-2024-08-06", "gpt-4.5-preview", "o1-preview", "claude-3-5-sonnet-latest", "claude-3-5-sonnet-20241022", "claude-3-5-sonnet-20240620", "claude-3-7-sonnet-latest", "claude-3-7-sonnet-20250219", "cerebras-llama-3.3-70b", "cerebras-llama-3.1-8b", "groq-llama-3.3-70b-versatile", "groq-llama-3.3-70b-specdec", "gemini-1.5-flash", "gemini-1.5-pro", "gemini-1.5-flash-8b", "gemini-2.0-flash-lite", "gemini-2.0-flash", "gemini-2.5-flash-preview-04-17", "gemini-2.5-pro-preview-03-25"]>;
4
+ export declare const AvailableModelSchema: z.ZodEnum<["gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "o4-mini", "o3", "o3-mini", "o1", "o1-mini", "gpt-4o", "gpt-4o-mini", "gpt-4o-2024-08-06", "gpt-4.5-preview", "o1-preview", "claude-haiku-4-5", "claude-3-7-sonnet-latest", "claude-3-7-sonnet-20250219", "cerebras-llama-3.3-70b", "cerebras-llama-3.1-8b", "groq-llama-3.3-70b-versatile", "groq-llama-3.3-70b-specdec", "gemini-1.5-flash", "gemini-1.5-pro", "gemini-1.5-flash-8b", "gemini-2.0-flash-lite", "gemini-2.0-flash", "gemini-2.5-flash-preview-04-17", "gemini-2.5-pro-preview-03-25"]>;
5
5
  export type AvailableModel = z.infer<typeof AvailableModelSchema> | string;
6
6
  export type ModelProvider = "openai" | "anthropic" | "cerebras" | "groq" | "google" | "aisdk";
7
7
  export type ClientOptions = OpenAIClientOptions | AnthropicClientOptions;
@@ -150,6 +150,9 @@ export interface ObserveOptions {
150
150
  * @deprecated The `onlyVisible` parameter has no effect in this version of Stagehand and will be removed in later versions.
151
151
  */
152
152
  onlyVisible?: boolean;
153
+ /**
154
+ * @deprecated The `drawOverlay` parameter has no effect in this version of Stagehand and will be removed in later versions.
155
+ */
153
156
  drawOverlay?: boolean;
154
157
  iframes?: boolean;
155
158
  frameId?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserbasehq/stagehand",
3
- "version": "2.5.4",
3
+ "version": "2.5.6",
4
4
  "description": "An AI web browsing framework focused on simplicity and extensibility.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -1,2 +0,0 @@
1
- export declare function isElementNode(node: Node): node is Element;
2
- export declare function isTextNode(node: Node): node is Text;
@@ -1,7 +0,0 @@
1
- /**
2
- * Tests if the element actually responds to .scrollTo(...)
3
- * and that scrollTop changes as expected.
4
- */
5
- export declare function canElementScroll(elem: HTMLElement): boolean;
6
- export declare function getNodeFromXpath(xpath: string): Node;
7
- export declare function waitForElementScrollEnd(element: HTMLElement, idleMs?: number): Promise<void>;
@@ -1,14 +0,0 @@
1
- /**
2
- * Escapes a string for use in an XPath expression.
3
- * Handles special characters, including single and double quotes.
4
- * @param value - The string to escape.
5
- * @returns The escaped string safe for XPath.
6
- */
7
- export declare function escapeXPathString(value: string): string;
8
- /**
9
- * Generates both a complicated XPath and a standard XPath for a given DOM element.
10
- * @param element - The target DOM element.
11
- * @param documentOverride - Optional document override.
12
- * @returns An object containing both XPaths.
13
- */
14
- export declare function generateXPathsForElement(element: ChildNode): Promise<string[]>;