@fusengine/browser-mcp 0.1.14 → 0.1.16

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 (61) hide show
  1. package/README.md +16 -4
  2. package/dist/actions/act-by-ref.d.ts +2 -2
  3. package/dist/actions/act-by-ref.d.ts.map +1 -1
  4. package/dist/actions/act-by-ref.js +4 -5
  5. package/dist/actions/act-by-ref.js.map +1 -1
  6. package/dist/actions/navigation.d.ts +10 -2
  7. package/dist/actions/navigation.d.ts.map +1 -1
  8. package/dist/actions/navigation.js +12 -2
  9. package/dist/actions/navigation.js.map +1 -1
  10. package/dist/actions/perform.d.ts.map +1 -1
  11. package/dist/actions/perform.js +4 -1
  12. package/dist/actions/perform.js.map +1 -1
  13. package/dist/actions/ref-locator.d.ts +17 -0
  14. package/dist/actions/ref-locator.d.ts.map +1 -0
  15. package/dist/actions/ref-locator.js +18 -0
  16. package/dist/actions/ref-locator.js.map +1 -0
  17. package/dist/extraction/collect-merge.d.ts +19 -0
  18. package/dist/extraction/collect-merge.d.ts.map +1 -0
  19. package/dist/extraction/collect-merge.js +18 -0
  20. package/dist/extraction/collect-merge.js.map +1 -0
  21. package/dist/extraction/scroll-script.d.ts +11 -0
  22. package/dist/extraction/scroll-script.d.ts.map +1 -0
  23. package/dist/extraction/scroll-script.js +55 -0
  24. package/dist/extraction/scroll-script.js.map +1 -0
  25. package/dist/extraction/snapshot-walk.d.ts +18 -0
  26. package/dist/extraction/snapshot-walk.d.ts.map +1 -0
  27. package/dist/extraction/snapshot-walk.js +61 -0
  28. package/dist/extraction/snapshot-walk.js.map +1 -0
  29. package/dist/extraction/snapshot.d.ts +12 -6
  30. package/dist/extraction/snapshot.d.ts.map +1 -1
  31. package/dist/extraction/snapshot.js +35 -39
  32. package/dist/extraction/snapshot.js.map +1 -1
  33. package/dist/interfaces/extraction.d.ts +12 -30
  34. package/dist/interfaces/extraction.d.ts.map +1 -1
  35. package/dist/interfaces/serp.d.ts +35 -0
  36. package/dist/interfaces/serp.d.ts.map +1 -0
  37. package/dist/interfaces/serp.js +6 -0
  38. package/dist/interfaces/serp.js.map +1 -0
  39. package/dist/lib/evaluate.d.ts +6 -3
  40. package/dist/lib/evaluate.d.ts.map +1 -1
  41. package/dist/lib/evaluate.js +4 -4
  42. package/dist/lib/evaluate.js.map +1 -1
  43. package/dist/server/server.d.ts.map +1 -1
  44. package/dist/server/server.js +2 -0
  45. package/dist/server/server.js.map +1 -1
  46. package/dist/server/tools/act.d.ts.map +1 -1
  47. package/dist/server/tools/act.js +3 -1
  48. package/dist/server/tools/act.js.map +1 -1
  49. package/dist/server/tools/collect.d.ts +13 -0
  50. package/dist/server/tools/collect.d.ts.map +1 -0
  51. package/dist/server/tools/collect.js +35 -0
  52. package/dist/server/tools/collect.js.map +1 -0
  53. package/dist/server/tools/screenshot.js +5 -5
  54. package/dist/server/tools/screenshot.js.map +1 -1
  55. package/dist/server/tools/snapshot.js +3 -3
  56. package/dist/server/tools/snapshot.js.map +1 -1
  57. package/dist/state/scroll-collect.d.ts +27 -0
  58. package/dist/state/scroll-collect.d.ts.map +1 -0
  59. package/dist/state/scroll-collect.js +34 -0
  60. package/dist/state/scroll-collect.js.map +1 -0
  61. package/package.json +2 -2
package/README.md CHANGED
@@ -78,6 +78,10 @@ Install the binaries once: `npm i -g @fusengine/browser-mcp` (provides `fuse-bro
78
78
  # One-shot probe of a real page
79
79
  fuse-browser probe https://example.com --extract-prices --observe-visual
80
80
 
81
+ # HTTP fast-path — browser TLS impersonation, NO browser launch (~10x faster)
82
+ # For server-rendered HTML (price lists, indexes). Falls back to probe for JS/SPA.
83
+ fuse-browser fetch https://books.toscrape.com/ --extract-prices --proxy http://user:pass@host:port
84
+
81
85
  # Hotels with country identity, proxy routing, replay
82
86
  fuse-browser probe 'https://www.booking.com/searchresults.html?ss=Tokyo' \
83
87
  --country JP --proxy-map proxies.json --replay --auto-consent --extract-prices
@@ -128,7 +132,7 @@ Supported: `FUSE_ENGINE`, `FUSE_CHANNEL`, `FUSE_CDP_ENDPOINT`, `FUSE_EXECUTABLE_
128
132
  `FUSE_HEADLESS`, `FUSE_COUNTRY`, `FUSE_CURRENCY`, `FUSE_USER_DATA_DIR`,
129
133
  `FUSE_STORAGE_STATE`, `FUSE_OUTPUT_DIR`.
130
134
 
131
- ### Tools (25)
135
+ ### Tools (26)
132
136
 
133
137
  | Group | Tools |
134
138
  | --- | --- |
@@ -136,8 +140,8 @@ Supported: `FUSE_ENGINE`, `FUSE_CHANNEL`, `FUSE_CDP_ENDPOINT`, `FUSE_EXECUTABLE_
136
140
  | **Fast-path** | `browser_fetch` — HTTP fetch with browser TLS/HTTP2 impersonation, **no browser launch** (~10× faster) for server-rendered HTML |
137
141
  | **Session** | `browser_open`, `browser_connect`, `browser_status`, `browser_close` |
138
142
  | **Navigate** | `browser_navigate`, `browser_back`, `browser_forward`, `browser_wait`, `browser_wait_for` |
139
- | **Act** | `browser_click`, `browser_fill`, `browser_login`, `browser_scroll`, `browser_press`, `browser_select` |
140
- | **Agentic** | `browser_snapshot` (indexed refs), `browser_act` (by ref + page diff), `browser_run` (multi-step plan) |
143
+ | **Act** | `browser_click`, `browser_fill`, `browser_login`, `browser_scroll` (window or a container via `selector`/`to:"end"`), `browser_press`, `browser_select` |
144
+ | **Agentic** | `browser_snapshot` (indexed refs), `browser_act` (by ref + page diff), `browser_run` (multi-step plan), `browser_collect` (exhaust a virtualized/infinite list) |
141
145
  | **Extract** | `browser_extract` (text/prices/hotels/challenges), `browser_extract_schema` (typed, by CSS selectors) |
142
146
  | **SERP** | `browser_serp_batch` — multi-query Google search in one session, per-query organic results + domain rank |
143
147
  | **Vision** | `browser_screenshot` (page, single element by `ref`, or responsive set via `viewport`/`viewports`) |
@@ -146,9 +150,17 @@ Key agentic patterns:
146
150
 
147
151
  - **`browser_snapshot` → `browser_act`** — snapshot tags each interactive element with a
148
152
  stable `ref`; act on a `ref` deterministically (or by text fallback). `browser_act`
149
- returns a **diff** of what changed (added/removed/text/url).
153
+ returns a **diff** of what changed (added/removed/text/url). The walk **pierces open
154
+ Shadow DOM and traverses iframes** (same- and cross-origin): elements inside a sub-frame
155
+ get a frame-scoped ref like `"3:4"`, so web-components, consent frames and embedded
156
+ checkouts are visible and actionable.
150
157
  - **`browser_wait_for`** — wait on a condition (`text` / `selector` / `gone` / `urlContains`),
151
158
  not a fixed delay.
159
+ - **`browser_collect`** — exhaust a **virtualized / infinite-scroll** list (hotel/flight
160
+ results, feeds): auto-detects the scroll container, scrolls incrementally and **dedups
161
+ rows by stable key** until the list ends. Returns the full set of rows (text / url /
162
+ optional prices) — data, not refs (virtualization recycles nodes), so to act on a found
163
+ row use `browser_act` by text or `browser_scroll` then `browser_snapshot`.
152
164
  - **`browser_run`** — execute an ordered plan (navigate/act/wait/extract) in one call,
153
165
  stopping at the first failure. Guardrails apply to the whole plan.
154
166
 
@@ -8,6 +8,6 @@ import type { Page } from "playwright";
8
8
  import type { ActionResult } from "../interfaces/types.js";
9
9
  /** Action kinds that can target a snapshot ref. */
10
10
  export type RefActionKind = "click" | "fill" | "select" | "pick";
11
- /** Run `kind` on the element carrying `data-fuse-ref="ref"`. */
12
- export declare function actByRef(page: Page, ref: number, kind: RefActionKind, value?: string, option?: string): Promise<ActionResult>;
11
+ /** Run `kind` on the element carrying the frame-scoped `ref`. */
12
+ export declare function actByRef(page: Page, ref: string | number, kind: RefActionKind, value?: string, option?: string): Promise<ActionResult>;
13
13
  //# sourceMappingURL=act-by-ref.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"act-by-ref.d.ts","sourceRoot":"","sources":["../../src/actions/act-by-ref.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D,mDAAmD;AACnD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjE,gEAAgE;AAChE,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,aAAa,EACnB,KAAK,SAAK,EACV,MAAM,SAAK,GACV,OAAO,CAAC,YAAY,CAAC,CAmBvB"}
1
+ {"version":3,"file":"act-by-ref.d.ts","sourceRoot":"","sources":["../../src/actions/act-by-ref.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAI3D,mDAAmD;AACnD,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEjE,iEAAiE;AACjE,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,MAAM,GAAG,MAAM,EACpB,IAAI,EAAE,aAAa,EACnB,KAAK,SAAK,EACV,MAAM,SAAK,GACV,OAAO,CAAC,YAAY,CAAC,CAkBvB"}
@@ -1,11 +1,10 @@
1
- import { REF_ATTRIBUTE } from "../extraction/snapshot.js";
2
1
  import { pickAutocomplete } from "./autocomplete.js";
3
- /** Run `kind` on the element carrying `data-fuse-ref="ref"`. */
2
+ import { refLocator } from "./ref-locator.js";
3
+ /** Run `kind` on the element carrying the frame-scoped `ref`. */
4
4
  export async function actByRef(page, ref, kind, value = "", option = "") {
5
- const selector = `[${REF_ATTRIBUTE}="${ref}"]`;
6
- const locator = page.locator(selector).first();
5
+ const locator = refLocator(page, ref);
7
6
  try {
8
- if ((await locator.count()) === 0) {
7
+ if (!locator || (await locator.count()) === 0) {
9
8
  return { type: kind, ok: false, ref, error: "ref_not_found" };
10
9
  }
11
10
  if (kind === "pick")
@@ -1 +1 @@
1
- {"version":3,"file":"act-by-ref.js","sourceRoot":"","sources":["../../src/actions/act-by-ref.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAKrD,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,IAAU,EACV,GAAW,EACX,IAAmB,EACnB,KAAK,GAAG,EAAE,EACV,MAAM,GAAG,EAAE;IAEX,MAAM,QAAQ,GAAG,IAAI,aAAa,KAAK,GAAG,IAAI,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;IAC/C,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QAChE,CAAC;QACD,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO,EAAE,GAAG,CAAC,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QAC/F,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;IACtF,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"act-by-ref.js","sourceRoot":"","sources":["../../src/actions/act-by-ref.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAK9C,iEAAiE;AACjE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,IAAU,EACV,GAAoB,EACpB,IAAmB,EACnB,KAAK,GAAG,EAAE,EACV,MAAM,GAAG,EAAE;IAEX,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC;QACH,IAAI,CAAC,OAAO,IAAI,CAAC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9C,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QAChE,CAAC;QACD,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO,EAAE,GAAG,CAAC,MAAM,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC;QAC/F,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,OAAO,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,MAAM,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IACxD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;IACtF,CAAC;AACH,CAAC"}
@@ -4,8 +4,16 @@
4
4
  */
5
5
  import type { Page } from "playwright";
6
6
  import type { ActionResult } from "../interfaces/types.js";
7
- /** Scroll the page by a pixel delta (positive = down/right). */
8
- export declare function scroll(page: Page, deltaY: number, deltaX?: number): Promise<ActionResult>;
7
+ /** Optional scroll target: a specific container and/or jump to its end. */
8
+ export interface ScrollOpts {
9
+ selector?: string;
10
+ to?: "end";
11
+ }
12
+ /**
13
+ * Scroll by a pixel delta (window, positive = down/right). With `selector` or
14
+ * `to:"end"`, scroll the matching (or auto-detected) scrollable container.
15
+ */
16
+ export declare function scroll(page: Page, deltaY: number, deltaX?: number, opts?: ScrollOpts): Promise<ActionResult>;
9
17
  /** Press a key or shortcut (e.g. "Enter", "ArrowDown", "Control+a"). */
10
18
  export declare function pressKey(page: Page, key: string): Promise<ActionResult>;
11
19
  /** Select option(s) in a <select> by value, label or index. */
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/actions/navigation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,gEAAgE;AAChE,wBAAsB,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,OAAO,CAAC,YAAY,CAAC,CAG1F;AAED,wEAAwE;AACxE,wBAAsB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAO7E;AAED,+DAA+D;AAC/D,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAOvB;AAED,6CAA6C;AAC7C,wBAAsB,eAAe,CACnC,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAAC,YAAY,CAAC,CAMvB"}
1
+ {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/actions/navigation.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAW3D,2EAA2E;AAC3E,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,KAAK,CAAC;CACZ;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAC1B,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,MAAM,SAAI,EACV,IAAI,GAAE,UAAe,GACpB,OAAO,CAAC,YAAY,CAAC,CAQvB;AAED,wEAAwE;AACxE,wBAAsB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAO7E;AAED,+DAA+D;AAC/D,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAOvB;AAED,6CAA6C;AAC7C,wBAAsB,eAAe,CACnC,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAAC,YAAY,CAAC,CAMvB"}
@@ -1,5 +1,15 @@
1
- /** Scroll the page by a pixel delta (positive = down/right). */
2
- export async function scroll(page, deltaY, deltaX = 0) {
1
+ import { SCROLL_SCRIPT } from "../extraction/scroll-script.js";
2
+ import { evalScriptArg } from "../lib/evaluate.js";
3
+ /**
4
+ * Scroll by a pixel delta (window, positive = down/right). With `selector` or
5
+ * `to:"end"`, scroll the matching (or auto-detected) scrollable container.
6
+ */
7
+ export async function scroll(page, deltaY, deltaX = 0, opts = {}) {
8
+ if (opts.selector || opts.to === "end") {
9
+ const arg = { selector: opts.selector ?? null, to: opts.to ?? null, delta: deltaY };
10
+ const geo = await evalScriptArg(page, SCROLL_SCRIPT, arg);
11
+ return { type: "scroll", ok: geo.found, deltaY, selector: opts.selector ?? null, scrollTop: geo.scrollTop, atEnd: geo.atEnd };
12
+ }
3
13
  await page.mouse.wheel(deltaX, deltaY);
4
14
  return { type: "scroll", ok: true, deltaX, deltaY };
5
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/actions/navigation.ts"],"names":[],"mappings":"AAOA,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAU,EAAE,MAAc,EAAE,MAAM,GAAG,CAAC;IACjE,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACtD,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAU,EAAE,GAAW;IACpD,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;IACzF,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAU,EACV,MAAc,EACd,KAAa;IAEb,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5F,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;IAC7F,CAAC;AACH,CAAC;AAED,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,IAAU,EACV,SAA6B;IAE7B,MAAM,QAAQ,GACZ,SAAS,KAAK,MAAM;QAClB,CAAC,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QACvE,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/E,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,KAAK,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AACrE,CAAC"}
1
+ {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/actions/navigation.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"perform.d.ts","sourceRoot":"","sources":["../../src/actions/perform.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAO3D,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,6CAA6C;AAC7C,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,WAAW,EACnB,SAAS,UAAQ,GAChB,OAAO,CAAC,YAAY,CAAC,CA6BvB;AAED,yDAAyD;AACzD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIhF"}
1
+ {"version":3,"file":"perform.d.ts","sourceRoot":"","sources":["../../src/actions/perform.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAO3D,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,6CAA6C;AAC7C,wBAAsB,aAAa,CACjC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,WAAW,EACnB,SAAS,UAAQ,GAChB,OAAO,CAAC,YAAY,CAAC,CAgCvB;AAED,yDAAyD;AACzD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAIhF"}
@@ -15,7 +15,10 @@ export async function performAction(page, action, humanMode = false) {
15
15
  case "login":
16
16
  return login(page, action, humanMode);
17
17
  case "scroll":
18
- return scroll(page, Number(action.deltaY ?? 600), Number(action.deltaX ?? 0));
18
+ return scroll(page, Number(action.deltaY ?? 600), Number(action.deltaX ?? 0), {
19
+ selector: typeof action.selector === "string" ? action.selector : undefined,
20
+ to: action.to === "end" ? "end" : undefined,
21
+ });
19
22
  case "press":
20
23
  return pressKey(page, String(action.key ?? ""));
21
24
  case "select":
@@ -1 +1 @@
1
- {"version":3,"file":"perform.js","sourceRoot":"","sources":["../../src/actions/perform.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,KAAK,EAAoB,MAAM,YAAY,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAK5C,6CAA6C;AAC7C,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,IAAU,EACV,MAAmB,EACnB,SAAS,GAAG,KAAK;IAEjB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC;IACzD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,OAAO;YACV,OAAO,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACxD,KAAK,MAAM;YACT,OAAO,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACnF,KAAK,OAAO;YACV,OAAO,KAAK,CAAC,IAAI,EAAE,MAAqB,EAAE,SAAS,CAAC,CAAC;QACvD,KAAK,QAAQ;YACX,OAAO,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;QAChF,KAAK,OAAO;YACV,OAAO,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;QAClD,KAAK,QAAQ;YACX,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC;QAChE,KAAK,MAAM;YACT,OAAO,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC;QACvH,KAAK,MAAM,CAAC;QACZ,KAAK,SAAS;YACZ,OAAO,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5C,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC;YACpC,MAAM,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;YAC9B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;QACxC,CAAC;QACD;YACE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,gBAAgB,EAAE,CAAC;IACrE,CAAC;AACH,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,mBAAmB,CAAC,MAAmB;IACrD,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;IAC3B,IAAI,UAAU,IAAI,IAAI;QAAE,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC"}
1
+ {"version":3,"file":"perform.js","sourceRoot":"","sources":["../../src/actions/perform.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Resolve a snapshot `ref` to a Playwright locator, honoring the frame-scoped
3
+ * ref scheme produced by {@link captureSnapshot}: `"<frame>:<local>"` targets
4
+ * `page.frames()[frame]`, a bare `"<local>"` targets the main frame.
5
+ * @module actions/ref-locator
6
+ */
7
+ import type { Locator, Page } from "playwright";
8
+ /** A ref split into its frame ordinal and frame-local index. */
9
+ export interface ParsedRef {
10
+ frame: number;
11
+ local: string;
12
+ }
13
+ /** Parse a ref string/number into `{ frame, local }` (bare value → main frame). */
14
+ export declare function parseRef(ref: string | number): ParsedRef;
15
+ /** Locator for `ref`, scoped to its owning frame; `null` if the frame is gone. */
16
+ export declare function refLocator(page: Page, ref: string | number): Locator | null;
17
+ //# sourceMappingURL=ref-locator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref-locator.d.ts","sourceRoot":"","sources":["../../src/actions/ref-locator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGhD,gEAAgE;AAChE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,mFAAmF;AACnF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAKxD;AAED,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAK3E"}
@@ -0,0 +1,18 @@
1
+ import { REF_ATTRIBUTE } from "../extraction/snapshot.js";
2
+ /** Parse a ref string/number into `{ frame, local }` (bare value → main frame). */
3
+ export function parseRef(ref) {
4
+ const s = String(ref);
5
+ const sep = s.indexOf(":");
6
+ if (sep === -1)
7
+ return { frame: 0, local: s };
8
+ return { frame: Number(s.slice(0, sep)), local: s.slice(sep + 1) };
9
+ }
10
+ /** Locator for `ref`, scoped to its owning frame; `null` if the frame is gone. */
11
+ export function refLocator(page, ref) {
12
+ const { frame, local } = parseRef(ref);
13
+ const target = page.frames()[frame];
14
+ if (!target)
15
+ return null;
16
+ return target.locator(`[${REF_ATTRIBUTE}="${local}"]`).first();
17
+ }
18
+ //# sourceMappingURL=ref-locator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ref-locator.js","sourceRoot":"","sources":["../../src/actions/ref-locator.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAQ1D,mFAAmF;AACnF,MAAM,UAAU,QAAQ,CAAC,GAAoB;IAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;AACrE,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,UAAU,CAAC,IAAU,EAAE,GAAoB;IACzD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO,MAAM,CAAC,OAAO,CAAC,IAAI,aAAa,KAAK,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;AACjE,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Pure merge/dedup for scroll-collected rows. Virtualized lists recycle DOM
3
+ * nodes, so rows are keyed by a stable identifier (data-id › href › text), not
4
+ * by node identity. Kept side-effect-free for unit testing.
5
+ * @module extraction/collect-merge
6
+ */
7
+ import type { CollectedItem, Price } from "../interfaces/extraction.js";
8
+ /** A raw row harvested in the page context (before price enrichment). */
9
+ export interface RawRow {
10
+ key: string;
11
+ text: string;
12
+ url: string | null;
13
+ }
14
+ /**
15
+ * Merge `rows` into `seen` (keyed dedup), optionally enriching each new row
16
+ * with prices via `pricer`. Returns the number of rows that were new.
17
+ */
18
+ export declare function mergeItems(seen: Map<string, CollectedItem>, rows: RawRow[], pricer: ((text: string) => Price[]) | null): number;
19
+ //# sourceMappingURL=collect-merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect-merge.d.ts","sourceRoot":"","sources":["../../src/extraction/collect-merge.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAExE,yEAAyE;AACzE,MAAM,WAAW,MAAM;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,EAChC,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,KAAK,EAAE,CAAC,GAAG,IAAI,GACzC,MAAM,CAUR"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Merge `rows` into `seen` (keyed dedup), optionally enriching each new row
3
+ * with prices via `pricer`. Returns the number of rows that were new.
4
+ */
5
+ export function mergeItems(seen, rows, pricer) {
6
+ let added = 0;
7
+ for (const row of rows) {
8
+ if (!row.key || seen.has(row.key))
9
+ continue;
10
+ const item = { key: row.key, text: row.text, url: row.url };
11
+ if (pricer)
12
+ item.prices = pricer(row.text);
13
+ seen.set(row.key, item);
14
+ added++;
15
+ }
16
+ return added;
17
+ }
18
+ //# sourceMappingURL=collect-merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect-merge.js","sourceRoot":"","sources":["../../src/extraction/collect-merge.ts"],"names":[],"mappings":"AAeA;;;GAGG;AACH,MAAM,UAAU,UAAU,CACxB,IAAgC,EAChC,IAAc,EACd,MAA0C;IAE1C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5C,MAAM,IAAI,GAAkB,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC;QAC3E,IAAI,MAAM;YAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACxB,KAAK,EAAE,CAAC;IACV,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Browser-side scripts for virtualized/infinite lists: detect the scrollable
3
+ * container (explicit selector or auto by overflow + scrollHeight), scroll it,
4
+ * and harvest the currently-mounted rows. Runs in the page context.
5
+ * @module extraction/scroll-script
6
+ */
7
+ /** Scroll the (auto-detected or `selector`) container; `to:"end"` jumps to bottom. */
8
+ export declare const SCROLL_SCRIPT = "(arg) => {\n const pick = (sel) => {\n if (sel) return document.querySelector(sel);\n let best = null, bestH = 0;\n for (const el of document.querySelectorAll('*')) {\n const oy = getComputedStyle(el).overflowY;\n if ((oy === 'auto' || oy === 'scroll' || oy === 'overlay') &&\n el.scrollHeight > el.clientHeight + 4 && el.clientHeight > innerHeight * 0.3 &&\n el.scrollHeight > bestH) { best = el; bestH = el.scrollHeight; }\n }\n return best || document.scrollingElement || document.documentElement;\n };\n const el = pick(arg.selector);\n if (!el) return { found: false };\n el.style.overflowAnchor = 'none';\n const before = el.scrollTop;\n if (arg.to === 'end') el.scrollTop = el.scrollHeight;\n else el.scrollTop += (arg.delta || Math.floor(el.clientHeight * 0.9));\n return { found: true, scrollTop: el.scrollTop, scrollHeight: el.scrollHeight,\n clientHeight: el.clientHeight, moved: el.scrollTop - before,\n atEnd: el.scrollTop + el.clientHeight >= el.scrollHeight - 4 };\n}";
9
+ /** Harvest visible `item` rows, then scroll the container one step. */
10
+ export declare const SCAN_SCRIPT = "(arg) => {\n const pick = (sel) => {\n if (sel) return document.querySelector(sel);\n let best = null, bestH = 0;\n for (const el of document.querySelectorAll('*')) {\n const oy = getComputedStyle(el).overflowY;\n if ((oy === 'auto' || oy === 'scroll' || oy === 'overlay') &&\n el.scrollHeight > el.clientHeight + 4 && el.clientHeight > innerHeight * 0.3 &&\n el.scrollHeight > bestH) { best = el; bestH = el.scrollHeight; }\n }\n return best || document.scrollingElement || document.documentElement;\n };\n const keyOf = (el) => (el.getAttribute('data-id') || el.getAttribute('data-key') ||\n (el.querySelector('a[href]') && el.querySelector('a[href]').href) ||\n (el.textContent || '').replace(/\\s+/g,' ').trim().slice(0, 120));\n const el = pick(arg.selector);\n const rows = [...document.querySelectorAll(arg.item)].slice(0, 500).map((r) => {\n const a = r.querySelector('a[href]');\n return { key: keyOf(r), text: (r.textContent || '').replace(/\\s+/g,' ').trim().slice(0, 300), url: a ? a.href : null };\n });\n let geo = { moved: 0, atEnd: true, scrollHeight: 0, clientHeight: 0, scrollTop: 0 };\n if (el) {\n el.style.overflowAnchor = 'none';\n const before = el.scrollTop;\n el.scrollTop += Math.floor(el.clientHeight * (arg.stepFraction || 0.9));\n geo = { moved: el.scrollTop - before, scrollHeight: el.scrollHeight,\n clientHeight: el.clientHeight, scrollTop: el.scrollTop,\n atEnd: el.scrollTop + el.clientHeight >= el.scrollHeight - 4 };\n }\n return { items: rows, geo };\n}";
11
+ //# sourceMappingURL=scroll-script.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-script.d.ts","sourceRoot":"","sources":["../../src/extraction/scroll-script.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsBH,sFAAsF;AACtF,eAAO,MAAM,aAAa,qhCAUxB,CAAC;AAEH,uEAAuE;AACvE,eAAO,MAAM,WAAW,8iDAgBtB,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Browser-side scripts for virtualized/infinite lists: detect the scrollable
3
+ * container (explicit selector or auto by overflow + scrollHeight), scroll it,
4
+ * and harvest the currently-mounted rows. Runs in the page context.
5
+ * @module extraction/scroll-script
6
+ */
7
+ /** Container picker: explicit `sel`, else the tallest overflow:auto/scroll element. */
8
+ const FINDER = `
9
+ const pick = (sel) => {
10
+ if (sel) return document.querySelector(sel);
11
+ let best = null, bestH = 0;
12
+ for (const el of document.querySelectorAll('*')) {
13
+ const oy = getComputedStyle(el).overflowY;
14
+ if ((oy === 'auto' || oy === 'scroll' || oy === 'overlay') &&
15
+ el.scrollHeight > el.clientHeight + 4 && el.clientHeight > innerHeight * 0.3 &&
16
+ el.scrollHeight > bestH) { best = el; bestH = el.scrollHeight; }
17
+ }
18
+ return best || document.scrollingElement || document.documentElement;
19
+ };`;
20
+ /** Stable key for a row: data-id › data-key › first href › trimmed text. */
21
+ const KEYER = `
22
+ const keyOf = (el) => (el.getAttribute('data-id') || el.getAttribute('data-key') ||
23
+ (el.querySelector('a[href]') && el.querySelector('a[href]').href) ||
24
+ (el.textContent || '').replace(/\\s+/g,' ').trim().slice(0, 120));`;
25
+ /** Scroll the (auto-detected or `selector`) container; `to:"end"` jumps to bottom. */
26
+ export const SCROLL_SCRIPT = `(arg) => {${FINDER}
27
+ const el = pick(arg.selector);
28
+ if (!el) return { found: false };
29
+ el.style.overflowAnchor = 'none';
30
+ const before = el.scrollTop;
31
+ if (arg.to === 'end') el.scrollTop = el.scrollHeight;
32
+ else el.scrollTop += (arg.delta || Math.floor(el.clientHeight * 0.9));
33
+ return { found: true, scrollTop: el.scrollTop, scrollHeight: el.scrollHeight,
34
+ clientHeight: el.clientHeight, moved: el.scrollTop - before,
35
+ atEnd: el.scrollTop + el.clientHeight >= el.scrollHeight - 4 };
36
+ }`;
37
+ /** Harvest visible `item` rows, then scroll the container one step. */
38
+ export const SCAN_SCRIPT = `(arg) => {${FINDER}${KEYER}
39
+ const el = pick(arg.selector);
40
+ const rows = [...document.querySelectorAll(arg.item)].slice(0, 500).map((r) => {
41
+ const a = r.querySelector('a[href]');
42
+ return { key: keyOf(r), text: (r.textContent || '').replace(/\\s+/g,' ').trim().slice(0, 300), url: a ? a.href : null };
43
+ });
44
+ let geo = { moved: 0, atEnd: true, scrollHeight: 0, clientHeight: 0, scrollTop: 0 };
45
+ if (el) {
46
+ el.style.overflowAnchor = 'none';
47
+ const before = el.scrollTop;
48
+ el.scrollTop += Math.floor(el.clientHeight * (arg.stepFraction || 0.9));
49
+ geo = { moved: el.scrollTop - before, scrollHeight: el.scrollHeight,
50
+ clientHeight: el.clientHeight, scrollTop: el.scrollTop,
51
+ atEnd: el.scrollTop + el.clientHeight >= el.scrollHeight - 4 };
52
+ }
53
+ return { items: rows, geo };
54
+ }`;
55
+ //# sourceMappingURL=scroll-script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-script.js","sourceRoot":"","sources":["../../src/extraction/scroll-script.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,uFAAuF;AACvF,MAAM,MAAM,GAAG;;;;;;;;;;;KAWV,CAAC;AAEN,4EAA4E;AAC5E,MAAM,KAAK,GAAG;;;uEAGyD,CAAC;AAExE,sFAAsF;AACtF,MAAM,CAAC,MAAM,aAAa,GAAG,aAAa,MAAM;;;;;;;;;;EAU9C,CAAC;AAEH,uEAAuE;AACvE,MAAM,CAAC,MAAM,WAAW,GAAG,aAAa,MAAM,GAAG,KAAK;;;;;;;;;;;;;;;;EAgBpD,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Browser-side snapshot walk: collects interactive elements, piercing OPEN
3
+ * Shadow DOM recursively. Iframes are NOT descended here — each frame is walked
4
+ * separately on the Node side via {@link captureSnapshot} (cross-origin frames
5
+ * are unreadable from the parent context, and same-origin ones would duplicate).
6
+ * Closed shadow roots are inaccessible by browser SOP and stay opaque.
7
+ * @module extraction/snapshot-walk
8
+ */
9
+ /** Attribute injected on each interactive element to anchor a stable ref. */
10
+ export declare const REF_ATTRIBUTE = "data-fuse-ref";
11
+ /**
12
+ * Arrow-function source (run via `evalScript` in each frame). Stamps a LOCAL
13
+ * `data-fuse-ref` (per-frame index) and returns elements in visitation order;
14
+ * the Node side rewrites `index` to a global counter and adds the frame-scoped
15
+ * `ref`. Capped at 200 elements per frame.
16
+ */
17
+ export declare const SNAPSHOT_SCRIPT = "() => {\n const SEL = 'button,a,input,select,textarea,[role=button],[role=combobox],[role=checkbox],[role=radio],[role=switch],[role=tab],[role=menuitem],[role=option],[contenteditable=true]';\n const obscured = (el, r) => {\n const cx = r.x + r.width / 2, cy = r.y + r.height / 2;\n if (r.width === 0 || cx < 0 || cy < 0 || cx > innerWidth || cy > innerHeight) return false;\n const top = document.elementFromPoint(cx, cy);\n return !!top && top !== el && !el.contains(top) && !top.contains(el);\n };\n const out = [];\n const describe = (el, index) => {\n const r = el.getBoundingClientRect();\n const val = typeof el.value === 'string' ? el.value : null;\n const isCheck = el.type === 'checkbox' || el.type === 'radio';\n return {\n index,\n tag: el.tagName.toLowerCase(),\n text: (el.innerText || el.getAttribute('aria-label') || el.getAttribute('placeholder') || '').trim().slice(0, 120),\n role: el.getAttribute('role'), id: el.id || null, name: el.getAttribute('name'),\n type: el.getAttribute('type'), href: el.getAttribute('href'),\n value: val ? val.slice(0, 120) : null, placeholder: el.getAttribute('placeholder'),\n disabled: !!el.disabled || el.getAttribute('aria-disabled') === 'true',\n checked: isCheck ? !!el.checked : undefined,\n options: el.tagName === 'SELECT' ? [...el.options].slice(0, 12).map((o) => o.label || o.value) : undefined,\n ariaExpanded: el.getAttribute('aria-expanded'), ariaControls: el.getAttribute('aria-controls'),\n visible: r.width > 0 && r.height > 0, obscured: obscured(el, r),\n box: {x: Math.round(r.x), y: Math.round(r.y), width: Math.round(r.width), height: Math.round(r.height)}\n };\n };\n const visit = (root) => {\n if (out.length >= 200) return;\n for (const el of root.querySelectorAll(SEL)) {\n if (out.length >= 200) return;\n const i = out.length;\n el.setAttribute('data-fuse-ref', String(i));\n out.push(describe(el, i));\n }\n for (const host of root.querySelectorAll('*')) {\n if (host.shadowRoot) visit(host.shadowRoot);\n }\n };\n visit(document);\n return out;\n}";
18
+ //# sourceMappingURL=snapshot-walk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-walk.d.ts","sourceRoot":"","sources":["../../src/extraction/snapshot-walk.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAK7C;;;;;GAKG;AACH,eAAO,MAAM,eAAe,0nEA0C1B,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Browser-side snapshot walk: collects interactive elements, piercing OPEN
3
+ * Shadow DOM recursively. Iframes are NOT descended here — each frame is walked
4
+ * separately on the Node side via {@link captureSnapshot} (cross-origin frames
5
+ * are unreadable from the parent context, and same-origin ones would duplicate).
6
+ * Closed shadow roots are inaccessible by browser SOP and stay opaque.
7
+ * @module extraction/snapshot-walk
8
+ */
9
+ /** Attribute injected on each interactive element to anchor a stable ref. */
10
+ export const REF_ATTRIBUTE = "data-fuse-ref";
11
+ const SELECTOR = "button,a,input,select,textarea,[role=button],[role=combobox],[role=checkbox],[role=radio],[role=switch],[role=tab],[role=menuitem],[role=option],[contenteditable=true]";
12
+ /**
13
+ * Arrow-function source (run via `evalScript` in each frame). Stamps a LOCAL
14
+ * `data-fuse-ref` (per-frame index) and returns elements in visitation order;
15
+ * the Node side rewrites `index` to a global counter and adds the frame-scoped
16
+ * `ref`. Capped at 200 elements per frame.
17
+ */
18
+ export const SNAPSHOT_SCRIPT = `() => {
19
+ const SEL = '${SELECTOR}';
20
+ const obscured = (el, r) => {
21
+ const cx = r.x + r.width / 2, cy = r.y + r.height / 2;
22
+ if (r.width === 0 || cx < 0 || cy < 0 || cx > innerWidth || cy > innerHeight) return false;
23
+ const top = document.elementFromPoint(cx, cy);
24
+ return !!top && top !== el && !el.contains(top) && !top.contains(el);
25
+ };
26
+ const out = [];
27
+ const describe = (el, index) => {
28
+ const r = el.getBoundingClientRect();
29
+ const val = typeof el.value === 'string' ? el.value : null;
30
+ const isCheck = el.type === 'checkbox' || el.type === 'radio';
31
+ return {
32
+ index,
33
+ tag: el.tagName.toLowerCase(),
34
+ text: (el.innerText || el.getAttribute('aria-label') || el.getAttribute('placeholder') || '').trim().slice(0, 120),
35
+ role: el.getAttribute('role'), id: el.id || null, name: el.getAttribute('name'),
36
+ type: el.getAttribute('type'), href: el.getAttribute('href'),
37
+ value: val ? val.slice(0, 120) : null, placeholder: el.getAttribute('placeholder'),
38
+ disabled: !!el.disabled || el.getAttribute('aria-disabled') === 'true',
39
+ checked: isCheck ? !!el.checked : undefined,
40
+ options: el.tagName === 'SELECT' ? [...el.options].slice(0, 12).map((o) => o.label || o.value) : undefined,
41
+ ariaExpanded: el.getAttribute('aria-expanded'), ariaControls: el.getAttribute('aria-controls'),
42
+ visible: r.width > 0 && r.height > 0, obscured: obscured(el, r),
43
+ box: {x: Math.round(r.x), y: Math.round(r.y), width: Math.round(r.width), height: Math.round(r.height)}
44
+ };
45
+ };
46
+ const visit = (root) => {
47
+ if (out.length >= 200) return;
48
+ for (const el of root.querySelectorAll(SEL)) {
49
+ if (out.length >= 200) return;
50
+ const i = out.length;
51
+ el.setAttribute('${REF_ATTRIBUTE}', String(i));
52
+ out.push(describe(el, i));
53
+ }
54
+ for (const host of root.querySelectorAll('*')) {
55
+ if (host.shadowRoot) visit(host.shadowRoot);
56
+ }
57
+ };
58
+ visit(document);
59
+ return out;
60
+ }`;
61
+ //# sourceMappingURL=snapshot-walk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot-walk.js","sourceRoot":"","sources":["../../src/extraction/snapshot-walk.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,6EAA6E;AAC7E,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAE7C,MAAM,QAAQ,GACZ,yKAAyK,CAAC;AAE5K;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;iBACd,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAgCA,aAAa;;;;;;;;;EASpC,CAAC"}
@@ -1,14 +1,20 @@
1
1
  /**
2
2
  * Accessibility-style snapshot: tag each interactive element with a stable
3
- * `data-fuse-ref` and return an indexed list the LLM can reason about.
4
- * The ref survives until the page re-renders, enabling deterministic
5
- * `browser_act` targeting via `[data-fuse-ref="N"]`.
3
+ * `data-fuse-ref` and return an indexed list the LLM can reason about. The walk
4
+ * runs in EVERY frame (`page.frames()`) and pierces open Shadow DOM, so refs
5
+ * cover iframes (same- and cross-origin) and web components. Each element's
6
+ * `ref` is frame-scoped (`"<frame>:<local>"`, bare `"<local>"` for the main
7
+ * frame) and resolves via {@link refLocator}.
6
8
  * @module extraction/snapshot
7
9
  */
8
10
  import type { Page } from "playwright";
9
11
  import type { InteractiveElement } from "../interfaces/extraction.js";
10
- /** Attribute injected on each interactive element to anchor a stable ref. */
11
- export declare const REF_ATTRIBUTE = "data-fuse-ref";
12
- /** Capture the indexed interactive snapshot, tagging each element with a ref. */
12
+ export { REF_ATTRIBUTE } from "./snapshot-walk.js";
13
+ /**
14
+ * Capture the indexed interactive snapshot across all frames, tagging each
15
+ * element with a (frame-local) ref attribute and exposing a frame-scoped `ref`.
16
+ * Detached frames and frames that reject evaluation (e.g. mid-navigation) are
17
+ * skipped rather than aborting the whole snapshot.
18
+ */
13
19
  export declare function captureSnapshot(page: Page): Promise<InteractiveElement[]>;
14
20
  //# sourceMappingURL=snapshot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/extraction/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGtE,6EAA6E;AAC7E,eAAO,MAAM,aAAa,kBAAkB,CAAC;AAwC7C,iFAAiF;AACjF,wBAAsB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAE/E"}
1
+ {"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/extraction/snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAItE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAKnD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAsB/E"}
@@ -1,43 +1,39 @@
1
1
  import { evalScript } from "../lib/evaluate.js";
2
- /** Attribute injected on each interactive element to anchor a stable ref. */
3
- export const REF_ATTRIBUTE = "data-fuse-ref";
4
- const SELECTOR = "button,a,input,select,textarea,[role=button],[role=combobox],[role=checkbox],[role=radio],[role=switch],[role=tab],[role=menuitem],[role=option],[contenteditable=true]";
5
- const SNAPSHOT_SCRIPT = `() => {
6
- const obscured = (el, r) => {
7
- const cx = r.x + r.width / 2, cy = r.y + r.height / 2;
8
- if (r.width === 0 || cx < 0 || cy < 0 || cx > innerWidth || cy > innerHeight) return false;
9
- const top = document.elementFromPoint(cx, cy);
10
- return !!top && top !== el && !el.contains(top) && !top.contains(el);
11
- };
12
- return [...document.querySelectorAll('${SELECTOR}')].slice(0, 200).map((el, index) => {
13
- el.setAttribute('${REF_ATTRIBUTE}', String(index));
14
- const r = el.getBoundingClientRect();
15
- const val = typeof el.value === 'string' ? el.value : null;
16
- const isCheck = el.type === 'checkbox' || el.type === 'radio';
17
- return {
18
- index,
19
- tag: el.tagName.toLowerCase(),
20
- text: (el.innerText || el.getAttribute('aria-label') || el.getAttribute('placeholder') || '').trim().slice(0, 120),
21
- role: el.getAttribute('role'),
22
- id: el.id || null,
23
- name: el.getAttribute('name'),
24
- type: el.getAttribute('type'),
25
- href: el.getAttribute('href'),
26
- value: val ? val.slice(0, 120) : null,
27
- placeholder: el.getAttribute('placeholder'),
28
- disabled: !!el.disabled || el.getAttribute('aria-disabled') === 'true',
29
- checked: isCheck ? !!el.checked : undefined,
30
- options: el.tagName === 'SELECT' ? [...el.options].slice(0, 12).map((o) => o.label || o.value) : undefined,
31
- ariaExpanded: el.getAttribute('aria-expanded'),
32
- ariaControls: el.getAttribute('aria-controls'),
33
- visible: r.width > 0 && r.height > 0,
34
- obscured: obscured(el, r),
35
- box: {x: Math.round(r.x), y: Math.round(r.y), width: Math.round(r.width), height: Math.round(r.height)}
36
- };
37
- });
38
- }`;
39
- /** Capture the indexed interactive snapshot, tagging each element with a ref. */
2
+ import { SNAPSHOT_SCRIPT } from "./snapshot-walk.js";
3
+ export { REF_ATTRIBUTE } from "./snapshot-walk.js";
4
+ /** Soft cap on total elements across all frames, to bound output size. */
5
+ const MAX_ELEMENTS = 400;
6
+ /**
7
+ * Capture the indexed interactive snapshot across all frames, tagging each
8
+ * element with a (frame-local) ref attribute and exposing a frame-scoped `ref`.
9
+ * Detached frames and frames that reject evaluation (e.g. mid-navigation) are
10
+ * skipped rather than aborting the whole snapshot.
11
+ */
40
12
  export async function captureSnapshot(page) {
41
- return evalScript(page, SNAPSHOT_SCRIPT);
13
+ const frames = page.frames();
14
+ const all = [];
15
+ let global = 0;
16
+ for (let f = 0; f < frames.length && all.length < MAX_ELEMENTS; f++) {
17
+ const frame = frames[f];
18
+ if (!frame || frame.isDetached())
19
+ continue;
20
+ let local;
21
+ try {
22
+ local = await evalScript(frame, SNAPSHOT_SCRIPT);
23
+ }
24
+ catch {
25
+ continue;
26
+ }
27
+ for (const el of local) {
28
+ if (all.length >= MAX_ELEMENTS)
29
+ break;
30
+ el.ref = f === 0 ? String(el.index) : `${f}:${el.index}`;
31
+ if (f > 0)
32
+ el.frame = f;
33
+ el.index = global++;
34
+ all.push(el);
35
+ }
36
+ }
37
+ return all;
42
38
  }
43
39
  //# sourceMappingURL=snapshot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/extraction/snapshot.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,6EAA6E;AAC7E,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAE7C,MAAM,QAAQ,GACZ,yKAAyK,CAAC;AAE5K,MAAM,eAAe,GAAG;;;;;;;0CAOkB,QAAQ;uBAC3B,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;EAyBlC,CAAC;AAEH,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAU;IAC9C,OAAO,UAAU,CAAuB,IAAI,EAAE,eAAe,CAAC,CAAC;AACjE,CAAC"}
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/extraction/snapshot.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,0EAA0E;AAC1E,MAAM,YAAY,GAAG,GAAG,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAU;IAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAyB,EAAE,CAAC;IACrC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;QACpE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,UAAU,EAAE;YAAE,SAAS;QAC3C,IAAI,KAA2B,CAAC;QAChC,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,UAAU,CAAuB,KAAK,EAAE,eAAe,CAAC,CAAC;QACzE,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,GAAG,CAAC,MAAM,IAAI,YAAY;gBAAE,MAAM;YACtC,EAAE,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;YACzD,IAAI,CAAC,GAAG,CAAC;gBAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC;YACxB,EAAE,CAAC,KAAK,GAAG,MAAM,EAAE,CAAC;YACpB,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -36,6 +36,10 @@ export interface Challenges {
36
36
  /** An interactive element observed visually. Optional fields enrich snapshots. */
37
37
  export interface InteractiveElement {
38
38
  index: number;
39
+ /** Frame-scoped ref for targeting: `"<frame>:<local>"`, or `"<local>"` for the main frame. */
40
+ ref?: string;
41
+ /** Owning frame ordinal in `page.frames()` (omitted for the main frame). */
42
+ frame?: number;
39
43
  tag: string;
40
44
  text: string;
41
45
  role: string | null;
@@ -59,6 +63,13 @@ export interface InteractiveElement {
59
63
  ariaControls?: string | null;
60
64
  obscured?: boolean;
61
65
  }
66
+ /** A row harvested from a (possibly virtualized) list via scroll-collect. */
67
+ export interface CollectedItem {
68
+ key: string;
69
+ text: string;
70
+ url: string | null;
71
+ prices?: Price[];
72
+ }
62
73
  /** Visual observation (screenshot + interactive elements). */
63
74
  export interface Visual {
64
75
  screenshotPath?: string;
@@ -68,34 +79,5 @@ export interface Visual {
68
79
  };
69
80
  interactiveElements?: InteractiveElement[];
70
81
  }
71
- /** A single Google SERP entry (organic result or ad). */
72
- export interface SerpResult {
73
- position: number;
74
- title: string;
75
- url: string;
76
- displayUrl?: string;
77
- snippet?: string;
78
- }
79
- /** Where a domain ranks within a SERP. */
80
- export interface DomainRank {
81
- domain: string;
82
- organic: number[];
83
- ads: number[];
84
- best: number | null;
85
- found: boolean;
86
- }
87
- /** Parsed Google search results page. */
88
- export interface Serp {
89
- organic: SerpResult[];
90
- ads: SerpResult[];
91
- related: string[];
92
- rank?: DomainRank;
93
- }
94
- /** One query's outcome in a SERP batch. */
95
- export interface SerpBatchRow {
96
- query: string;
97
- rank?: DomainRank;
98
- results: SerpResult[];
99
- error?: string;
100
- }
82
+ export type { DomainRank, Serp, SerpBatchRow, SerpResult } from "./serp.js";
101
83
  //# sourceMappingURL=extraction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../../src/interfaces/extraction.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"extraction.d.ts","sourceRoot":"","sources":["../../src/interfaces/extraction.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,yCAAyC;AACzC,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,oDAAoD;AACpD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,kDAAkD;AAClD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACtD,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,SAAS,EAAE,UAAU,GAAG,IAAI,CAAC;CAC9B;AAED,2CAA2C;AAC3C,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,EAAE,OAAO,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;CACd;AAED,kFAAkF;AAClF,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,8FAA8F;IAC9F,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7D,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,6EAA6E;AAC7E,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;CAClB;AAED,8DAA8D;AAC9D,MAAM,WAAW,MAAM;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,mBAAmB,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAC5C;AAED,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Types for Google SERP parsing and rank tracking.
3
+ * @module interfaces/serp
4
+ */
5
+ /** A single Google SERP entry (organic result or ad). */
6
+ export interface SerpResult {
7
+ position: number;
8
+ title: string;
9
+ url: string;
10
+ displayUrl?: string;
11
+ snippet?: string;
12
+ }
13
+ /** Where a domain ranks within a SERP. */
14
+ export interface DomainRank {
15
+ domain: string;
16
+ organic: number[];
17
+ ads: number[];
18
+ best: number | null;
19
+ found: boolean;
20
+ }
21
+ /** Parsed Google search results page. */
22
+ export interface Serp {
23
+ organic: SerpResult[];
24
+ ads: SerpResult[];
25
+ related: string[];
26
+ rank?: DomainRank;
27
+ }
28
+ /** One query's outcome in a SERP batch. */
29
+ export interface SerpBatchRow {
30
+ query: string;
31
+ rank?: DomainRank;
32
+ results: SerpResult[];
33
+ error?: string;
34
+ }
35
+ //# sourceMappingURL=serp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serp.d.ts","sourceRoot":"","sources":["../../src/interfaces/serp.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,yDAAyD;AACzD,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,0CAA0C;AAC1C,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,GAAG,EAAE,MAAM,EAAE,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,yCAAyC;AACzC,MAAM,WAAW,IAAI;IACnB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,GAAG,EAAE,UAAU,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,UAAU,CAAC;CACnB;AAED,2CAA2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Types for Google SERP parsing and rank tracking.
3
+ * @module interfaces/serp
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=serp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serp.js","sourceRoot":"","sources":["../../src/interfaces/serp.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -9,9 +9,12 @@
9
9
  * `(arg) => {...}` scripts while staying isolated from Node DOM typing.
10
10
  * @module lib/evaluate
11
11
  */
12
- import type { Page } from "playwright";
12
+ import type { Frame, Page } from "playwright";
13
+ /** A context that can evaluate browser scripts — a page or one of its frames. */
14
+ type EvalTarget = Pick<Page, "evaluate"> | Pick<Frame, "evaluate">;
13
15
  /** Evaluate an arrow-function browser script with no argument; returns `R`. */
14
- export declare function evalScript<R>(page: Page, script: string): Promise<R>;
16
+ export declare function evalScript<R>(ctx: EvalTarget, script: string): Promise<R>;
15
17
  /** Evaluate an arrow-function browser script with one serializable argument. */
16
- export declare function evalScriptArg<R, A>(page: Page, script: string, arg: A): Promise<R>;
18
+ export declare function evalScriptArg<R, A>(ctx: EvalTarget, script: string, arg: A): Promise<R>;
19
+ export {};
17
20
  //# sourceMappingURL=evaluate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/lib/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAEpE;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAGlF"}
1
+ {"version":3,"file":"evaluate.d.ts","sourceRoot":"","sources":["../../src/lib/evaluate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAE9C,iFAAiF;AACjF,KAAK,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;AAEnE,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAEzE;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAGvF"}
@@ -1,10 +1,10 @@
1
1
  /** Evaluate an arrow-function browser script with no argument; returns `R`. */
2
- export function evalScript(page, script) {
3
- return page.evaluate(`(${script})()`);
2
+ export function evalScript(ctx, script) {
3
+ return ctx.evaluate(`(${script})()`);
4
4
  }
5
5
  /** Evaluate an arrow-function browser script with one serializable argument. */
6
- export function evalScriptArg(page, script, arg) {
6
+ export function evalScriptArg(ctx, script, arg) {
7
7
  const expression = `(${script})(${JSON.stringify(arg)})`;
8
- return page.evaluate(expression);
8
+ return ctx.evaluate(expression);
9
9
  }
10
10
  //# sourceMappingURL=evaluate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/lib/evaluate.ts"],"names":[],"mappings":"AAaA,+EAA+E;AAC/E,MAAM,UAAU,UAAU,CAAI,IAAU,EAAE,MAAc;IACtD,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,KAA2B,CAAC,CAAC;AAC9D,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAO,IAAU,EAAE,MAAc,EAAE,GAAM;IACpE,MAAM,UAAU,GAAG,IAAI,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;IACzD,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAgC,CAAC,CAAC;AACzD,CAAC"}
1
+ {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/lib/evaluate.ts"],"names":[],"mappings":"AAgBA,+EAA+E;AAC/E,MAAM,UAAU,UAAU,CAAI,GAAe,EAAE,MAAc;IAC3D,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,MAAM,KAA2B,CAAC,CAAC;AAC7D,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAO,GAAe,EAAE,MAAc,EAAE,GAAM;IACzE,MAAM,UAAU,GAAG,IAAI,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;IACzD,OAAO,GAAG,CAAC,QAAQ,CAAC,UAAgC,CAAC,CAAC;AACxD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgBvD,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,IAAI,WAAW,CAkB1C"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAiBvD,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,IAAI,WAAW,CAmB1C"}
@@ -7,6 +7,7 @@ import { VERSION } from "../lib/version.js";
7
7
  import { SessionManager } from "../session/manager.js";
8
8
  import { registerResources } from "./resources.js";
9
9
  import { registerActTools } from "./tools/act.js";
10
+ import { registerCollectTool } from "./tools/collect.js";
10
11
  import { registerConnectTool } from "./tools/connect.js";
11
12
  import { registerExtractTool } from "./tools/extract.js";
12
13
  import { registerExtractSchemaTool } from "./tools/extract-schema.js";
@@ -31,6 +32,7 @@ export function createServer() {
31
32
  registerNavigateTool(server, sessions);
32
33
  registerActTools(server, sessions);
33
34
  registerSnapshotTools(server, sessions);
35
+ registerCollectTool(server, sessions);
34
36
  registerWaitTool(server, sessions);
35
37
  registerRunTool(server, sessions);
36
38
  registerExtractTool(server, sessions);
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAQnD,6EAA6E;AAC7E,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IACtC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACxC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,yBAAyB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5C,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAQnD,6EAA6E;AAC7E,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IACtC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACxC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,yBAAyB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5C,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../../src/server/tools/act.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAwB/D,8CAA8C;AAC9C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAqDlF"}
1
+ {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../../src/server/tools/act.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAwB/D,8CAA8C;AAC9C,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAuDlF"}
@@ -23,10 +23,12 @@ export function registerActTools(server, sessions) {
23
23
  target: String(a.target),
24
24
  value: String(a.value),
25
25
  }));
26
- actTool(server, sessions, "browser_scroll", "Scroll the page by a pixel delta (positive deltaY scrolls down).", { sessionId, deltaY: z.number().optional(), deltaX: z.number().optional() }, (a) => ({
26
+ actTool(server, sessions, "browser_scroll", "Scroll by a pixel delta (positive deltaY scrolls down). Pass `selector` to scroll a specific scrollable container (auto-detected if omitted with `to`), or `to:\"end\"` to jump to its bottom.", { sessionId, deltaY: z.number().optional(), deltaX: z.number().optional(), selector: z.string().optional(), to: z.enum(["end"]).optional() }, (a) => ({
27
27
  type: "scroll",
28
28
  deltaY: a.deltaY ?? 600,
29
29
  deltaX: a.deltaX ?? 0,
30
+ selector: a.selector,
31
+ to: a.to,
30
32
  }));
31
33
  actTool(server, sessions, "browser_press", "Press a key or shortcut (Enter, ArrowDown, Control+a...).", { sessionId, key: z.string() }, (a) => ({
32
34
  type: "press",
@@ -1 +1 @@
1
- {"version":3,"file":"act.js","sourceRoot":"","sources":["../../../src/server/tools/act.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"act.js","sourceRoot":"","sources":["../../../src/server/tools/act.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `browser_collect` tool: exhaust a (virtualized/infinite) list by scrolling its
3
+ * container and merging the rows it mounts along the way — perception beyond the
4
+ * fold. Returns DATA (key/text/url/prices), not actionable refs: virtualization
5
+ * recycles nodes, so to act on a found row use browser_act by `target` text or
6
+ * browser_scroll(selector) then browser_snapshot.
7
+ * @module server/tools/collect
8
+ */
9
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ import type { SessionManager } from "../../session/manager.js";
11
+ /** Register `browser_collect`. */
12
+ export declare function registerCollectTool(server: McpServer, sessions: SessionManager): void;
13
+ //# sourceMappingURL=collect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../../src/server/tools/collect.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAI/D,kCAAkC;AAClC,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI,CAiCrF"}
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ import { scrollCollect } from "../../state/scroll-collect.js";
3
+ import { jsonResult } from "../result.js";
4
+ import { withSession } from "./with-session.js";
5
+ /** Register `browser_collect`. */
6
+ export function registerCollectTool(server, sessions) {
7
+ server.registerTool("browser_collect", {
8
+ title: "Collect a scrolling list",
9
+ description: "Scroll a (virtualized/infinite) list and return the deduped union of its rows — items beyond the first screen that a single snapshot misses (hotel/flight results, feeds). `item` is the CSS selector for one row; `container` is optional (auto-detected otherwise). Returns data (key/text/url, optional prices), NOT refs — to act on a row, use browser_act by text.",
10
+ inputSchema: {
11
+ sessionId: z.string(),
12
+ item: z.string(),
13
+ container: z.string().optional(),
14
+ maxSteps: z.number().int().optional(),
15
+ extractPrices: z.boolean().optional(),
16
+ },
17
+ }, async (args) => {
18
+ const a = args;
19
+ return withSession(sessions, String(a.sessionId), async (s) => {
20
+ const result = await scrollCollect(s.page, {
21
+ item: String(a.item),
22
+ container: typeof a.container === "string" ? a.container : undefined,
23
+ maxSteps: typeof a.maxSteps === "number" ? a.maxSteps : undefined,
24
+ extractPrices: a.extractPrices === true,
25
+ });
26
+ return jsonResult({
27
+ count: result.items.length,
28
+ steps: result.steps,
29
+ reachedEnd: result.reachedEnd,
30
+ items: result.items,
31
+ });
32
+ });
33
+ });
34
+ }
35
+ //# sourceMappingURL=collect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.js","sourceRoot":"","sources":["../../../src/server/tools/collect.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,kCAAkC;AAClC,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,QAAwB;IAC7E,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,KAAK,EAAE,0BAA0B;QACjC,WAAW,EACT,0WAA0W;QAC5W,WAAW,EAAE;YACX,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;YACrB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;YAChB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAChC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;YACrC,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;SACtC;KACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,CAAC,GAAG,IAA+B,CAAC;QAC1C,OAAO,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;YAC5D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE;gBACzC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;gBACpB,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;gBACpE,QAAQ,EAAE,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;gBACjE,aAAa,EAAE,CAAC,CAAC,aAAa,KAAK,IAAI;aACxC,CAAC,CAAC;YACH,OAAO,UAAU,CAAC;gBAChB,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM;gBAC1B,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,UAAU,EAAE,MAAM,CAAC,UAAU;gBAC7B,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { z } from "zod";
2
- import { REF_ATTRIBUTE } from "../../extraction/snapshot.js";
2
+ import { refLocator } from "../../actions/ref-locator.js";
3
3
  import { resolveViewport, viewportLabel } from "../../engine/viewport.js";
4
4
  import { settleForCapture } from "../../state/settle-capture.js";
5
5
  import { errorResult, imageResult, multiImageResult } from "../result.js";
@@ -16,16 +16,16 @@ export function registerScreenshotTool(server, sessions) {
16
16
  inputSchema: {
17
17
  sessionId: z.string(),
18
18
  fullPage: z.boolean().optional(),
19
- ref: z.number().int().optional(),
19
+ ref: z.union([z.number().int(), z.string()]).optional(),
20
20
  viewport: VIEWPORT_SCHEMA.optional(),
21
21
  viewports: z.array(VIEWPORT_SCHEMA).optional(),
22
22
  },
23
23
  }, async (args) => {
24
24
  const a = args;
25
25
  return withSession(sessions, String(a.sessionId), async (s) => {
26
- if (typeof a.ref === "number") {
27
- const locator = s.page.locator(`[${REF_ATTRIBUTE}="${a.ref}"]`).first();
28
- if ((await locator.count()) === 0)
26
+ if (typeof a.ref === "number" || typeof a.ref === "string") {
27
+ const locator = refLocator(s.page, a.ref);
28
+ if (!locator || (await locator.count()) === 0)
29
29
  return errorResult("ref_not_found");
30
30
  const buf = await locator.screenshot({ timeout: 5_000 });
31
31
  return imageResult(buf.toString("base64"), `element ref=${a.ref}`);
@@ -1 +1 @@
1
- {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../../src/server/tools/screenshot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../../src/server/tools/screenshot.ts"],"names":[],"mappings":"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"}
@@ -13,7 +13,7 @@ async function runAct(page, a, human) {
13
13
  const kind = a.kind;
14
14
  const value = a.value ? String(a.value) : "";
15
15
  const option = a.option ? String(a.option) : "";
16
- if (typeof a.ref === "number")
16
+ if (typeof a.ref === "number" || typeof a.ref === "string")
17
17
  return actByRef(page, a.ref, kind, value, option);
18
18
  if (typeof a.target !== "string")
19
19
  return null;
@@ -27,7 +27,7 @@ async function runAct(page, a, human) {
27
27
  export function registerSnapshotTools(server, sessions) {
28
28
  server.registerTool("browser_snapshot", {
29
29
  title: "Snapshot",
30
- description: "Return the indexed interactive elements of the live page. Each element gets a stable `ref` to use with browser_act for deterministic targeting.",
30
+ description: "Return the indexed interactive elements of the live page, including those inside open Shadow DOM and iframes (same- and cross-origin). Use each element's `ref` (e.g. \"12\" or \"3:4\" for a sub-frame) with browser_act for deterministic targeting.",
31
31
  inputSchema: { sessionId: z.string() },
32
32
  }, async (args) => {
33
33
  const a = args;
@@ -42,7 +42,7 @@ export function registerSnapshotTools(server, sessions) {
42
42
  inputSchema: {
43
43
  sessionId: z.string(),
44
44
  kind: KIND,
45
- ref: z.number().int().optional(),
45
+ ref: z.union([z.number().int(), z.string()]).optional(),
46
46
  target: z.string().optional(),
47
47
  value: z.string().optional(),
48
48
  option: z.string().optional(),
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../src/server/tools/snapshot.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../src/server/tools/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Scroll-and-collect loop for virtualized/infinite lists: repeatedly harvest the
3
+ * mounted rows, scroll the container one step, settle, and merge until the
4
+ * container stops growing (K stable rounds) or refuses to advance (true bottom)
5
+ * or a step cap is hit. Returns the deduped union of rows seen.
6
+ * @module state/scroll-collect
7
+ */
8
+ import type { Page } from "playwright";
9
+ import type { CollectedItem } from "../interfaces/extraction.js";
10
+ /** Options for {@link scrollCollect}. */
11
+ export interface CollectOptions {
12
+ item: string;
13
+ container?: string;
14
+ maxSteps?: number;
15
+ stableRounds?: number;
16
+ extractPrices?: boolean;
17
+ settleMs?: number;
18
+ }
19
+ /** Result of a scroll-collect run. */
20
+ export interface CollectResult {
21
+ items: CollectedItem[];
22
+ steps: number;
23
+ reachedEnd: boolean;
24
+ }
25
+ /** Exhaust a (virtualized) list by scrolling its container and merging rows. */
26
+ export declare function scrollCollect(page: Page, opts: CollectOptions): Promise<CollectResult>;
27
+ //# sourceMappingURL=scroll-collect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-collect.d.ts","sourceRoot":"","sources":["../../src/state/scroll-collect.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAIvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAGjE,yCAAyC;AACzC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,sCAAsC;AACtC,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,OAAO,CAAC;CACrB;AAOD,gFAAgF;AAChF,wBAAsB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA2B5F"}
@@ -0,0 +1,34 @@
1
+ import { mergeItems } from "../extraction/collect-merge.js";
2
+ import { extractPrices } from "../extraction/prices.js";
3
+ import { SCAN_SCRIPT } from "../extraction/scroll-script.js";
4
+ import { evalScriptArg } from "../lib/evaluate.js";
5
+ /** Exhaust a (virtualized) list by scrolling its container and merging rows. */
6
+ export async function scrollCollect(page, opts) {
7
+ const maxSteps = opts.maxSteps ?? 60;
8
+ const need = opts.stableRounds ?? 3;
9
+ const arg = { item: opts.item, selector: opts.container ?? null, stepFraction: 0.9 };
10
+ const pricer = opts.extractPrices ? extractPrices : null;
11
+ const seen = new Map();
12
+ let stable = 0;
13
+ let prevH = 0;
14
+ let reachedEnd = false;
15
+ let steps = 0;
16
+ for (; steps < maxSteps; steps++) {
17
+ const out = await evalScriptArg(page, SCAN_SCRIPT, arg);
18
+ const added = mergeItems(seen, out.items, pricer);
19
+ const grew = out.geo.scrollHeight > prevH + 4;
20
+ prevH = out.geo.scrollHeight;
21
+ if (out.geo.moved < 2) {
22
+ reachedEnd = true;
23
+ break;
24
+ }
25
+ stable = !grew && added === 0 ? stable + 1 : 0;
26
+ if (stable >= need) {
27
+ reachedEnd = out.geo.atEnd;
28
+ break;
29
+ }
30
+ await page.waitForTimeout(opts.settleMs ?? 150);
31
+ }
32
+ return { items: [...seen.values()], steps: steps + 1, reachedEnd };
33
+ }
34
+ //# sourceMappingURL=scroll-collect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scroll-collect.js","sourceRoot":"","sources":["../../src/state/scroll-collect.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,UAAU,EAAe,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAE7D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAwBnD,gFAAgF;AAChF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAU,EAAE,IAAoB;IAClE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC;IACpC,MAAM,GAAG,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC;IACrF,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;IACzD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC9C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,KAAK,GAAG,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,MAAM,aAAa,CAAsB,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QAC7E,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClD,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,YAAY,GAAG,KAAK,GAAG,CAAC,CAAC;QAC9C,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC;QAC7B,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YACtB,UAAU,GAAG,IAAI,CAAC;YAClB,MAAM;QACR,CAAC;QACD,MAAM,GAAG,CAAC,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/C,IAAI,MAAM,IAAI,IAAI,EAAE,CAAC;YACnB,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC;YAC3B,MAAM;QACR,CAAC;QACD,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,EAAE,UAAU,EAAE,CAAC;AACrE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/browser-mcp",
3
- "version": "0.1.14",
3
+ "version": "0.1.16",
4
4
  "description": "MCP server + CLI giving AI agents a real, stealth browser (Patchright/Playwright) — per-country identity, self-healing actions, snapshots, multi-step plans, structured extraction, CDP attach.",
5
5
  "license": "MIT",
6
6
  "author": "Fusengine",
@@ -54,7 +54,7 @@
54
54
  "build": "tsc -p tsconfig.json",
55
55
  "typecheck": "tsc -p tsconfig.json --noEmit",
56
56
  "test": "bun test tests/unit",
57
- "test:integration": "node --test --import tsx tests/integration/mcp.test.ts tests/integration/probe.test.ts tests/integration/snapshot.test.ts tests/integration/run.test.ts tests/integration/extract-schema.test.ts",
57
+ "test:integration": "node --test --import tsx tests/integration/mcp.test.ts tests/integration/probe.test.ts tests/integration/snapshot.test.ts tests/integration/snapshot-frames.test.ts tests/integration/collect.test.ts tests/integration/run.test.ts tests/integration/extract-schema.test.ts",
58
58
  "browsers": "patchright install chromium",
59
59
  "mcp": "node --import tsx src/bin/mcp.ts",
60
60
  "cli": "node --import tsx src/bin/cli.ts"