@enricai/barnacle 1.12.70 → 1.12.72
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/recon/capture-filters.d.ts +8 -1
- package/dist/recon/capture-filters.d.ts.map +1 -1
- package/dist/recon/capture-filters.js +97 -26
- package/dist/recon/capture-filters.js.map +1 -1
- package/dist/scraper/browser-click-expr.d.ts +3 -4
- package/dist/scraper/browser-click-expr.d.ts.map +1 -1
- package/dist/scraper/browser-click-expr.js +3 -4
- package/dist/scraper/browser-click-expr.js.map +1 -1
- package/dist/scraper/flow-runner.d.ts +27 -6
- package/dist/scraper/flow-runner.d.ts.map +1 -1
- package/dist/scraper/flow-runner.js +328 -70
- package/dist/scraper/flow-runner.js.map +1 -1
- package/dist/scraper/frame-target.d.ts +12 -0
- package/dist/scraper/frame-target.d.ts.map +1 -1
- package/dist/scraper/frame-target.js +1 -0
- package/dist/scraper/frame-target.js.map +1 -1
- package/dist/scraper/submit-control.d.ts +52 -2
- package/dist/scraper/submit-control.d.ts.map +1 -1
- package/dist/scraper/submit-control.js +117 -21
- package/dist/scraper/submit-control.js.map +1 -1
- package/dist/scraper/target-resolution-diagnostic.d.ts +53 -0
- package/dist/scraper/target-resolution-diagnostic.d.ts.map +1 -0
- package/dist/scraper/target-resolution-diagnostic.js +153 -0
- package/dist/scraper/target-resolution-diagnostic.js.map +1 -0
- package/dist/scripts/recon-browser.d.ts +32 -2
- package/dist/scripts/recon-browser.d.ts.map +1 -1
- package/dist/scripts/recon-browser.js +2 -0
- package/dist/scripts/recon-browser.js.map +1 -1
- package/dist/scripts/recon-generate.d.ts +148 -6
- package/dist/scripts/recon-generate.d.ts.map +1 -1
- package/dist/scripts/recon-generate.js +575 -93
- package/dist/scripts/recon-generate.js.map +1 -1
- package/package.json +1 -1
- package/dist/scraper/deep-query.d.ts +0 -44
- package/dist/scraper/deep-query.d.ts.map +0 -1
- package/dist/scraper/deep-query.js +0 -93
- package/dist/scraper/deep-query.js.map +0 -1
|
@@ -64,6 +64,18 @@ export declare function mainFrameTarget(page: Page, opts?: {
|
|
|
64
64
|
declaredFrameSelector?: string | null;
|
|
65
65
|
evaluateTimeoutMs?: number;
|
|
66
66
|
}): FrameTarget;
|
|
67
|
+
/**
|
|
68
|
+
* Builds a child-frame `FrameTarget`: `evaluate`/`locator` delegate to the
|
|
69
|
+
* resolved `Frame` (reaching across the cross-origin boundary via its own
|
|
70
|
+
* CDP session), while `url`/`title` fall back to the frame's own
|
|
71
|
+
* `location.href` and the top document's title respectively — `Frame` has
|
|
72
|
+
* no `title()` of its own. `evaluate`/`url`/`title` are bounded by the same
|
|
73
|
+
* watchdog as `mainFrameTarget` (`locator` stays unwrapped — it's
|
|
74
|
+
* synchronous, building a `Locator` handle rather than making a CDP call).
|
|
75
|
+
*/
|
|
76
|
+
export declare function childFrameTarget(page: Page, frame: StagehandFrame, frameSelector: string, opts?: {
|
|
77
|
+
evaluateTimeoutMs?: number;
|
|
78
|
+
}): FrameTarget;
|
|
67
79
|
/**
|
|
68
80
|
* Single non-polling presence probe for a frame that may have already
|
|
69
81
|
* attached — the seam callers should use instead of hand-rolling
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-target.d.ts","sourceRoot":"","sources":["../../src/scraper/frame-target.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAQrD,kHAAkH;AAClH,KAAK,cAAc,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,uFAAuF;IACvF,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,uIAAuI;IACvI,QAAQ,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC;;;;;;;;;;;;OAYG;IACH,QAAQ,CAAC,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/C,wGAAwG;IACxG,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,OAAO,EACjC,wBAAwB,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,EACjE,GAAG,CAAC,EAAE,GAAG,GACR,OAAO,CAAC,CAAC,CAAC,CAAC;IACd,wFAAwF;IACxF,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;IACvD,6EAA6E;IAC7E,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACvB,gMAAgM;IAChM,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CAC1B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,IAAI,EACV,IAAI,GAAE;IAAE,qBAAqB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/E,WAAW,CAmBb;
|
|
1
|
+
{"version":3,"file":"frame-target.d.ts","sourceRoot":"","sources":["../../src/scraper/frame-target.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.mainFrameTarget = mainFrameTarget;
|
|
16
|
+
exports.childFrameTarget = childFrameTarget;
|
|
16
17
|
exports.probeAttachedFrameTarget = probeAttachedFrameTarget;
|
|
17
18
|
exports.resolveFrameTarget = resolveFrameTarget;
|
|
18
19
|
exports.readCurrentFrameUrl = readCurrentFrameUrl;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-target.js","sourceRoot":"","sources":["../../src/scraper/frame-target.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG
|
|
1
|
+
{"version":3,"file":"frame-target.js","sourceRoot":"","sources":["../../src/scraper/frame-target.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Submit-control locator: ranks every submit-shaped candidate the deep
|
|
3
|
-
* resolver
|
|
3
|
+
* resolver can reach — piercing open shadow roots — so
|
|
4
4
|
* the cascade can act on the best-ranked candidate and retry the runner-up
|
|
5
5
|
* if the first click phantoms. A false-positive submit click on a real run
|
|
6
6
|
* (e.g. clicking "Save draft") is worse than the current failure, since it
|
|
@@ -8,6 +8,56 @@
|
|
|
8
8
|
* conservative: only tiers with strong, unambiguous submit signal are
|
|
9
9
|
* included, and "Back"/"Cancel"/"Save draft"-shaped controls never appear.
|
|
10
10
|
*/
|
|
11
|
+
/**
|
|
12
|
+
* Verbs that identify a control as NOT the submit action even when it is
|
|
13
|
+
* button-shaped and reachable. Checked before any positive tier so a
|
|
14
|
+
* button whose text merely contains "submit" as a substring of a longer
|
|
15
|
+
* negative phrase (unlikely in practice, but the exclusion is what makes
|
|
16
|
+
* the ranking conservative) cannot slip through. Exported so other
|
|
17
|
+
* submit-shape consumers (e.g. flow-runner.ts's xpath tail-retarget
|
|
18
|
+
* disambiguation) apply the identical negative-verb vocabulary instead of a
|
|
19
|
+
* second, driftable copy.
|
|
20
|
+
*/
|
|
21
|
+
export declare const NEGATIVE_TEXT_EXPR = "((text) => {\n const negatives = [\"back\", \"cancel\", \"save draft\", \"save for later\", \"previous\", \"close\"];\n return negatives.some((n) => text === n || text.startsWith(n + \" \") || text.endsWith(\" \" + n));\n})";
|
|
22
|
+
/**
|
|
23
|
+
* Tag/role-agnostic tier-0.5 fallback: a generic-action-verb accessible name
|
|
24
|
+
* (create/continue/next/confirm/proceed — the labels a JS-handled action
|
|
25
|
+
* control with an explicit `type="button"`, or a plain `<div>`/`<a>`/custom-
|
|
26
|
+
* element with a click handler, commonly uses instead of the literal word
|
|
27
|
+
* "submit") qualifies regardless of tag/role, or — when the candidate carries
|
|
28
|
+
* no text signal of its own at all — it is the sole non-excluded button/
|
|
29
|
+
* role="button" control inside its nearest form-like (`<form>` /
|
|
30
|
+
* `[role="form"]`) ancestor. Kept as a
|
|
31
|
+
* separate export (rather than folded into {@link RANK_TIERS_EXPR} inline) so
|
|
32
|
+
* `flow-runner.ts`'s independent hand-rolled submit-shape predicates can
|
|
33
|
+
* import and apply the identical widened signal instead of re-diverging.
|
|
34
|
+
* Deliberately does NOT relax the isButtonLike gate itself — that would
|
|
35
|
+
* accept any div/input regardless of text, exactly the "arbitrary structural
|
|
36
|
+
* divs" false-positive this module's docblock warns against.
|
|
37
|
+
*/
|
|
38
|
+
export declare const SUBMIT_SHAPE_FALLBACK_EXPR = "((el, name, isNegative) => {\n if (/\\b(create|continue|next|confirm|proceed)\\b/.test(name)) return true;\n if (name !== \"\") return false;\n const isFormLike = (node) =>\n (node.tagName || \"\").toLowerCase() === \"form\" ||\n (node.getAttribute && (node.getAttribute(\"role\") || \"\").toLowerCase() === \"form\");\n const findFormContainer = (node) => {\n for (let depth = 0; depth < 6 && node; depth++) {\n if (isFormLike(node)) return node;\n node = node.parentElement;\n }\n return null;\n };\n const container = findFormContainer(el.parentElement);\n if (!container) return false;\n const accessibleName = ((el) => {\n const norm = (s) => (s || \"\").replace(/\\s+/g, \" \").trim().toLowerCase();\n const tag = (el.tagName || \"\").toLowerCase();\n const fallback = tag === \"input\" ? el.value : el.textContent;\n return norm(el.getAttribute(\"aria-label\") || fallback || \"\");\n});\n const isCandidate = (c) => {\n if (c === el) return true;\n const cTag = (c.tagName || \"\").toLowerCase();\n const cRole = (c.getAttribute(\"role\") || \"\").toLowerCase();\n if (cTag !== \"button\" && cTag !== \"input\" && cRole !== \"button\") return false;\n return !isNegative(accessibleName(c));\n };\n const candidates = Array.from(container.querySelectorAll(\"*\")).filter(isCandidate);\n return candidates.length === 1 && candidates[0] === el;\n})";
|
|
39
|
+
/**
|
|
40
|
+
* Single site-agnostic submit-shape predicate: `(el) => boolean`, composing
|
|
41
|
+
* {@link NEGATIVE_TEXT_EXPR}, {@link ACCESSIBLE_NAME_EXPR}, and
|
|
42
|
+
* {@link SUBMIT_SHAPE_FALLBACK_EXPR} so every caller shares one decision
|
|
43
|
+
* boundary instead of hand-rolling a divergent copy. No tag or `type`
|
|
44
|
+
* attribute — not even `<input type="submit">`/`type="image">`, nor an
|
|
45
|
+
* explicit `type="submit"` on a `<button>`/`<input>` — earns unconditional
|
|
46
|
+
* structural credit: a native submit-typed control that click-intercepts
|
|
47
|
+
* rather than actually submitting (e.g. a "Show contact form" reveal toggle
|
|
48
|
+
* a page happens to mark up as `<button type="submit">` for layout reasons,
|
|
49
|
+
* with no submit intent at all) must earn its credit through the SAME
|
|
50
|
+
* corroboration path as a non-native `<div>`/`<a>`/custom-element action
|
|
51
|
+
* control — {@link SUBMIT_SHAPE_FALLBACK_EXPR}'s generic-action-verb
|
|
52
|
+
* accessible name, or sole-actionable-candidate-in-form when it carries no
|
|
53
|
+
* text. Exported so `flow-runner.ts`'s `resolvedClickTargetIsSubmitShaped` /
|
|
54
|
+
* `XPATH_TAIL_RETARGET_RESOLVE_FN_SRC` share this one boolean producer
|
|
55
|
+
* instead of re-diverging. {@link RANK_TIERS_EXPR} independently retains the
|
|
56
|
+
* unconditional explicit-`type="submit"` credit for its own graduated (not
|
|
57
|
+
* boolean) tiering — a separate producer used for candidate
|
|
58
|
+
* ranking/disambiguation, not this verification veto.
|
|
59
|
+
*/
|
|
60
|
+
export declare const SUBMIT_SHAPE_EXPR = "((el) => {\n if (!el || !el.tagName) return false;\n const isNegative = ((text) => {\n const negatives = [\"back\", \"cancel\", \"save draft\", \"save for later\", \"previous\", \"close\"];\n return negatives.some((n) => text === n || text.startsWith(n + \" \") || text.endsWith(\" \" + n));\n});\n const accessibleName = ((el) => {\n const norm = (s) => (s || \"\").replace(/\\s+/g, \" \").trim().toLowerCase();\n const tag = (el.tagName || \"\").toLowerCase();\n const fallback = tag === \"input\" ? el.value : el.textContent;\n return norm(el.getAttribute(\"aria-label\") || fallback || \"\");\n});\n const name = accessibleName(el);\n if (isNegative(name)) return false;\n const isFallbackShaped = ((el, name, isNegative) => {\n if (/\\b(create|continue|next|confirm|proceed)\\b/.test(name)) return true;\n if (name !== \"\") return false;\n const isFormLike = (node) =>\n (node.tagName || \"\").toLowerCase() === \"form\" ||\n (node.getAttribute && (node.getAttribute(\"role\") || \"\").toLowerCase() === \"form\");\n const findFormContainer = (node) => {\n for (let depth = 0; depth < 6 && node; depth++) {\n if (isFormLike(node)) return node;\n node = node.parentElement;\n }\n return null;\n };\n const container = findFormContainer(el.parentElement);\n if (!container) return false;\n const accessibleName = ((el) => {\n const norm = (s) => (s || \"\").replace(/\\s+/g, \" \").trim().toLowerCase();\n const tag = (el.tagName || \"\").toLowerCase();\n const fallback = tag === \"input\" ? el.value : el.textContent;\n return norm(el.getAttribute(\"aria-label\") || fallback || \"\");\n});\n const isCandidate = (c) => {\n if (c === el) return true;\n const cTag = (c.tagName || \"\").toLowerCase();\n const cRole = (c.getAttribute(\"role\") || \"\").toLowerCase();\n if (cTag !== \"button\" && cTag !== \"input\" && cRole !== \"button\") return false;\n return !isNegative(accessibleName(c));\n };\n const candidates = Array.from(container.querySelectorAll(\"*\")).filter(isCandidate);\n return candidates.length === 1 && candidates[0] === el;\n});\n return isFallbackShaped(el, name, isNegative);\n})";
|
|
11
61
|
/**
|
|
12
62
|
* Builds a self-contained `page.evaluate` expression string that walks the
|
|
13
63
|
* whole document (light DOM plus every open shadow root, arbitrarily deep)
|
|
@@ -65,7 +115,7 @@ export declare function buildRankSubmitCandidatesExpr(root?: string): string;
|
|
|
65
115
|
*/
|
|
66
116
|
export declare function buildClickByDeepIndexExpr(deepIndex: number, root?: string): string;
|
|
67
117
|
/** Confidence tier for a ranked submit candidate — higher is more confident. See {@link buildRankSubmitCandidatesExpr}. */
|
|
68
|
-
export type SubmitCandidateTier = 1 | 2 | 3;
|
|
118
|
+
export type SubmitCandidateTier = 0.5 | 1 | 2 | 3;
|
|
69
119
|
/** One ranked candidate returned by {@link buildRankSubmitCandidatesExpr}'s `page.evaluate` call. */
|
|
70
120
|
export interface SubmitCandidate {
|
|
71
121
|
/** Position in the deterministic deep-traversal order; pass to {@link buildClickByDeepIndexExpr} to click this exact candidate. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit-control.d.ts","sourceRoot":"","sources":["../../src/scraper/submit-control.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"submit-control.d.ts","sourceRoot":"","sources":["../../src/scraper/submit-control.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;;;;;;GASG;AACH,eAAO,MAAM,kBAAkB,sOAG5B,CAAC;AA8EJ;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,0BAA0B,s4CAyBpC,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,iBAAiB,uoEAQ3B,CAAC;AA+CJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,SAAa,GAAG,MAAM,CA0BvE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,SAAa,GAAG,MAAM,CAYtF;AAED,2HAA2H;AAC3H,MAAM,MAAM,mBAAmB,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAElD,qGAAqG;AACrG,MAAM,WAAW,eAAe;IAC9B,mIAAmI;IACnI,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,0EAA0E;AAC1E,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,oKAAoK;IACpK,MAAM,CAAC,EAAE,gBAAgB,CAAC;CAC3B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
3
|
* Submit-control locator: ranks every submit-shaped candidate the deep
|
|
4
|
-
* resolver
|
|
4
|
+
* resolver can reach — piercing open shadow roots — so
|
|
5
5
|
* the cascade can act on the best-ranked candidate and retry the runner-up
|
|
6
6
|
* if the first click phantoms. A false-positive submit click on a real run
|
|
7
7
|
* (e.g. clicking "Save draft") is worse than the current failure, since it
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
* included, and "Back"/"Cancel"/"Save draft"-shaped controls never appear.
|
|
11
11
|
*/
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.SUBMIT_SHAPE_EXPR = exports.SUBMIT_SHAPE_FALLBACK_EXPR = exports.NEGATIVE_TEXT_EXPR = void 0;
|
|
13
14
|
exports.buildRankSubmitCandidatesExpr = buildRankSubmitCandidatesExpr;
|
|
14
15
|
exports.buildClickByDeepIndexExpr = buildClickByDeepIndexExpr;
|
|
15
16
|
const browser_click_expr_1 = require("./browser-click-expr");
|
|
@@ -18,21 +19,29 @@ const browser_click_expr_1 = require("./browser-click-expr");
|
|
|
18
19
|
* button-shaped and reachable. Checked before any positive tier so a
|
|
19
20
|
* button whose text merely contains "submit" as a substring of a longer
|
|
20
21
|
* negative phrase (unlikely in practice, but the exclusion is what makes
|
|
21
|
-
* the ranking conservative) cannot slip through.
|
|
22
|
+
* the ranking conservative) cannot slip through. Exported so other
|
|
23
|
+
* submit-shape consumers (e.g. flow-runner.ts's xpath tail-retarget
|
|
24
|
+
* disambiguation) apply the identical negative-verb vocabulary instead of a
|
|
25
|
+
* second, driftable copy.
|
|
22
26
|
*/
|
|
23
|
-
|
|
27
|
+
exports.NEGATIVE_TEXT_EXPR = `((text) => {
|
|
24
28
|
const negatives = ["back", "cancel", "save draft", "save for later", "previous", "close"];
|
|
25
29
|
return negatives.some((n) => text === n || text.startsWith(n + " ") || text.endsWith(" " + n));
|
|
26
30
|
})`;
|
|
27
31
|
/**
|
|
28
32
|
* Normalizes an element's accessible name to lowercase, whitespace-collapsed
|
|
29
|
-
* text, preferring `aria-label` over visible `textContent
|
|
30
|
-
* `
|
|
31
|
-
*
|
|
33
|
+
* text, preferring `aria-label` over visible `textContent`, falling back to
|
|
34
|
+
* `value` for an `<input>` (which never has text-node children, so its
|
|
35
|
+
* accessible name comes from its `value` attribute per native AccName
|
|
36
|
+
* semantics — without this, an `<input type="submit" value="Create
|
|
37
|
+
* Account">` normalizes to an empty name and cannot earn corroboration
|
|
38
|
+
* through {@link SUBMIT_SHAPE_FALLBACK_EXPR}'s generic-action-verb check).
|
|
32
39
|
*/
|
|
33
40
|
const ACCESSIBLE_NAME_EXPR = `((el) => {
|
|
34
41
|
const norm = (s) => (s || "").replace(/\\s+/g, " ").trim().toLowerCase();
|
|
35
|
-
|
|
42
|
+
const tag = (el.tagName || "").toLowerCase();
|
|
43
|
+
const fallback = tag === "input" ? el.value : el.textContent;
|
|
44
|
+
return norm(el.getAttribute("aria-label") || fallback || "");
|
|
36
45
|
})`;
|
|
37
46
|
/**
|
|
38
47
|
* Visibility check: a node with a 0x0 layout box, or a computed
|
|
@@ -75,10 +84,9 @@ const IS_DISABLED_EXPR = `((el) => {
|
|
|
75
84
|
return false;
|
|
76
85
|
})`;
|
|
77
86
|
/**
|
|
78
|
-
* Recursive open-shadow-root walker,
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
* not runtime code that can share a module import).
|
|
87
|
+
* Recursive open-shadow-root walker, composed as a browser-context
|
|
88
|
+
* expression string via string interpolation rather than runtime code that
|
|
89
|
+
* could share a module import.
|
|
82
90
|
*/
|
|
83
91
|
const DEEP_ELEMENTS_EXPR = `((root) => {
|
|
84
92
|
const out = [];
|
|
@@ -92,32 +100,120 @@ const DEEP_ELEMENTS_EXPR = `((root) => {
|
|
|
92
100
|
walk(root);
|
|
93
101
|
return out;
|
|
94
102
|
})`;
|
|
103
|
+
/**
|
|
104
|
+
* Tag/role-agnostic tier-0.5 fallback: a generic-action-verb accessible name
|
|
105
|
+
* (create/continue/next/confirm/proceed — the labels a JS-handled action
|
|
106
|
+
* control with an explicit `type="button"`, or a plain `<div>`/`<a>`/custom-
|
|
107
|
+
* element with a click handler, commonly uses instead of the literal word
|
|
108
|
+
* "submit") qualifies regardless of tag/role, or — when the candidate carries
|
|
109
|
+
* no text signal of its own at all — it is the sole non-excluded button/
|
|
110
|
+
* role="button" control inside its nearest form-like (`<form>` /
|
|
111
|
+
* `[role="form"]`) ancestor. Kept as a
|
|
112
|
+
* separate export (rather than folded into {@link RANK_TIERS_EXPR} inline) so
|
|
113
|
+
* `flow-runner.ts`'s independent hand-rolled submit-shape predicates can
|
|
114
|
+
* import and apply the identical widened signal instead of re-diverging.
|
|
115
|
+
* Deliberately does NOT relax the isButtonLike gate itself — that would
|
|
116
|
+
* accept any div/input regardless of text, exactly the "arbitrary structural
|
|
117
|
+
* divs" false-positive this module's docblock warns against.
|
|
118
|
+
*/
|
|
119
|
+
exports.SUBMIT_SHAPE_FALLBACK_EXPR = `((el, name, isNegative) => {
|
|
120
|
+
if (/\\b(create|continue|next|confirm|proceed)\\b/.test(name)) return true;
|
|
121
|
+
if (name !== "") return false;
|
|
122
|
+
const isFormLike = (node) =>
|
|
123
|
+
(node.tagName || "").toLowerCase() === "form" ||
|
|
124
|
+
(node.getAttribute && (node.getAttribute("role") || "").toLowerCase() === "form");
|
|
125
|
+
const findFormContainer = (node) => {
|
|
126
|
+
for (let depth = 0; depth < ${browser_click_expr_1.MAX_SELECTION_ANCESTOR_DEPTH} && node; depth++) {
|
|
127
|
+
if (isFormLike(node)) return node;
|
|
128
|
+
node = node.parentElement;
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
};
|
|
132
|
+
const container = findFormContainer(el.parentElement);
|
|
133
|
+
if (!container) return false;
|
|
134
|
+
const accessibleName = ${ACCESSIBLE_NAME_EXPR};
|
|
135
|
+
const isCandidate = (c) => {
|
|
136
|
+
if (c === el) return true;
|
|
137
|
+
const cTag = (c.tagName || "").toLowerCase();
|
|
138
|
+
const cRole = (c.getAttribute("role") || "").toLowerCase();
|
|
139
|
+
if (cTag !== "button" && cTag !== "input" && cRole !== "button") return false;
|
|
140
|
+
return !isNegative(accessibleName(c));
|
|
141
|
+
};
|
|
142
|
+
const candidates = Array.from(container.querySelectorAll("*")).filter(isCandidate);
|
|
143
|
+
return candidates.length === 1 && candidates[0] === el;
|
|
144
|
+
})`;
|
|
145
|
+
/**
|
|
146
|
+
* Single site-agnostic submit-shape predicate: `(el) => boolean`, composing
|
|
147
|
+
* {@link NEGATIVE_TEXT_EXPR}, {@link ACCESSIBLE_NAME_EXPR}, and
|
|
148
|
+
* {@link SUBMIT_SHAPE_FALLBACK_EXPR} so every caller shares one decision
|
|
149
|
+
* boundary instead of hand-rolling a divergent copy. No tag or `type`
|
|
150
|
+
* attribute — not even `<input type="submit">`/`type="image">`, nor an
|
|
151
|
+
* explicit `type="submit"` on a `<button>`/`<input>` — earns unconditional
|
|
152
|
+
* structural credit: a native submit-typed control that click-intercepts
|
|
153
|
+
* rather than actually submitting (e.g. a "Show contact form" reveal toggle
|
|
154
|
+
* a page happens to mark up as `<button type="submit">` for layout reasons,
|
|
155
|
+
* with no submit intent at all) must earn its credit through the SAME
|
|
156
|
+
* corroboration path as a non-native `<div>`/`<a>`/custom-element action
|
|
157
|
+
* control — {@link SUBMIT_SHAPE_FALLBACK_EXPR}'s generic-action-verb
|
|
158
|
+
* accessible name, or sole-actionable-candidate-in-form when it carries no
|
|
159
|
+
* text. Exported so `flow-runner.ts`'s `resolvedClickTargetIsSubmitShaped` /
|
|
160
|
+
* `XPATH_TAIL_RETARGET_RESOLVE_FN_SRC` share this one boolean producer
|
|
161
|
+
* instead of re-diverging. {@link RANK_TIERS_EXPR} independently retains the
|
|
162
|
+
* unconditional explicit-`type="submit"` credit for its own graduated (not
|
|
163
|
+
* boolean) tiering — a separate producer used for candidate
|
|
164
|
+
* ranking/disambiguation, not this verification veto.
|
|
165
|
+
*/
|
|
166
|
+
exports.SUBMIT_SHAPE_EXPR = `((el) => {
|
|
167
|
+
if (!el || !el.tagName) return false;
|
|
168
|
+
const isNegative = ${exports.NEGATIVE_TEXT_EXPR};
|
|
169
|
+
const accessibleName = ${ACCESSIBLE_NAME_EXPR};
|
|
170
|
+
const name = accessibleName(el);
|
|
171
|
+
if (isNegative(name)) return false;
|
|
172
|
+
const isFallbackShaped = ${exports.SUBMIT_SHAPE_FALLBACK_EXPR};
|
|
173
|
+
return isFallbackShaped(el, name, isNegative);
|
|
174
|
+
})`;
|
|
95
175
|
/**
|
|
96
176
|
* Ranking tiers, most confident first. Each tier's `test` receives the
|
|
97
177
|
* element plus its precomputed accessible name and reports whether it
|
|
98
178
|
* belongs in that tier — the first matching tier wins, so an element that
|
|
99
179
|
* qualifies for tier 1 is never re-evaluated against tier 2/3.
|
|
100
180
|
*
|
|
101
|
-
* 1. Explicit `type="submit"` — unambiguous native semantics.
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
181
|
+
* 1. Explicit `type="submit"` — unambiguous native semantics. `type` is only
|
|
182
|
+
* meaningful on button/input elements, so this tier alone still requires
|
|
183
|
+
* one of those tags.
|
|
184
|
+
* 2. Accessible name is exactly (or is dominated by) "submit" — covers a
|
|
185
|
+
* `<div>`/`<span>`/custom-element control (e.g. a newsletter form's
|
|
186
|
+
* click-handled `<span>Submit</span>`) whose text is "Submit" but carries
|
|
187
|
+
* no native tag, type attribute, or explicit role (Stencil/web-component
|
|
188
|
+
* controls often omit all three).
|
|
189
|
+
* 3. Accessible name contains "submit" as a distinct word alongside other
|
|
190
|
+
* text (e.g. "Submit Application"), with no negative verb present —
|
|
191
|
+
* covers any element matched by text alone rather than by tag/type/role,
|
|
192
|
+
* including a checkout form's non-button submit control.
|
|
193
|
+
* 4. Button/role="button" element with no submit wording at all and no
|
|
194
|
+
* negative verb present (e.g. `<button type="button">Create Account</button>`),
|
|
195
|
+
* OR — regardless of tag/role — an accessible name carrying a generic
|
|
196
|
+
* action verb (e.g. a `<div>`/`<a>`'s "Create Account"), OR a candidate
|
|
197
|
+
* with no text signal at all that is the sole non-excluded actionable
|
|
198
|
+
* control inside its nearest form-like container (see
|
|
199
|
+
* {@link SUBMIT_SHAPE_FALLBACK_EXPR}) — a generic action control the
|
|
200
|
+
* earlier tiers cannot recognize by submit-specific wording, kept weakest
|
|
201
|
+
* and evaluated last so it never outranks a tier with real submit signal
|
|
202
|
+
* and only surfaces when nothing stronger is on the page.
|
|
109
203
|
*/
|
|
110
204
|
const RANK_TIERS_EXPR = `((el, name) => {
|
|
111
|
-
const isNegative = ${NEGATIVE_TEXT_EXPR};
|
|
205
|
+
const isNegative = ${exports.NEGATIVE_TEXT_EXPR};
|
|
112
206
|
if (isNegative(name)) return 0;
|
|
113
207
|
const tag = (el.tagName || "").toLowerCase();
|
|
114
208
|
const type = (el.getAttribute("type") || "").toLowerCase();
|
|
115
209
|
const role = (el.getAttribute("role") || "").toLowerCase();
|
|
116
210
|
const isButtonLike = tag === "button" || tag === "input" || role === "button";
|
|
117
|
-
if (!isButtonLike) return 0;
|
|
118
211
|
if ((tag === "button" || tag === "input") && type === "submit") return 3;
|
|
119
212
|
if (name === "submit") return 2;
|
|
120
213
|
if (/\\bsubmit\\b/.test(name)) return 1;
|
|
214
|
+
if (isButtonLike) return 0.5;
|
|
215
|
+
const isFallbackShaped = ${exports.SUBMIT_SHAPE_FALLBACK_EXPR};
|
|
216
|
+
if (isFallbackShaped(el, name, isNegative)) return 0.5;
|
|
121
217
|
return 0;
|
|
122
218
|
})`;
|
|
123
219
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit-control.js","sourceRoot":"","sources":["../../src/scraper/submit-control.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG
|
|
1
|
+
{"version":3,"file":"submit-control.js","sourceRoot":"","sources":["../../src/scraper/submit-control.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;;;AAEH,qEAAiG;AAEjG;;;;;;;;;GASG;AACU,QAAA,kBAAkB,GAAG;;;GAG/B,CAAC;AAEJ;;;;;;;;GAQG;AACH,MAAM,oBAAoB,GAAG;;;;;GAK1B,CAAC;AAEJ;;;;;;;;;;GAUG;AACH,MAAM,eAAe,GAAG;;;;;GAKrB,CAAC;AAEJ;;;;;;;;;;;;;;GAcG;AACH,MAAM,gBAAgB,GAAG;gCACO,iDAA4B;;;;;;GAMzD,CAAC;AAEJ;;;;GAIG;AACH,MAAM,kBAAkB,GAAG;;;;;;;;;;;GAWxB,CAAC;AAEJ;;;;;;;;;;;;;;;GAeG;AACU,QAAA,0BAA0B,GAAG;;;;;;;kCAOR,iDAA4B;;;;;;;;2BAQnC,oBAAoB;;;;;;;;;;GAU5C,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;GAoBG;AACU,QAAA,iBAAiB,GAAG;;uBAEV,QAAA,kBAAkB;2BACd,oBAAoB;;;6BAGlB,QAAA,0BAA0B;;GAEpD,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,eAAe,GAAG;uBACD,QAAA,kBAAkB;;;;;;;;;;6BAUZ,QAAA,0BAA0B;;;GAGpD,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,uCAA8C,IAAI,GAAG,UAAU;IAC7D,OAAO;6BACoB,oBAAoB;uBAC1B,eAAe;wBACd,eAAe;yBACd,gBAAgB;2BACd,kBAAkB;+BACd,IAAI;;;;;;;;;;;;;;;;;;OAkB5B,CAAC;AACR,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,mCAA0C,SAAiB,EAAE,IAAI,GAAG,UAAU;IAC5E,OAAO;wBACe,eAAe;yBACd,gBAAgB;2BACd,kBAAkB;+BACd,IAAI;qBACd,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;;;MAGxC,IAAA,wCAAmB,EAAC,IAAI,CAAC;;OAExB,CAAC;AACR,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target-resolution failure diagnostic: when every technique the cascade has
|
|
3
|
+
* (Stagehand act/observe, the deep-locator resolver, the child-iframe
|
|
4
|
+
* fallback) fails to find a step's target, the next person debugging that
|
|
5
|
+
* failure has nothing to go on but a body-HTML dump and a guess. This module
|
|
6
|
+
* captures WHAT the submit-shaped ranking itself saw at the moment of
|
|
7
|
+
* failure — every candidate it ranked, with enough identity (tag, role,
|
|
8
|
+
* accessible name, tier, visibility, disabled state) to tell "the target
|
|
9
|
+
* genuinely wasn't there" apart from "it was there but ranked wrong" or "it
|
|
10
|
+
* was there but disabled/hidden" — so a live failure is diagnosable without
|
|
11
|
+
* another guessing round.
|
|
12
|
+
*/
|
|
13
|
+
import type { Page } from "@browserbasehq/stagehand";
|
|
14
|
+
import type { FrameTarget } from "./frame-target";
|
|
15
|
+
import { type SubmitCandidate, type SubmitCandidateTier } from "./submit-control";
|
|
16
|
+
/** One submit-shaped candidate the ranking cascade saw, annotated with the fields a triager needs to tell it apart from the others. */
|
|
17
|
+
export interface DiagnosticSnapshotCandidate {
|
|
18
|
+
tag: string;
|
|
19
|
+
role: string;
|
|
20
|
+
accessibleName: string;
|
|
21
|
+
tier: SubmitCandidateTier;
|
|
22
|
+
visible: boolean;
|
|
23
|
+
disabled: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** Bounded diagnostic snapshot captured at the moment target resolution gave up. */
|
|
26
|
+
export interface TargetResolutionDiagnosticSnapshot {
|
|
27
|
+
/** Every submit-shaped candidate the ranking cascade saw, highest tier first — the top entry is what the cascade would have clicked, the rest are what it passed over. */
|
|
28
|
+
candidates: DiagnosticSnapshotCandidate[];
|
|
29
|
+
/** Short accessibility-tree excerpt of the region the failed step's instruction most plausibly targeted, or `null` when no candidate was found to anchor the excerpt on. */
|
|
30
|
+
accessibilityExcerpt: string | null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Captures a bounded diagnostic snapshot of the current submit-shaped
|
|
34
|
+
* candidate ranking, called from the two `onStepFailure` sites once every
|
|
35
|
+
* resolution technique has already failed. Reuses
|
|
36
|
+
* {@link buildRankSubmitCandidatesExpr} for the ranking half rather than
|
|
37
|
+
* re-implementing candidate scoring, so the snapshot stays honest about
|
|
38
|
+
* exactly what the cascade's own ranking saw — a divergent, re-implemented
|
|
39
|
+
* ranking here would risk telling a triager the cascade saw a candidate it
|
|
40
|
+
* never actually considered. Never throws: an `evaluate` failure on an
|
|
41
|
+
* already-failing page (navigated away, torn down) degrades to `null`,
|
|
42
|
+
* mirroring the existing `bodyOuterHtml.catch(() => null)` convention at
|
|
43
|
+
* both call sites, since this is diagnostic-only code and must never be
|
|
44
|
+
* the reason a failure path itself fails.
|
|
45
|
+
*
|
|
46
|
+
* `precomputedRanked`, when given, is used in place of a fresh
|
|
47
|
+
* `buildRankSubmitCandidatesExpr` round trip — the deep-submit-locator
|
|
48
|
+
* cascade attempt already ranks the same submit-shaped candidates against
|
|
49
|
+
* the same DOM moments earlier, so re-ranking here would just be a second,
|
|
50
|
+
* redundant `page.evaluate` call reporting the same thing.
|
|
51
|
+
*/
|
|
52
|
+
export declare function captureTargetResolutionDiagnosticSnapshot(target: FrameTarget | undefined, page: Page, precomputedRanked?: SubmitCandidate[] | null): Promise<TargetResolutionDiagnosticSnapshot | null>;
|
|
53
|
+
//# sourceMappingURL=target-resolution-diagnostic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target-resolution-diagnostic.d.ts","sourceRoot":"","sources":["../../src/scraper/target-resolution-diagnostic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAGrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACzB,MAAM,0BAA0B,CAAC;AAoBlC,uIAAuI;AACvI,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,mBAAmB,CAAC;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,oFAAoF;AACpF,MAAM,WAAW,kCAAkC;IACjD,0KAA0K;IAC1K,UAAU,EAAE,2BAA2B,EAAE,CAAC;IAC1C,4KAA4K;IAC5K,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAuED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,yCAAyC,CAC7D,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,EAAE,IAAI,EACV,iBAAiB,CAAC,EAAE,eAAe,EAAE,GAAG,IAAI,GAC3C,OAAO,CAAC,kCAAkC,GAAG,IAAI,CAAC,CAyCpD"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Target-resolution failure diagnostic: when every technique the cascade has
|
|
4
|
+
* (Stagehand act/observe, the deep-locator resolver, the child-iframe
|
|
5
|
+
* fallback) fails to find a step's target, the next person debugging that
|
|
6
|
+
* failure has nothing to go on but a body-HTML dump and a guess. This module
|
|
7
|
+
* captures WHAT the submit-shaped ranking itself saw at the moment of
|
|
8
|
+
* failure — every candidate it ranked, with enough identity (tag, role,
|
|
9
|
+
* accessible name, tier, visibility, disabled state) to tell "the target
|
|
10
|
+
* genuinely wasn't there" apart from "it was there but ranked wrong" or "it
|
|
11
|
+
* was there but disabled/hidden" — so a live failure is diagnosable without
|
|
12
|
+
* another guessing round.
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.captureTargetResolutionDiagnosticSnapshot = captureTargetResolutionDiagnosticSnapshot;
|
|
16
|
+
const logging_1 = require("../lib/logging");
|
|
17
|
+
const submit_control_1 = require("./submit-control");
|
|
18
|
+
const logger = (0, logging_1.getLogger)({ name: "scraper/target-resolution-diagnostic" });
|
|
19
|
+
/** Cap on the number of ranked candidates kept in a snapshot. */
|
|
20
|
+
const MAX_SNAPSHOT_CANDIDATES = 25;
|
|
21
|
+
/**
|
|
22
|
+
* Byte budget for the whole serialized snapshot. Mirrors flow-runner.ts's
|
|
23
|
+
* `FAILURE_DUMP_MAX_BODY_LENGTH` truncation convention for `bodyOuterHtml`
|
|
24
|
+
* (100KB) but scaled down: this snapshot is a small structured summary, not
|
|
25
|
+
* a raw DOM dump, so a much smaller cap already comfortably bounds a
|
|
26
|
+
* pathological page (thousands of candidates or a huge excerpt) without
|
|
27
|
+
* ever approaching the body-dump's own budget.
|
|
28
|
+
*/
|
|
29
|
+
const MAX_SNAPSHOT_JSON_LENGTH = 20_000;
|
|
30
|
+
/** Cap on the accessibility-tree excerpt before it is folded into the snapshot. */
|
|
31
|
+
const MAX_EXCERPT_LENGTH = 2_000;
|
|
32
|
+
/**
|
|
33
|
+
* Re-walks the light DOM plus every open shadow root (same traversal shape
|
|
34
|
+
* as `submit-control.ts`'s private `DEEP_ELEMENTS_EXPR` — duplicated rather
|
|
35
|
+
* than imported, since both are browser-context expression strings composed
|
|
36
|
+
* by string interpolation, matching that module's own stated convention for
|
|
37
|
+
* why `IS_VISIBLE_EXPR`/`DEEP_ELEMENTS_EXPR` are duplicated instead of
|
|
38
|
+
* shared) to read the role/visible/disabled/excerpt fields the ranking
|
|
39
|
+
* expression itself doesn't return, and to build a short accessible-name
|
|
40
|
+
* excerpt around the top-ranked candidate. Runs as a single `page.evaluate`
|
|
41
|
+
* round trip so the DOM observed here always matches the one
|
|
42
|
+
* `buildRankSubmitCandidatesExpr` just ranked.
|
|
43
|
+
*/
|
|
44
|
+
function buildCandidateDetailExpr(root, deepIndices) {
|
|
45
|
+
return `(() => {
|
|
46
|
+
const deepElements = ((rootEl) => {
|
|
47
|
+
const out = [];
|
|
48
|
+
const walk = (node) => {
|
|
49
|
+
const kids = node.querySelectorAll ? Array.from(node.querySelectorAll("*")) : [];
|
|
50
|
+
for (const el of kids) {
|
|
51
|
+
out.push(el);
|
|
52
|
+
if (el.shadowRoot) walk(el.shadowRoot);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
walk(rootEl);
|
|
56
|
+
return out;
|
|
57
|
+
})(${root});
|
|
58
|
+
const isVisible = (el) => {
|
|
59
|
+
const rect = el.getBoundingClientRect();
|
|
60
|
+
if (rect.width === 0 && rect.height === 0) return false;
|
|
61
|
+
const style = getComputedStyle(el);
|
|
62
|
+
return style.display !== "none" && style.visibility !== "hidden";
|
|
63
|
+
};
|
|
64
|
+
const isDisabled = (el) => {
|
|
65
|
+
for (let depth = 0, node = el; depth < 8 && node; depth++) {
|
|
66
|
+
if (node.disabled === true) return true;
|
|
67
|
+
if (node.getAttribute && node.getAttribute("aria-disabled") === "true") return true;
|
|
68
|
+
node = node.parentElement;
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
};
|
|
72
|
+
const roleOf = (el) => {
|
|
73
|
+
const explicit = el.getAttribute("role");
|
|
74
|
+
if (explicit) return explicit;
|
|
75
|
+
const tag = (el.tagName || "").toLowerCase();
|
|
76
|
+
if (tag === "button") return "button";
|
|
77
|
+
if (tag === "input") return "input";
|
|
78
|
+
if (tag === "a") return "link";
|
|
79
|
+
return "";
|
|
80
|
+
};
|
|
81
|
+
const indices = ${JSON.stringify(deepIndices)};
|
|
82
|
+
const details = indices.map((i) => {
|
|
83
|
+
const el = deepElements[i];
|
|
84
|
+
if (!el) return { role: "", visible: false, disabled: true };
|
|
85
|
+
return { role: roleOf(el), visible: isVisible(el), disabled: isDisabled(el) };
|
|
86
|
+
});
|
|
87
|
+
const topEl = indices.length > 0 ? deepElements[indices[0]] : null;
|
|
88
|
+
let excerpt = null;
|
|
89
|
+
if (topEl) {
|
|
90
|
+
const container =
|
|
91
|
+
topEl.closest("form, section, [role=dialog], fieldset") || topEl.parentElement || topEl;
|
|
92
|
+
excerpt = (container.innerText || container.textContent || "")
|
|
93
|
+
.replace(/\\s+/g, " ")
|
|
94
|
+
.trim()
|
|
95
|
+
.slice(0, ${MAX_EXCERPT_LENGTH});
|
|
96
|
+
}
|
|
97
|
+
return { details, excerpt };
|
|
98
|
+
})()`;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Captures a bounded diagnostic snapshot of the current submit-shaped
|
|
102
|
+
* candidate ranking, called from the two `onStepFailure` sites once every
|
|
103
|
+
* resolution technique has already failed. Reuses
|
|
104
|
+
* {@link buildRankSubmitCandidatesExpr} for the ranking half rather than
|
|
105
|
+
* re-implementing candidate scoring, so the snapshot stays honest about
|
|
106
|
+
* exactly what the cascade's own ranking saw — a divergent, re-implemented
|
|
107
|
+
* ranking here would risk telling a triager the cascade saw a candidate it
|
|
108
|
+
* never actually considered. Never throws: an `evaluate` failure on an
|
|
109
|
+
* already-failing page (navigated away, torn down) degrades to `null`,
|
|
110
|
+
* mirroring the existing `bodyOuterHtml.catch(() => null)` convention at
|
|
111
|
+
* both call sites, since this is diagnostic-only code and must never be
|
|
112
|
+
* the reason a failure path itself fails.
|
|
113
|
+
*
|
|
114
|
+
* `precomputedRanked`, when given, is used in place of a fresh
|
|
115
|
+
* `buildRankSubmitCandidatesExpr` round trip — the deep-submit-locator
|
|
116
|
+
* cascade attempt already ranks the same submit-shaped candidates against
|
|
117
|
+
* the same DOM moments earlier, so re-ranking here would just be a second,
|
|
118
|
+
* redundant `page.evaluate` call reporting the same thing.
|
|
119
|
+
*/
|
|
120
|
+
async function captureTargetResolutionDiagnosticSnapshot(target, page, precomputedRanked) {
|
|
121
|
+
try {
|
|
122
|
+
const evaluator = target ?? page;
|
|
123
|
+
const root = "document";
|
|
124
|
+
const ranked = precomputedRanked ??
|
|
125
|
+
(await evaluator.evaluate((0, submit_control_1.buildRankSubmitCandidatesExpr)(root)));
|
|
126
|
+
const bounded = ranked.slice(0, MAX_SNAPSHOT_CANDIDATES);
|
|
127
|
+
const detail = await evaluator.evaluate(buildCandidateDetailExpr(root, bounded.map((c) => c.deepIndex)));
|
|
128
|
+
const candidates = bounded.map((c, i) => ({
|
|
129
|
+
tag: c.tag,
|
|
130
|
+
accessibleName: c.accessibleName,
|
|
131
|
+
tier: c.tier,
|
|
132
|
+
role: detail.details[i]?.role ?? "",
|
|
133
|
+
visible: detail.details[i]?.visible ?? false,
|
|
134
|
+
disabled: detail.details[i]?.disabled ?? true,
|
|
135
|
+
}));
|
|
136
|
+
const snapshot = {
|
|
137
|
+
candidates,
|
|
138
|
+
accessibilityExcerpt: detail.excerpt || null,
|
|
139
|
+
};
|
|
140
|
+
const serialized = JSON.stringify(snapshot);
|
|
141
|
+
if (serialized.length <= MAX_SNAPSHOT_JSON_LENGTH)
|
|
142
|
+
return snapshot;
|
|
143
|
+
return {
|
|
144
|
+
candidates: candidates.slice(0, Math.max(1, Math.floor(candidates.length / 2))),
|
|
145
|
+
accessibilityExcerpt: snapshot.accessibilityExcerpt,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
logger.warn(`target-resolution diagnostic snapshot failed to capture: ${String(error)}`);
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=target-resolution-diagnostic.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"target-resolution-diagnostic.js","sourceRoot":"","sources":["../../src/scraper/target-resolution-diagnostic.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAIH,2CAA0C;AAE1C,6DAIkC;AAElC,MAAM,MAAM,GAAG,IAAA,mBAAS,EAAC,EAAE,IAAI,EAAE,sCAAsC,EAAE,CAAC,CAAC;AAE3E,iEAAiE;AACjE,MAAM,uBAAuB,GAAG,EAAE,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAExC,mFAAmF;AACnF,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAoBjC;;;;;;;;;;;GAWG;AACH,SAAS,wBAAwB,CAAC,IAAY,EAAE,WAA8B;IAC5E,OAAO;;;;;;;;;;;;SAYA,IAAI;;;;;;;;;;;;;;;;;;;;;;;;sBAwBS,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;;;;;;;;;;;;;;oBAc7B,kBAAkB;;;OAG/B,CAAC;AACR,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACI,KAAK,oDACV,MAA+B,EAC/B,IAAU,EACV,iBAA4C;IAE5C,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,IAAI,IAAI,CAAC;QACjC,MAAM,IAAI,GAAG,UAAU,CAAC;QACxB,MAAM,MAAM,GACV,iBAAiB;YACjB,CAAC,MAAM,SAAS,CAAC,QAAQ,CAEvB,IAAA,8CAA6B,EAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,uBAAuB,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,QAAQ,CAIrC,wBAAwB,CACtB,IAAI,EACJ,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAChC,CACF,CAAC;QACF,MAAM,UAAU,GAAkC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YACvE,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,cAAc,EAAE,CAAC,CAAC,cAAc;YAChC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE;YACnC,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,KAAK;YAC5C,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,IAAI;SAC9C,CAAC,CAAC,CAAC;QACJ,MAAM,QAAQ,GAAuC;YACnD,UAAU;YACV,oBAAoB,EAAE,MAAM,CAAC,OAAO,IAAI,IAAI;SAC7C,CAAC;QACF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,UAAU,CAAC,MAAM,IAAI,wBAAwB;YAAE,OAAO,QAAQ,CAAC;QACnE,OAAO;YACL,UAAU,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YAC/E,oBAAoB,EAAE,QAAQ,CAAC,oBAAoB;SACpD,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,4DAA4D,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzF,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|