@enricai/barnacle 1.6.7 → 1.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/plugins/config-plugin.d.ts +1 -0
  2. package/dist/plugins/config-plugin.d.ts.map +1 -1
  3. package/dist/plugins/config-plugin.js +2 -0
  4. package/dist/plugins/config-plugin.js.map +1 -1
  5. package/dist/scraper/behavioral-signals.d.ts +10 -3
  6. package/dist/scraper/behavioral-signals.d.ts.map +1 -1
  7. package/dist/scraper/behavioral-signals.js +17 -6
  8. package/dist/scraper/behavioral-signals.js.map +1 -1
  9. package/dist/scraper/deep-query.d.ts +8 -0
  10. package/dist/scraper/deep-query.d.ts.map +1 -1
  11. package/dist/scraper/deep-query.js +9 -1
  12. package/dist/scraper/deep-query.js.map +1 -1
  13. package/dist/scraper/flow-runner.d.ts +156 -24
  14. package/dist/scraper/flow-runner.d.ts.map +1 -1
  15. package/dist/scraper/flow-runner.js +246 -134
  16. package/dist/scraper/flow-runner.js.map +1 -1
  17. package/dist/scraper/frame-target.d.ts +98 -0
  18. package/dist/scraper/frame-target.d.ts.map +1 -0
  19. package/dist/scraper/frame-target.js +212 -0
  20. package/dist/scraper/frame-target.js.map +1 -0
  21. package/dist/scraper/stagehand-guard.d.ts +31 -3
  22. package/dist/scraper/stagehand-guard.d.ts.map +1 -1
  23. package/dist/scraper/stagehand-guard.js +53 -7
  24. package/dist/scraper/stagehand-guard.js.map +1 -1
  25. package/dist/scraper/submit-control.d.ts +15 -2
  26. package/dist/scraper/submit-control.d.ts.map +1 -1
  27. package/dist/scraper/submit-control.js +17 -4
  28. package/dist/scraper/submit-control.js.map +1 -1
  29. package/dist/scripts/recon-browser.d.ts +95 -1
  30. package/dist/scripts/recon-browser.d.ts.map +1 -1
  31. package/dist/scripts/recon-browser.js +54 -10
  32. package/dist/scripts/recon-browser.js.map +1 -1
  33. package/dist/scripts/recon-generate.d.ts +6 -0
  34. package/dist/scripts/recon-generate.d.ts.map +1 -1
  35. package/dist/scripts/recon-generate.js +9 -7
  36. package/dist/scripts/recon-generate.js.map +1 -1
  37. package/package.json +1 -1
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Cross-origin frame resolver: the single seam that lets every downstream
3
+ * helper (flow-runner primitives, guarded Stagehand calls) act on either the
4
+ * main frame or a resolved cross-origin OOPIF without knowing which. Some
5
+ * ATS integrations (e.g. UCHealth's Talemetry wizard) embed their entire
6
+ * application form inside a cross-origin `<iframe>` rather than navigating
7
+ * the top window to it, and `document`-rooted helpers (`page.evaluate`,
8
+ * `page.locator`) cannot reach across that boundary — `contentDocument` on a
9
+ * cross-origin iframe element is `null` from page script's perspective.
10
+ * `resolveFrameTarget` finds the child `Frame` Stagehand's CDP layer already
11
+ * attached to and wraps it in a uniform `FrameTarget` surface.
12
+ */
13
+ import type { Page } from "@browserbasehq/stagehand";
14
+ /** The frame handle type `Page.frames()` returns, without a deep import into Stagehand's understudy internals. */
15
+ type StagehandFrame = ReturnType<Page["frames"]>[number];
16
+ /**
17
+ * Uniform evaluate/locator/url/title surface bound to either the main frame
18
+ * (`frame: null`) or a resolved cross-origin child frame. `frameSelector` is
19
+ * the CSS selector of the scoped frame (or `null` for main), carried so
20
+ * callers can pass it straight through to `ObserveOptions.selector` /
21
+ * `ExtractOptions.selector` and scope Stagehand's own observe/extract calls
22
+ * to the same frame this target evaluates and locates against.
23
+ */
24
+ export interface FrameTarget {
25
+ /** The resolved child frame, or `null` when this target is bound to the main frame. */
26
+ readonly frame: StagehandFrame | null;
27
+ /** CSS selector for the Stagehand scope hint (`ObserveOptions.selector` / `ExtractOptions.selector`), or `null` for the main frame. */
28
+ readonly frameSelector: string | null;
29
+ /** Evaluate a function or expression against the resolved frame (or the main frame when unresolved). */
30
+ evaluate<R = unknown, Arg = unknown>(pageFunctionOrExpression: string | ((arg: Arg) => R | Promise<R>), arg?: Arg): Promise<R>;
31
+ /** Build a Locator scoped to the resolved frame (or the main frame when unresolved). */
32
+ locator(selector: string): ReturnType<Page["locator"]>;
33
+ /** Current URL of the resolved frame (or the main frame when unresolved). */
34
+ url(): Promise<string>;
35
+ /** Current document title. Cross-origin child frames have no accessible `document.title` distinct from the top document via CDP `Page.title`, so this always reads the top document's title. */
36
+ title(): Promise<string>;
37
+ }
38
+ /**
39
+ * Builds the main-frame `FrameTarget`: every method delegates straight to
40
+ * `Page`, matching today's behavior for every site whose ATS form never
41
+ * leaves the top window. Exported so call sites that have not yet resolved
42
+ * a `FrameTarget` from `deps.frameSelector` can still pass a target-shaped
43
+ * value to helpers that now require one.
44
+ */
45
+ export declare function mainFrameTarget(page: Page): FrameTarget;
46
+ /**
47
+ * Resolves the `FrameTarget` for `frameSelector` against `page`, polling for
48
+ * up to `FRAME_READY_TIMEOUT_MS` (at `FRAME_READY_POLL_MS` intervals) before
49
+ * falling back to the main-frame target rather than throwing:
50
+ *
51
+ * 1. `frameSelector` is `null`/`undefined` → main-frame target (today's
52
+ * behavior, unchanged) — zero polling, zero delay.
53
+ * 2. Each poll: no element in the main document matches `frameSelector`, or
54
+ * it isn't an `<iframe>`, or its `src` can't be read and more than one
55
+ * `page.frames()` candidate exists (identity match is ambiguous), or no
56
+ * `page.frames()` entry has a matching origin yet → try again after
57
+ * `FRAME_READY_POLL_MS`.
58
+ * 3. A poll finds a matching frame → a child-frame target bound to it,
59
+ * however many polls it took (an iframe created mid-flow by an earlier
60
+ * step, e.g. after a click reveals it, resolves as soon as Stagehand's
61
+ * CDP layer attaches to it instead of only when present at the first
62
+ * poll).
63
+ * 4. Still unresolved once the deadline passes → main-frame target, with a
64
+ * `warn` naming the selector so a silent revert-to-main-frame is
65
+ * diagnosable from the log instead of invisible.
66
+ *
67
+ * `opts` overrides the poll timing for tests; production call sites rely on
68
+ * the `FRAME_READY_TIMEOUT_MS`/`FRAME_READY_POLL_MS` defaults.
69
+ */
70
+ export declare function resolveFrameTarget(page: Page, frameSelector?: string | null, opts?: {
71
+ timeoutMs?: number;
72
+ pollMs?: number;
73
+ }): Promise<FrameTarget>;
74
+ /**
75
+ * Composes a Stagehand hop-notation scope string from a frame selector and an
76
+ * inner selector, for callers building `ObserveOptions.selector` /
77
+ * `ExtractOptions.selector` values — kept separate from `FrameTarget` itself
78
+ * so `resolveFrameTarget` keeps receiving only the bare iframe-id hop (the
79
+ * contract `frame-resolve.test.ts` pins) rather than a pre-composed string.
80
+ */
81
+ export declare function buildHopSelector(frameSelector: string | null | undefined, innerSelector: string): string;
82
+ /** Shared delay helper — `FrameTarget` has no `waitForTimeout` since it isn't frame-scoped. */
83
+ export declare function sleep(ms: number): Promise<void>;
84
+ /**
85
+ * Blocks until a resolved child frame has a live document (`document.readyState`
86
+ * is `"interactive"` or `"complete"`), so callers do not observe/act against a
87
+ * frame that CDP has attached to but that has not yet navigated past `about:blank`
88
+ * — the state right after `Target.setAutoAttach` fires and before the OOPIF's own
89
+ * navigation lands. Best-effort like `waitForSpaReady`: never throws, just resolves
90
+ * once ready or once `timeoutMs` elapses, so a frame that never becomes ready
91
+ * degrades to "proceed anyway" rather than hanging the flow.
92
+ */
93
+ export declare function waitForChildFrameReady(target: FrameTarget, opts?: {
94
+ timeoutMs?: number;
95
+ pollMs?: number;
96
+ }): Promise<void>;
97
+ export {};
98
+ //# sourceMappingURL=frame-target.d.ts.map
@@ -0,0 +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;AAMrD,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,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;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,WAAW,CASvD;AA0FD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,EAC7B,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,WAAW,CAAC,CAoBtB;AAID;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACxC,aAAa,EAAE,MAAM,GACpB,MAAM,CAOR;AAMD,+FAA+F;AAC/F,wBAAgB,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GACjD,OAAO,CAAC,IAAI,CAAC,CAqBf"}
@@ -0,0 +1,212 @@
1
+ "use strict";
2
+ /**
3
+ * Cross-origin frame resolver: the single seam that lets every downstream
4
+ * helper (flow-runner primitives, guarded Stagehand calls) act on either the
5
+ * main frame or a resolved cross-origin OOPIF without knowing which. Some
6
+ * ATS integrations (e.g. UCHealth's Talemetry wizard) embed their entire
7
+ * application form inside a cross-origin `<iframe>` rather than navigating
8
+ * the top window to it, and `document`-rooted helpers (`page.evaluate`,
9
+ * `page.locator`) cannot reach across that boundary — `contentDocument` on a
10
+ * cross-origin iframe element is `null` from page script's perspective.
11
+ * `resolveFrameTarget` finds the child `Frame` Stagehand's CDP layer already
12
+ * attached to and wraps it in a uniform `FrameTarget` surface.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.mainFrameTarget = mainFrameTarget;
16
+ exports.resolveFrameTarget = resolveFrameTarget;
17
+ exports.buildHopSelector = buildHopSelector;
18
+ exports.sleep = sleep;
19
+ exports.waitForChildFrameReady = waitForChildFrameReady;
20
+ const logging_1 = require("../lib/logging");
21
+ const logger = (0, logging_1.getLogger)({ name: "scraper/frame-target" });
22
+ /**
23
+ * Builds the main-frame `FrameTarget`: every method delegates straight to
24
+ * `Page`, matching today's behavior for every site whose ATS form never
25
+ * leaves the top window. Exported so call sites that have not yet resolved
26
+ * a `FrameTarget` from `deps.frameSelector` can still pass a target-shaped
27
+ * value to helpers that now require one.
28
+ */
29
+ function mainFrameTarget(page) {
30
+ return {
31
+ frame: null,
32
+ frameSelector: null,
33
+ evaluate: (pageFunctionOrExpression, arg) => page.evaluate(pageFunctionOrExpression, arg),
34
+ locator: (selector) => page.locator(selector),
35
+ url: () => Promise.resolve(page.url()),
36
+ title: () => page.title(),
37
+ };
38
+ }
39
+ /**
40
+ * Builds a child-frame `FrameTarget`: `evaluate`/`locator` delegate to the
41
+ * resolved `Frame` (reaching across the cross-origin boundary via its own
42
+ * CDP session), while `url`/`title` fall back to the frame's own
43
+ * `location.href` and the top document's title respectively — `Frame` has
44
+ * no `title()` of its own.
45
+ */
46
+ function childFrameTarget(page, frame, frameSelector) {
47
+ return {
48
+ frame,
49
+ frameSelector,
50
+ evaluate: (pageFunctionOrExpression, arg) => frame.evaluate(pageFunctionOrExpression, arg),
51
+ locator: (selector) => frame.locator(selector),
52
+ url: () => frame.evaluate("location.href"),
53
+ title: () => page.title(),
54
+ };
55
+ }
56
+ /**
57
+ * Reads the origin (scheme + host) off a URL string, or `null` if it isn't
58
+ * parseable — used to match a candidate `page.frames()` entry against the
59
+ * `<iframe>` element's `src` attribute without requiring an exact URL match
60
+ * (the iframe `src` and the frame's live `location.href` commonly differ by
61
+ * path/query after the child navigates, e.g. an application UUID appended
62
+ * post-load).
63
+ */
64
+ function originOf(url) {
65
+ try {
66
+ return new URL(url).origin;
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ /**
73
+ * Attempts one resolution pass: reads the `<iframe>` element's `src` (not
74
+ * `contentDocument`, which stays readable across the cross-origin boundary —
75
+ * only same-origin script access to the child's document is blocked), then
76
+ * looks for a `page.frames()` entry whose origin matches it. Returns `null`
77
+ * rather than a target so the caller can distinguish "not yet attached, keep
78
+ * polling" from a resolved target.
79
+ *
80
+ * The `src` attribute read can lose a same-tick race against the widget
81
+ * script that constructs the `<iframe>`: some ATS integrations (e.g.
82
+ * UCHealth's Talemetry wizard) assign `src` as a JS property immediately
83
+ * before `appendChild`, so a poll can observe the element already in the
84
+ * DOM with `src` still empty or not yet reflected to the attribute. Giving
85
+ * up in that case would depend on same-tick attribute reflection that isn't
86
+ * guaranteed. Instead, when the element is confirmed to be the matching
87
+ * `<iframe>` but its `src` can't be read, fall back to matching by element
88
+ * identity: if `page.frames()` has resolved exactly one candidate frame
89
+ * beyond the main frame, that frame must be the one CDP attached to for
90
+ * this iframe, so bind to it directly rather than degrading to the main
91
+ * frame.
92
+ */
93
+ async function tryResolveChildFrame(page, frameSelector) {
94
+ const iframeSrcExpr = `(() => {
95
+ const el = document.querySelector(${JSON.stringify(frameSelector)});
96
+ if (!el || el.tagName !== "IFRAME") return { matched: false, src: null };
97
+ return { matched: true, src: el.getAttribute("src") };
98
+ })()`;
99
+ const { matched, src: iframeSrc } = await page.evaluate(iframeSrcExpr);
100
+ if (!matched)
101
+ return null;
102
+ const candidates = page.frames();
103
+ const targetOrigin = iframeSrc ? originOf(iframeSrc) : null;
104
+ if (!targetOrigin) {
105
+ const [onlyCandidate] = candidates;
106
+ return candidates.length === 1 && onlyCandidate
107
+ ? childFrameTarget(page, onlyCandidate, frameSelector)
108
+ : null;
109
+ }
110
+ for (const candidate of candidates) {
111
+ const candidateUrl = await candidate.evaluate("location.href").catch(() => null);
112
+ if (candidateUrl && originOf(candidateUrl) === targetOrigin) {
113
+ return childFrameTarget(page, candidate, frameSelector);
114
+ }
115
+ }
116
+ return null;
117
+ }
118
+ /**
119
+ * Resolves the `FrameTarget` for `frameSelector` against `page`, polling for
120
+ * up to `FRAME_READY_TIMEOUT_MS` (at `FRAME_READY_POLL_MS` intervals) before
121
+ * falling back to the main-frame target rather than throwing:
122
+ *
123
+ * 1. `frameSelector` is `null`/`undefined` → main-frame target (today's
124
+ * behavior, unchanged) — zero polling, zero delay.
125
+ * 2. Each poll: no element in the main document matches `frameSelector`, or
126
+ * it isn't an `<iframe>`, or its `src` can't be read and more than one
127
+ * `page.frames()` candidate exists (identity match is ambiguous), or no
128
+ * `page.frames()` entry has a matching origin yet → try again after
129
+ * `FRAME_READY_POLL_MS`.
130
+ * 3. A poll finds a matching frame → a child-frame target bound to it,
131
+ * however many polls it took (an iframe created mid-flow by an earlier
132
+ * step, e.g. after a click reveals it, resolves as soon as Stagehand's
133
+ * CDP layer attaches to it instead of only when present at the first
134
+ * poll).
135
+ * 4. Still unresolved once the deadline passes → main-frame target, with a
136
+ * `warn` naming the selector so a silent revert-to-main-frame is
137
+ * diagnosable from the log instead of invisible.
138
+ *
139
+ * `opts` overrides the poll timing for tests; production call sites rely on
140
+ * the `FRAME_READY_TIMEOUT_MS`/`FRAME_READY_POLL_MS` defaults.
141
+ */
142
+ async function resolveFrameTarget(page, frameSelector, opts = {}) {
143
+ if (!frameSelector)
144
+ return mainFrameTarget(page);
145
+ const resolved = await tryResolveChildFrame(page, frameSelector);
146
+ if (resolved)
147
+ return resolved;
148
+ const timeoutMs = opts.timeoutMs ?? FRAME_READY_TIMEOUT_MS;
149
+ const pollMs = opts.pollMs ?? FRAME_READY_POLL_MS;
150
+ const deadline = Date.now() + timeoutMs;
151
+ while (Date.now() < deadline) {
152
+ await sleep(pollMs);
153
+ const polled = await tryResolveChildFrame(page, frameSelector);
154
+ if (polled)
155
+ return polled;
156
+ }
157
+ logger.warn(`frame ${frameSelector} did not attach within ${timeoutMs}ms — falling back to main frame`);
158
+ return mainFrameTarget(page);
159
+ }
160
+ const HOP_SEPARATOR = " >> ";
161
+ /**
162
+ * Composes a Stagehand hop-notation scope string from a frame selector and an
163
+ * inner selector, for callers building `ObserveOptions.selector` /
164
+ * `ExtractOptions.selector` values — kept separate from `FrameTarget` itself
165
+ * so `resolveFrameTarget` keeps receiving only the bare iframe-id hop (the
166
+ * contract `frame-resolve.test.ts` pins) rather than a pre-composed string.
167
+ */
168
+ function buildHopSelector(frameSelector, innerSelector) {
169
+ if (!frameSelector)
170
+ return innerSelector;
171
+ const trimmedFrameSelector = frameSelector.trimEnd();
172
+ if (trimmedFrameSelector.endsWith(">>")) {
173
+ return `${trimmedFrameSelector} ${innerSelector.trimStart()}`;
174
+ }
175
+ return `${trimmedFrameSelector}${HOP_SEPARATOR}${innerSelector.trimStart()}`;
176
+ }
177
+ /** Readiness-wait defaults — cheap poll, short timeout: an attached-but-not-yet-navigated child frame should settle in well under a second. */
178
+ const FRAME_READY_TIMEOUT_MS = 5_000;
179
+ const FRAME_READY_POLL_MS = 100;
180
+ /** Shared delay helper — `FrameTarget` has no `waitForTimeout` since it isn't frame-scoped. */
181
+ function sleep(ms) {
182
+ return new Promise((resolve) => setTimeout(resolve, ms));
183
+ }
184
+ /**
185
+ * Blocks until a resolved child frame has a live document (`document.readyState`
186
+ * is `"interactive"` or `"complete"`), so callers do not observe/act against a
187
+ * frame that CDP has attached to but that has not yet navigated past `about:blank`
188
+ * — the state right after `Target.setAutoAttach` fires and before the OOPIF's own
189
+ * navigation lands. Best-effort like `waitForSpaReady`: never throws, just resolves
190
+ * once ready or once `timeoutMs` elapses, so a frame that never becomes ready
191
+ * degrades to "proceed anyway" rather than hanging the flow.
192
+ */
193
+ async function waitForChildFrameReady(target, opts = {}) {
194
+ if (!target.frame)
195
+ return;
196
+ const timeoutMs = opts.timeoutMs ?? FRAME_READY_TIMEOUT_MS;
197
+ const pollMs = opts.pollMs ?? FRAME_READY_POLL_MS;
198
+ const isReady = async () => {
199
+ const readyState = await target.evaluate("document.readyState").catch(() => null);
200
+ return readyState === "interactive" || readyState === "complete";
201
+ };
202
+ if (await isReady())
203
+ return;
204
+ const deadline = Date.now() + timeoutMs;
205
+ while (Date.now() < deadline) {
206
+ await sleep(pollMs);
207
+ if (await isReady())
208
+ return;
209
+ }
210
+ logger.warn(`child frame ${target.frameSelector ?? "(unresolved)"} still not ready after ${timeoutMs}ms — proceeding anyway`);
211
+ }
212
+ //# sourceMappingURL=frame-target.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame-target.js","sourceRoot":"","sources":["../../src/scraper/frame-target.ts"],"names":[],"mappings":"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"}
@@ -39,6 +39,7 @@
39
39
  import type { Action, ActOptions, ActResult, ExtractOptions, ObserveOptions, Stagehand } from "@browserbasehq/stagehand";
40
40
  import { z } from "zod/v4";
41
41
  import { type LlmCallInput } from "../lib/telemetry/call-capture";
42
+ import { type FrameTarget } from "../scraper/frame-target";
42
43
  /**
43
44
  * Injectable capture function — matches `captureLlmCall`'s signature. Same
44
45
  * shape as `JudgeCaptureFn` in `@/lib/llm/judge`. Lets each guard call route
@@ -109,20 +110,47 @@ export declare class StagehandSchemaError extends Error {
109
110
  * `Action` (from a prior `observe`). On the happy path, returns Stagehand's
110
111
  * `ActResult` verbatim. On envelope drift, throws `StagehandSchemaError`
111
112
  * and logs `failureKind: "schema-validation-failed"`.
113
+ *
114
+ * Accepts the same trailing `frameTarget` param as `guardedObserve`/
115
+ * `guardedExtract` for signature symmetry, but does not forward it into
116
+ * `ActOptions` — `ActOptions` has no `selector` field, and its `page`
117
+ * override only accepts a full Playwright/Puppeteer/Patchright/understudy
118
+ * `Page`, not the `Frame` handle `FrameTarget.frame` exposes (the
119
+ * understudy `Page` constructor is private, so there is no way to
120
+ * synthesize a frame-scoped `Page`). Scope `act` at the call site instead:
121
+ * pair a frame-scoped `guardedObserve` (whose returned `Action.selector`
122
+ * already targets the resolved frame's DOM) with `guardedAct` called on
123
+ * that `Action` — the `observe(...)[0] -> act(target)` pattern already used
124
+ * throughout `flow-runner.ts`.
112
125
  */
113
- export declare function guardedAct(stagehand: Stagehand, input: string | Action, options?: ActOptions, captureFn?: StagehandCaptureFn): Promise<ActResult>;
126
+ export declare function guardedAct(stagehand: Stagehand, input: string | Action, options?: ActOptions, captureFn?: StagehandCaptureFn, _frameTarget?: FrameTarget): Promise<ActResult>;
114
127
  /**
115
128
  * Schema-guarded wrapper around Stagehand's `observe`. Mirrors the
116
129
  * Stagehand overloads: no args, options-only, instruction-only,
117
130
  * instruction + options. On envelope drift (the `Action[]` shape changes),
118
131
  * throws `StagehandSchemaError`.
132
+ *
133
+ * When `frameTarget` resolves to a cross-origin child frame, its
134
+ * `frameSelector` is merged into `ObserveOptions.selector` so Stagehand's
135
+ * snapshot/candidate search is scoped to that frame's DOM instead of only
136
+ * the top frame. A caller-supplied `options.selector` wins over
137
+ * `frameTarget.frameSelector` — the caller made an explicit choice. The
138
+ * main-frame target (`frameTarget` omitted, or its `frameSelector` is
139
+ * `null`) leaves `options` untouched, so every existing call site is
140
+ * byte-identical to today.
119
141
  */
120
- export declare function guardedObserve(stagehand: Stagehand, instruction?: string, options?: ObserveOptions, captureFn?: StagehandCaptureFn): Promise<Action[]>;
142
+ export declare function guardedObserve(stagehand: Stagehand, instruction?: string, options?: ObserveOptions, captureFn?: StagehandCaptureFn, frameTarget?: FrameTarget): Promise<Action[]>;
121
143
  /**
122
144
  * Schema-guarded wrapper around Stagehand's `extract` 3-arg overload. The
123
145
  * caller's Zod schema is what Stagehand asks the LLM to satisfy AND what we
124
146
  * `safeParse` against caller-side. Refuse the 1-arg / 2-arg defaults; every
125
147
  * extract call in the codebase must enforce a schema.
148
+ *
149
+ * When `frameTarget` resolves to a cross-origin child frame, its
150
+ * `frameSelector` is merged into `ExtractOptions.selector` so Stagehand
151
+ * extracts from that frame's DOM instead of only the top frame. A
152
+ * caller-supplied `options.selector` wins over `frameTarget.frameSelector`.
153
+ * The main-frame target leaves `options` untouched.
126
154
  */
127
- export declare function guardedExtract<T extends z.ZodTypeAny>(stagehand: Stagehand, instruction: string, schema: T, options?: ExtractOptions, captureFn?: StagehandCaptureFn): Promise<z.infer<T>>;
155
+ export declare function guardedExtract<T extends z.ZodTypeAny>(stagehand: Stagehand, instruction: string, schema: T, options?: ExtractOptions, captureFn?: StagehandCaptureFn, frameTarget?: FrameTarget): Promise<z.infer<T>>;
128
156
  //# sourceMappingURL=stagehand-guard.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"stagehand-guard.d.ts","sourceRoot":"","sources":["../../src/scraper/stagehand-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAIH,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,SAAS,EACT,cAAc,EACd,cAAc,EACd,SAAS,EACV,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,8BAA8B,CAAC;AAOtC;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAExE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa;;;;;iBAKxB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;iBAM5B,CAAC;AAEH;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,EAAG,0BAA0B,CAAU;IACpD,QAAQ,CAAC,SAAS,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAE9B,YACE,SAAS,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,EACxC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EACpB,WAAW,EAAE,OAAO,EAOrB;CACF;AAoBD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,CAAC,EAAE,UAAU,EACpB,SAAS,CAAC,EAAE,kBAAkB,GAC7B,OAAO,CAAC,SAAS,CAAC,CAqEpB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,SAAS,EACpB,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,cAAc,EACxB,SAAS,CAAC,EAAE,kBAAkB,GAC7B,OAAO,CAAC,MAAM,EAAE,CAAC,CAkEnB;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EACzD,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,cAAc,EACxB,SAAS,CAAC,EAAE,kBAAkB,GAC7B,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAsErB"}
1
+ {"version":3,"file":"stagehand-guard.d.ts","sourceRoot":"","sources":["../../src/scraper/stagehand-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAIH,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,SAAS,EACT,cAAc,EACd,cAAc,EACd,SAAS,EACV,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,8BAA8B,CAAC;AAMtC,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE5E;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAExE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,aAAa;;;;;iBAKxB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;iBAM5B,CAAC;AAEH;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,EAAG,0BAA0B,CAAU;IACpD,QAAQ,CAAC,SAAS,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,CAAC;IAClD,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAE9B,YACE,SAAS,EAAE,KAAK,GAAG,SAAS,GAAG,SAAS,EACxC,QAAQ,EAAE,CAAC,CAAC,QAAQ,EACpB,WAAW,EAAE,OAAO,EAOrB;CACF;AAwCD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,UAAU,CAC9B,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,CAAC,EAAE,UAAU,EACpB,SAAS,CAAC,EAAE,kBAAkB,EAC9B,YAAY,CAAC,EAAE,WAAW,GACzB,OAAO,CAAC,SAAS,CAAC,CAqEpB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,SAAS,EACpB,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,CAAC,EAAE,cAAc,EACxB,SAAS,CAAC,EAAE,kBAAkB,EAC9B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,MAAM,EAAE,CAAC,CAmEnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,cAAc,CAAC,CAAC,SAAS,CAAC,CAAC,UAAU,EACzD,SAAS,EAAE,SAAS,EACpB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,CAAC,EACT,OAAO,CAAC,EAAE,cAAc,EACxB,SAAS,CAAC,EAAE,kBAAkB,EAC9B,WAAW,CAAC,EAAE,WAAW,GACxB,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAsErB"}
@@ -46,6 +46,7 @@ const node_crypto_1 = require("node:crypto");
46
46
  const v4_1 = require("zod/v4");
47
47
  const call_capture_1 = require("../lib/telemetry/call-capture");
48
48
  const call_types_1 = require("../lib/telemetry/call-types");
49
+ const frame_target_1 = require("../scraper/frame-target");
49
50
  /**
50
51
  * Zod mirror of Stagehand's public `Action` shape (from
51
52
  * `@browserbasehq/stagehand/.../public/methods.d.ts`):
@@ -118,14 +119,43 @@ function safeStringify(value, cap = 4000) {
118
119
  function actInstructionOf(input) {
119
120
  return typeof input === "string" ? input : input.description;
120
121
  }
122
+ /**
123
+ * Merges `frameTarget.frameSelector` into `options.selector` for
124
+ * `ObserveOptions`/`ExtractOptions`, composed as Stagehand `">>"` hop
125
+ * notation (`buildHopSelector`) rather than the bare iframe selector —
126
+ * `resolveCssFocusFrameAndTail` only crosses into the child frame's own CDP
127
+ * session when the selector has a hop segment before `>>`; a bare selector
128
+ * performs zero hops and scopes to the (empty) `<iframe>` element itself.
129
+ * The inner segment defaults to `*` (whole-frame scope) since callers don't
130
+ * supply one here. Returns `options` untouched when `frameTarget` is
131
+ * unresolved (main frame) or a caller-supplied `selector` is already
132
+ * present — both cases must leave today's call sites byte-identical.
133
+ */
134
+ function frameScopedOptions(options, frameTarget) {
135
+ if (!frameTarget?.frameSelector || options?.selector !== undefined)
136
+ return options;
137
+ return { ...options, selector: (0, frame_target_1.buildHopSelector)(frameTarget.frameSelector, "*") };
138
+ }
121
139
  /**
122
140
  * Schema-guarded wrapper around Stagehand's `act`. Same signature as the
123
141
  * underlying call: accepts either an instruction string or a structured
124
142
  * `Action` (from a prior `observe`). On the happy path, returns Stagehand's
125
143
  * `ActResult` verbatim. On envelope drift, throws `StagehandSchemaError`
126
144
  * and logs `failureKind: "schema-validation-failed"`.
145
+ *
146
+ * Accepts the same trailing `frameTarget` param as `guardedObserve`/
147
+ * `guardedExtract` for signature symmetry, but does not forward it into
148
+ * `ActOptions` — `ActOptions` has no `selector` field, and its `page`
149
+ * override only accepts a full Playwright/Puppeteer/Patchright/understudy
150
+ * `Page`, not the `Frame` handle `FrameTarget.frame` exposes (the
151
+ * understudy `Page` constructor is private, so there is no way to
152
+ * synthesize a frame-scoped `Page`). Scope `act` at the call site instead:
153
+ * pair a frame-scoped `guardedObserve` (whose returned `Action.selector`
154
+ * already targets the resolved frame's DOM) with `guardedAct` called on
155
+ * that `Action` — the `observe(...)[0] -> act(target)` pattern already used
156
+ * throughout `flow-runner.ts`.
127
157
  */
128
- async function guardedAct(stagehand, input, options, captureFn) {
158
+ async function guardedAct(stagehand, input, options, captureFn, _frameTarget) {
129
159
  const callId = (0, node_crypto_1.randomUUID)();
130
160
  const userContent = actInstructionOf(input);
131
161
  const t0 = performance.now();
@@ -192,19 +222,29 @@ async function guardedAct(stagehand, input, options, captureFn) {
192
222
  * Stagehand overloads: no args, options-only, instruction-only,
193
223
  * instruction + options. On envelope drift (the `Action[]` shape changes),
194
224
  * throws `StagehandSchemaError`.
225
+ *
226
+ * When `frameTarget` resolves to a cross-origin child frame, its
227
+ * `frameSelector` is merged into `ObserveOptions.selector` so Stagehand's
228
+ * snapshot/candidate search is scoped to that frame's DOM instead of only
229
+ * the top frame. A caller-supplied `options.selector` wins over
230
+ * `frameTarget.frameSelector` — the caller made an explicit choice. The
231
+ * main-frame target (`frameTarget` omitted, or its `frameSelector` is
232
+ * `null`) leaves `options` untouched, so every existing call site is
233
+ * byte-identical to today.
195
234
  */
196
- async function guardedObserve(stagehand, instruction, options, captureFn) {
235
+ async function guardedObserve(stagehand, instruction, options, captureFn, frameTarget) {
197
236
  const callId = (0, node_crypto_1.randomUUID)();
198
237
  const userContent = instruction ?? "";
199
238
  const t0 = performance.now();
239
+ const scopedOptions = frameScopedOptions(options, frameTarget);
200
240
  try {
201
241
  // Match Stagehand's overloads: pass instruction only when defined, so
202
242
  // the SDK falls through to its no-arg/options-only path otherwise.
203
243
  const raw = instruction === undefined
204
- ? options === undefined
244
+ ? scopedOptions === undefined
205
245
  ? await stagehand.observe()
206
- : await stagehand.observe(options)
207
- : await stagehand.observe(instruction, options);
246
+ : await stagehand.observe(scopedOptions)
247
+ : await stagehand.observe(instruction, scopedOptions);
208
248
  const latencyMs = performance.now() - t0;
209
249
  const parsed = v4_1.z.array(exports.ACTION_SCHEMA).safeParse(raw);
210
250
  if (!parsed.success) {
@@ -257,8 +297,14 @@ async function guardedObserve(stagehand, instruction, options, captureFn) {
257
297
  * caller's Zod schema is what Stagehand asks the LLM to satisfy AND what we
258
298
  * `safeParse` against caller-side. Refuse the 1-arg / 2-arg defaults; every
259
299
  * extract call in the codebase must enforce a schema.
300
+ *
301
+ * When `frameTarget` resolves to a cross-origin child frame, its
302
+ * `frameSelector` is merged into `ExtractOptions.selector` so Stagehand
303
+ * extracts from that frame's DOM instead of only the top frame. A
304
+ * caller-supplied `options.selector` wins over `frameTarget.frameSelector`.
305
+ * The main-frame target leaves `options` untouched.
260
306
  */
261
- async function guardedExtract(stagehand, instruction, schema, options, captureFn) {
307
+ async function guardedExtract(stagehand, instruction, schema, options, captureFn, frameTarget) {
262
308
  const callId = (0, node_crypto_1.randomUUID)();
263
309
  const t0 = performance.now();
264
310
  try {
@@ -270,7 +316,7 @@ async function guardedExtract(stagehand, instruction, schema, options, captureFn
270
316
  // the cleanest public-API way to express "whatever overload-2 expects."
271
317
  // The `as unknown` step is needed because TS won't accept a single
272
318
  // direct cast across the entire overload set.
273
- const raw = await stagehand.extract(instruction, schema, options);
319
+ const raw = await stagehand.extract(instruction, schema, frameScopedOptions(options, frameTarget));
274
320
  const latencyMs = performance.now() - t0;
275
321
  const parsed = schema.safeParse(raw);
276
322
  if (!parsed.success) {
@@ -1 +1 @@
1
- {"version":3,"file":"stagehand-guard.js","sourceRoot":"","sources":["../../src/scraper/stagehand-guard.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stagehand-guard.js","sourceRoot":"","sources":["../../src/scraper/stagehand-guard.ts"],"names":[],"mappings":"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"}
@@ -22,8 +22,16 @@
22
22
  * re-runs the identical traversal and clicks the element at that index, so
23
23
  * the caller can locate once, decide which candidate to try, then click by
24
24
  * index without holding a live element handle across the two round trips.
25
+ *
26
+ * `root` overrides the traversal root expression (default `"document"`),
27
+ * interpolated verbatim into the generated code so a caller evaluating
28
+ * this expression via `Frame.evaluate` can pass `"document"` and still
29
+ * resolve that frame's own document — the expression never captures an
30
+ * outer `document` reference. {@link buildClickByDeepIndexExpr} must be
31
+ * given the same `root` so its re-run traversal produces the same
32
+ * `deepIndex` ordering as the one this call returned.
25
33
  */
26
- export declare function buildRankSubmitCandidatesExpr(): string;
34
+ export declare function buildRankSubmitCandidatesExpr(root?: string): string;
27
35
  /**
28
36
  * Builds a self-contained `page.evaluate` expression string that re-runs
29
37
  * the same deterministic deep traversal as {@link buildRankSubmitCandidatesExpr}
@@ -32,8 +40,13 @@ export declare function buildRankSubmitCandidatesExpr(): string;
32
40
  * convention). Returns `{ clicked: false }` without throwing if the index is
33
41
  * out of range for the current DOM (e.g. the page changed between the
34
42
  * locate and click calls).
43
+ *
44
+ * `root` overrides the traversal root expression (default `"document"`)
45
+ * and must match the `root` passed to the {@link buildRankSubmitCandidatesExpr}
46
+ * call that produced `deepIndex`, or the re-run traversal order will not
47
+ * line up with the original ranking.
35
48
  */
36
- export declare function buildClickByDeepIndexExpr(deepIndex: number): string;
49
+ export declare function buildClickByDeepIndexExpr(deepIndex: number, root?: string): string;
37
50
  /** Confidence tier for a ranked submit candidate — higher is more confident. See {@link buildRankSubmitCandidatesExpr}. */
38
51
  export type SubmitCandidateTier = 1 | 2 | 3;
39
52
  /** One ranked candidate returned by {@link buildRankSubmitCandidatesExpr}'s `page.evaluate` call. */
@@ -1 +1 @@
1
- {"version":3,"file":"submit-control.d.ts","sourceRoot":"","sources":["../../src/scraper/submit-control.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyEH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,6BAA6B,IAAI,MAAM,CAsBtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAYnE;AAED,2HAA2H;AAC3H,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAE5C,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;CAClB"}
1
+ {"version":3,"file":"submit-control.d.ts","sourceRoot":"","sources":["../../src/scraper/submit-control.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAyEH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,SAAa,GAAG,MAAM,CAsBvE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,SAAa,GAAG,MAAM,CAYtF;AAED,2HAA2H;AAC3H,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAE5C,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;CAClB"}
@@ -93,13 +93,21 @@ const RANK_TIERS_EXPR = `((el, name) => {
93
93
  * re-runs the identical traversal and clicks the element at that index, so
94
94
  * the caller can locate once, decide which candidate to try, then click by
95
95
  * index without holding a live element handle across the two round trips.
96
+ *
97
+ * `root` overrides the traversal root expression (default `"document"`),
98
+ * interpolated verbatim into the generated code so a caller evaluating
99
+ * this expression via `Frame.evaluate` can pass `"document"` and still
100
+ * resolve that frame's own document — the expression never captures an
101
+ * outer `document` reference. {@link buildClickByDeepIndexExpr} must be
102
+ * given the same `root` so its re-run traversal produces the same
103
+ * `deepIndex` ordering as the one this call returned.
96
104
  */
97
- function buildRankSubmitCandidatesExpr() {
105
+ function buildRankSubmitCandidatesExpr(root = "document") {
98
106
  return `(() => {
99
107
  const accessibleName = ${ACCESSIBLE_NAME_EXPR};
100
108
  const rankTier = ${RANK_TIERS_EXPR};
101
109
  const deepElements = ${DEEP_ELEMENTS_EXPR};
102
- const all = deepElements(document);
110
+ const all = deepElements(${root});
103
111
  const ranked = [];
104
112
  for (let i = 0; i < all.length; i++) {
105
113
  const el = all[i];
@@ -125,11 +133,16 @@ function buildRankSubmitCandidatesExpr() {
125
133
  * convention). Returns `{ clicked: false }` without throwing if the index is
126
134
  * out of range for the current DOM (e.g. the page changed between the
127
135
  * locate and click calls).
136
+ *
137
+ * `root` overrides the traversal root expression (default `"document"`)
138
+ * and must match the `root` passed to the {@link buildRankSubmitCandidatesExpr}
139
+ * call that produced `deepIndex`, or the re-run traversal order will not
140
+ * line up with the original ranking.
128
141
  */
129
- function buildClickByDeepIndexExpr(deepIndex) {
142
+ function buildClickByDeepIndexExpr(deepIndex, root = "document") {
130
143
  return `(() => {
131
144
  const deepElements = ${DEEP_ELEMENTS_EXPR};
132
- const all = deepElements(document);
145
+ const all = deepElements(${root});
133
146
  const el = all[${JSON.stringify(deepIndex)}];
134
147
  if (!el) return { clicked: false };
135
148
  if (typeof el.focus === "function") { try { el.focus(); } catch (e) {} }
@@ -1 +1 @@
1
- {"version":3,"file":"submit-control.js","sourceRoot":"","sources":["../../src/scraper/submit-control.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;;AAEH;;;;;;GAMG;AACH,MAAM,kBAAkB,GAAG;;;GAGxB,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG;;;GAG1B,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG;;;;;;;;;;;GAWxB,CAAC;AAEJ;;;;;;;;;;;;;;GAcG;AACH,MAAM,eAAe,GAAG;uBACD,kBAAkB;;;;;;;;;;;GAWtC,CAAC;AAEJ;;;;;;;;;;;;;;GAcG;AACH;IACE,OAAO;6BACoB,oBAAoB;uBAC1B,eAAe;2BACX,kBAAkB;;;;;;;;;;;;;;;;;OAiBtC,CAAC;AACR,CAAC;AAED;;;;;;;;GAQG;AACH,mCAA0C,SAAiB;IACzD,OAAO;2BACkB,kBAAkB;;qBAExB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;;;;;;;OAOvC,CAAC;AACR,CAAC"}
1
+ {"version":3,"file":"submit-control.js","sourceRoot":"","sources":["../../src/scraper/submit-control.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;;AAEH;;;;;;GAMG;AACH,MAAM,kBAAkB,GAAG;;;GAGxB,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG;;;GAG1B,CAAC;AAEJ;;;;;GAKG;AACH,MAAM,kBAAkB,GAAG;;;;;;;;;;;GAWxB,CAAC;AAEJ;;;;;;;;;;;;;;GAcG;AACH,MAAM,eAAe,GAAG;uBACD,kBAAkB;;;;;;;;;;;GAWtC,CAAC;AAEJ;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,uCAA8C,IAAI,GAAG,UAAU;IAC7D,OAAO;6BACoB,oBAAoB;uBAC1B,eAAe;2BACX,kBAAkB;+BACd,IAAI;;;;;;;;;;;;;;;;OAgB5B,CAAC;AACR,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,mCAA0C,SAAiB,EAAE,IAAI,GAAG,UAAU;IAC5E,OAAO;2BACkB,kBAAkB;+BACd,IAAI;qBACd,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC;;;;;;;OAOvC,CAAC;AACR,CAAC"}