@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 +5 -2
- package/dist/index.js +136 -99
- package/dist/lib/StagehandContext.d.ts +1 -0
- package/dist/lib/StagehandPage.d.ts +0 -1
- package/dist/lib/dom/build/scriptContent.d.ts +1 -1
- package/dist/lib/dom/index.d.ts +1 -2
- package/dist/lib/dom/process.d.ts +0 -17
- package/dist/lib/handlers/observeHandler.d.ts +3 -0
- package/dist/lib/utils.d.ts +0 -3
- package/dist/lib/version.d.ts +1 -1
- package/dist/types/context.d.ts +2 -0
- package/dist/types/model.d.ts +1 -1
- package/dist/types/stagehand.d.ts +3 -0
- package/package.json +1 -1
- package/dist/lib/dom/elementCheckUtils.d.ts +0 -2
- package/dist/lib/dom/utils.d.ts +0 -7
- package/dist/lib/dom/xpathUtils.d.ts +0 -14
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-
|
|
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.
|
|
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
|
|
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
|
|
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-
|
|
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-
|
|
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";
|
package/dist/lib/dom/index.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
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;
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -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.
|
package/dist/lib/version.d.ts
CHANGED
package/dist/types/context.d.ts
CHANGED
|
@@ -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>;
|
package/dist/types/model.d.ts
CHANGED
|
@@ -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-
|
|
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
package/dist/lib/dom/utils.d.ts
DELETED
|
@@ -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[]>;
|