@fusengine/browser-mcp 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/actions/act-by-ref.d.ts +2 -2
- package/dist/actions/act-by-ref.d.ts.map +1 -1
- package/dist/actions/act-by-ref.js +4 -5
- package/dist/actions/act-by-ref.js.map +1 -1
- package/dist/actions/ref-locator.d.ts +17 -0
- package/dist/actions/ref-locator.d.ts.map +1 -0
- package/dist/actions/ref-locator.js +18 -0
- package/dist/actions/ref-locator.js.map +1 -0
- package/dist/extraction/snapshot-walk.d.ts +18 -0
- package/dist/extraction/snapshot-walk.d.ts.map +1 -0
- package/dist/extraction/snapshot-walk.js +61 -0
- package/dist/extraction/snapshot-walk.js.map +1 -0
- package/dist/extraction/snapshot.d.ts +12 -6
- package/dist/extraction/snapshot.d.ts.map +1 -1
- package/dist/extraction/snapshot.js +35 -39
- package/dist/extraction/snapshot.js.map +1 -1
- package/dist/interfaces/extraction.d.ts +5 -30
- package/dist/interfaces/extraction.d.ts.map +1 -1
- package/dist/interfaces/serp.d.ts +35 -0
- package/dist/interfaces/serp.d.ts.map +1 -0
- package/dist/interfaces/serp.js +6 -0
- package/dist/interfaces/serp.js.map +1 -0
- package/dist/lib/evaluate.d.ts +6 -3
- package/dist/lib/evaluate.d.ts.map +1 -1
- package/dist/lib/evaluate.js +4 -4
- package/dist/lib/evaluate.js.map +1 -1
- package/dist/server/tools/screenshot.js +5 -5
- package/dist/server/tools/screenshot.js.map +1 -1
- package/dist/server/tools/snapshot.js +3 -3
- package/dist/server/tools/snapshot.js.map +1 -1
- 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
|
|
@@ -146,7 +150,10 @@ 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.
|
|
152
159
|
- **`browser_run`** — execute an ordered plan (navigate/act/wait/extract) in one call,
|
|
@@ -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 `
|
|
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,
|
|
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
|
-
|
|
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
|
|
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,
|
|
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"}
|
|
@@ -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,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
|
-
*
|
|
5
|
-
*
|
|
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
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
|
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
|
-
|
|
3
|
-
export
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
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":"
|
|
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;
|
|
@@ -68,34 +72,5 @@ export interface Visual {
|
|
|
68
72
|
};
|
|
69
73
|
interactiveElements?: InteractiveElement[];
|
|
70
74
|
}
|
|
71
|
-
|
|
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
|
-
}
|
|
75
|
+
export type { DomainRank, Serp, SerpBatchRow, SerpResult } from "./serp.js";
|
|
101
76
|
//# sourceMappingURL=extraction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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,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,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,
|
|
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,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 @@
|
|
|
1
|
+
{"version":3,"file":"serp.js","sourceRoot":"","sources":["../../src/interfaces/serp.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/dist/lib/evaluate.d.ts
CHANGED
|
@@ -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>(
|
|
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>(
|
|
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;
|
|
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"}
|
package/dist/lib/evaluate.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/** Evaluate an arrow-function browser script with no argument; returns `R`. */
|
|
2
|
-
export function evalScript(
|
|
3
|
-
return
|
|
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(
|
|
6
|
+
export function evalScriptArg(ctx, script, arg) {
|
|
7
7
|
const expression = `(${script})(${JSON.stringify(arg)})`;
|
|
8
|
-
return
|
|
8
|
+
return ctx.evaluate(expression);
|
|
9
9
|
}
|
|
10
10
|
//# sourceMappingURL=evaluate.js.map
|
package/dist/lib/evaluate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../src/lib/evaluate.ts"],"names":[],"mappings":"
|
|
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,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
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
|
|
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":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,
|
|
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
|
|
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":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAsB,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAEzD,uDAAuD;AACvD,KAAK,UAAU,MAAM,CAAC,IAAU,EAAE,CAA0B,EAAE,KAAc;IAC1E,MAAM,IAAI,GAAG,CAAC,CAAC,IAAqB,CAAC;IACrC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../../src/server/tools/snapshot.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAsB,MAAM,6BAA6B,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAEzD,uDAAuD;AACvD,KAAK,UAAU,MAAM,CAAC,IAAU,EAAE,CAA0B,EAAE,KAAc;IAC1E,MAAM,IAAI,GAAG,CAAC,CAAC,IAAqB,CAAC;IACrC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAChD,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAC9G,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC9C,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IAClG,OAAO,IAAI,KAAK,MAAM;QACpB,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC;QAC7C,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;AAC5C,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,QAAwB;IAC/E,MAAM,CAAC,YAAY,CACjB,kBAAkB,EAClB;QACE,KAAK,EAAE,UAAU;QACjB,WAAW,EACT,wPAAwP;QAC1P,WAAW,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE;KACvC,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,QAAQ,GAAG,MAAM,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC/C,OAAO,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,YAAY,CACjB,aAAa,EACb;QACE,KAAK,EAAE,gBAAgB;QACvB,WAAW,EACT,oRAAoR;QACtR,WAAW,EAAE;YACX,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;YACrB,IAAI,EAAE,IAAI;YACV,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;YACvD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAC9B;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,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC7C,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC3D,IAAI,CAAC,MAAM;gBAAE,OAAO,WAAW,CAAC,+CAA+C,CAAC,CAAC;YACjF,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YAC5C,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC;YACtE,OAAO,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusengine/browser-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
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/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"
|