@fusengine/browser-mcp 0.1.0
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/LICENSE +21 -0
- package/README.md +175 -0
- package/dist/actions/act-by-ref.d.ts +13 -0
- package/dist/actions/act-by-ref.d.ts.map +1 -0
- package/dist/actions/act-by-ref.js +25 -0
- package/dist/actions/act-by-ref.js.map +1 -0
- package/dist/actions/human.d.ts +8 -0
- package/dist/actions/human.d.ts.map +1 -0
- package/dist/actions/human.js +6 -0
- package/dist/actions/human.js.map +1 -0
- package/dist/actions/login.d.ts +17 -0
- package/dist/actions/login.d.ts.map +1 -0
- package/dist/actions/login.js +11 -0
- package/dist/actions/login.js.map +1 -0
- package/dist/actions/navigation.d.ts +15 -0
- package/dist/actions/navigation.d.ts.map +1 -0
- package/dist/actions/navigation.js +33 -0
- package/dist/actions/navigation.js.map +1 -0
- package/dist/actions/perform.d.ts +15 -0
- package/dist/actions/perform.d.ts.map +1 -0
- package/dist/actions/perform.js +41 -0
- package/dist/actions/perform.js.map +1 -0
- package/dist/actions/smart-click.d.ts +9 -0
- package/dist/actions/smart-click.d.ts.map +1 -0
- package/dist/actions/smart-click.js +55 -0
- package/dist/actions/smart-click.js.map +1 -0
- package/dist/actions/smart-fill.d.ts +9 -0
- package/dist/actions/smart-fill.d.ts.map +1 -0
- package/dist/actions/smart-fill.js +46 -0
- package/dist/actions/smart-fill.js.map +1 -0
- package/dist/actions/wait-for.d.ts +21 -0
- package/dist/actions/wait-for.d.ts.map +1 -0
- package/dist/actions/wait-for.js +28 -0
- package/dist/actions/wait-for.js.map +1 -0
- package/dist/agent/actions-loop.d.ts +18 -0
- package/dist/agent/actions-loop.d.ts.map +1 -0
- package/dist/agent/actions-loop.js +44 -0
- package/dist/agent/actions-loop.js.map +1 -0
- package/dist/agent/browser-agent.d.ts +24 -0
- package/dist/agent/browser-agent.d.ts.map +1 -0
- package/dist/agent/browser-agent.js +36 -0
- package/dist/agent/browser-agent.js.map +1 -0
- package/dist/agent/compact.d.ts +8 -0
- package/dist/agent/compact.d.ts.map +1 -0
- package/dist/agent/compact.js +24 -0
- package/dist/agent/compact.js.map +1 -0
- package/dist/agent/config.d.ts +30 -0
- package/dist/agent/config.d.ts.map +1 -0
- package/dist/agent/config.js +49 -0
- package/dist/agent/config.js.map +1 -0
- package/dist/agent/detect.d.ts +17 -0
- package/dist/agent/detect.d.ts.map +1 -0
- package/dist/agent/detect.js +9 -0
- package/dist/agent/detect.js.map +1 -0
- package/dist/agent/network.d.ts +16 -0
- package/dist/agent/network.d.ts.map +1 -0
- package/dist/agent/network.js +16 -0
- package/dist/agent/network.js.map +1 -0
- package/dist/agent/probe-run.d.ts +6 -0
- package/dist/agent/probe-run.d.ts.map +1 -0
- package/dist/agent/probe-run.js +90 -0
- package/dist/agent/probe-run.js.map +1 -0
- package/dist/agent/report.d.ts +29 -0
- package/dist/agent/report.d.ts.map +1 -0
- package/dist/agent/report.js +53 -0
- package/dist/agent/report.js.map +1 -0
- package/dist/agent/run-steps.d.ts +22 -0
- package/dist/agent/run-steps.d.ts.map +1 -0
- package/dist/agent/run-steps.js +59 -0
- package/dist/agent/run-steps.js.map +1 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +84 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/mcp.d.ts +3 -0
- package/dist/bin/mcp.d.ts.map +1 -0
- package/dist/bin/mcp.js +28 -0
- package/dist/bin/mcp.js.map +1 -0
- package/dist/captcha/solve.d.ts +17 -0
- package/dist/captcha/solve.d.ts.map +1 -0
- package/dist/captcha/solve.js +42 -0
- package/dist/captcha/solve.js.map +1 -0
- package/dist/consent/booking-currency.d.ts +14 -0
- package/dist/consent/booking-currency.d.ts.map +1 -0
- package/dist/consent/booking-currency.js +82 -0
- package/dist/consent/booking-currency.js.map +1 -0
- package/dist/consent/consent.d.ts +11 -0
- package/dist/consent/consent.d.ts.map +1 -0
- package/dist/consent/consent.js +27 -0
- package/dist/consent/consent.js.map +1 -0
- package/dist/consent/currency-url.d.ts +10 -0
- package/dist/consent/currency-url.d.ts.map +1 -0
- package/dist/consent/currency-url.js +18 -0
- package/dist/consent/currency-url.js.map +1 -0
- package/dist/consent/currency.d.ts +14 -0
- package/dist/consent/currency.d.ts.map +1 -0
- package/dist/consent/currency.js +48 -0
- package/dist/consent/currency.js.map +1 -0
- package/dist/engine/cdp-engine.d.ts +21 -0
- package/dist/engine/cdp-engine.d.ts.map +1 -0
- package/dist/engine/cdp-engine.js +36 -0
- package/dist/engine/cdp-engine.js.map +1 -0
- package/dist/engine/cdp-launch.d.ts +11 -0
- package/dist/engine/cdp-launch.d.ts.map +1 -0
- package/dist/engine/cdp-launch.js +54 -0
- package/dist/engine/cdp-launch.js.map +1 -0
- package/dist/engine/context.d.ts +14 -0
- package/dist/engine/context.d.ts.map +1 -0
- package/dist/engine/context.js +22 -0
- package/dist/engine/context.js.map +1 -0
- package/dist/engine/launch.d.ts +6 -0
- package/dist/engine/launch.d.ts.map +1 -0
- package/dist/engine/launch.js +53 -0
- package/dist/engine/launch.js.map +1 -0
- package/dist/engine/loader.d.ts +13 -0
- package/dist/engine/loader.d.ts.map +1 -0
- package/dist/engine/loader.js +24 -0
- package/dist/engine/loader.js.map +1 -0
- package/dist/engine/patchright-engine.d.ts +4 -0
- package/dist/engine/patchright-engine.d.ts.map +1 -0
- package/dist/engine/patchright-engine.js +10 -0
- package/dist/engine/patchright-engine.js.map +1 -0
- package/dist/engine/playwright-engine.d.ts +8 -0
- package/dist/engine/playwright-engine.d.ts.map +1 -0
- package/dist/engine/playwright-engine.js +24 -0
- package/dist/engine/playwright-engine.js.map +1 -0
- package/dist/engine/registry.d.ts +13 -0
- package/dist/engine/registry.d.ts.map +1 -0
- package/dist/engine/registry.js +18 -0
- package/dist/engine/registry.js.map +1 -0
- package/dist/extraction/challenges.d.ts +9 -0
- package/dist/extraction/challenges.d.ts.map +1 -0
- package/dist/extraction/challenges.js +24 -0
- package/dist/extraction/challenges.js.map +1 -0
- package/dist/extraction/hotel-offers.d.ts +11 -0
- package/dist/extraction/hotel-offers.d.ts.map +1 -0
- package/dist/extraction/hotel-offers.js +63 -0
- package/dist/extraction/hotel-offers.js.map +1 -0
- package/dist/extraction/main-text.d.ts +13 -0
- package/dist/extraction/main-text.d.ts.map +1 -0
- package/dist/extraction/main-text.js +20 -0
- package/dist/extraction/main-text.js.map +1 -0
- package/dist/extraction/prices.d.ts +18 -0
- package/dist/extraction/prices.d.ts.map +1 -0
- package/dist/extraction/prices.js +74 -0
- package/dist/extraction/prices.js.map +1 -0
- package/dist/extraction/snapshot-diff.d.ts +28 -0
- package/dist/extraction/snapshot-diff.d.ts.map +1 -0
- package/dist/extraction/snapshot-diff.js +30 -0
- package/dist/extraction/snapshot-diff.js.map +1 -0
- package/dist/extraction/snapshot.d.ts +14 -0
- package/dist/extraction/snapshot.d.ts.map +1 -0
- package/dist/extraction/snapshot.js +26 -0
- package/dist/extraction/snapshot.js.map +1 -0
- package/dist/extraction/structured.d.ts +26 -0
- package/dist/extraction/structured.d.ts.map +1 -0
- package/dist/extraction/structured.js +28 -0
- package/dist/extraction/structured.js.map +1 -0
- package/dist/extraction/visual.d.ts +9 -0
- package/dist/extraction/visual.d.ts.map +1 -0
- package/dist/extraction/visual.js +29 -0
- package/dist/extraction/visual.js.map +1 -0
- package/dist/guardrails/preflight.d.ts +25 -0
- package/dist/guardrails/preflight.d.ts.map +1 -0
- package/dist/guardrails/preflight.js +27 -0
- package/dist/guardrails/preflight.js.map +1 -0
- package/dist/identity/country-profiles.d.ts +12 -0
- package/dist/identity/country-profiles.d.ts.map +1 -0
- package/dist/identity/country-profiles.js +58 -0
- package/dist/identity/country-profiles.js.map +1 -0
- package/dist/identity/identity.d.ts +19 -0
- package/dist/identity/identity.d.ts.map +1 -0
- package/dist/identity/identity.js +31 -0
- package/dist/identity/identity.js.map +1 -0
- package/dist/identity/resolve.d.ts +25 -0
- package/dist/identity/resolve.d.ts.map +1 -0
- package/dist/identity/resolve.js +21 -0
- package/dist/identity/resolve.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/engine-types.d.ts +15 -0
- package/dist/interfaces/engine-types.d.ts.map +1 -0
- package/dist/interfaces/engine-types.js +6 -0
- package/dist/interfaces/engine-types.js.map +1 -0
- package/dist/interfaces/engine.d.ts +30 -0
- package/dist/interfaces/engine.d.ts.map +1 -0
- package/dist/interfaces/engine.js +2 -0
- package/dist/interfaces/engine.js.map +1 -0
- package/dist/interfaces/extraction.d.ts +63 -0
- package/dist/interfaces/extraction.d.ts.map +1 -0
- package/dist/interfaces/extraction.js +6 -0
- package/dist/interfaces/extraction.js.map +1 -0
- package/dist/interfaces/net.d.ts +48 -0
- package/dist/interfaces/net.d.ts.map +1 -0
- package/dist/interfaces/net.js +6 -0
- package/dist/interfaces/net.js.map +1 -0
- package/dist/interfaces/report.d.ts +87 -0
- package/dist/interfaces/report.d.ts.map +1 -0
- package/dist/interfaces/report.js +2 -0
- package/dist/interfaces/report.js.map +1 -0
- package/dist/interfaces/types.d.ts +90 -0
- package/dist/interfaces/types.d.ts.map +1 -0
- package/dist/interfaces/types.js +6 -0
- package/dist/interfaces/types.js.map +1 -0
- package/dist/lib/errors.d.ts +19 -0
- package/dist/lib/errors.d.ts.map +1 -0
- package/dist/lib/errors.js +30 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/evaluate.d.ts +17 -0
- package/dist/lib/evaluate.d.ts.map +1 -0
- package/dist/lib/evaluate.js +10 -0
- package/dist/lib/evaluate.js.map +1 -0
- package/dist/lib/fs.d.ts +11 -0
- package/dist/lib/fs.d.ts.map +1 -0
- package/dist/lib/fs.js +34 -0
- package/dist/lib/fs.js.map +1 -0
- package/dist/lib/logger.d.ts +14 -0
- package/dist/lib/logger.d.ts.map +1 -0
- package/dist/lib/logger.js +22 -0
- package/dist/lib/logger.js.map +1 -0
- package/dist/lib/output-dir.d.ts +12 -0
- package/dist/lib/output-dir.d.ts.map +1 -0
- package/dist/lib/output-dir.js +37 -0
- package/dist/lib/output-dir.js.map +1 -0
- package/dist/lib/retry.d.ts +28 -0
- package/dist/lib/retry.d.ts.map +1 -0
- package/dist/lib/retry.js +41 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/lib/text.d.ts +9 -0
- package/dist/lib/text.d.ts.map +1 -0
- package/dist/lib/text.js +13 -0
- package/dist/lib/text.js.map +1 -0
- package/dist/net/captcha-client.d.ts +10 -0
- package/dist/net/captcha-client.d.ts.map +1 -0
- package/dist/net/captcha-client.js +48 -0
- package/dist/net/captcha-client.js.map +1 -0
- package/dist/net/captcha-inject.d.ts +10 -0
- package/dist/net/captcha-inject.d.ts.map +1 -0
- package/dist/net/captcha-inject.js +24 -0
- package/dist/net/captcha-inject.js.map +1 -0
- package/dist/net/navigate.d.ts +19 -0
- package/dist/net/navigate.d.ts.map +1 -0
- package/dist/net/navigate.js +32 -0
- package/dist/net/navigate.js.map +1 -0
- package/dist/net/throttle.d.ts +3 -0
- package/dist/net/throttle.d.ts.map +1 -0
- package/dist/net/throttle.js +23 -0
- package/dist/net/throttle.js.map +1 -0
- package/dist/proxy/country-map.d.ts +13 -0
- package/dist/proxy/country-map.d.ts.map +1 -0
- package/dist/proxy/country-map.js +38 -0
- package/dist/proxy/country-map.js.map +1 -0
- package/dist/server/env-defaults.d.ts +11 -0
- package/dist/server/env-defaults.d.ts.map +1 -0
- package/dist/server/env-defaults.js +20 -0
- package/dist/server/env-defaults.js.map +1 -0
- package/dist/server/map-options.d.ts +6 -0
- package/dist/server/map-options.d.ts.map +1 -0
- package/dist/server/map-options.js +43 -0
- package/dist/server/map-options.js.map +1 -0
- package/dist/server/resources.d.ts +4 -0
- package/dist/server/resources.d.ts.map +1 -0
- package/dist/server/resources.js +28 -0
- package/dist/server/resources.js.map +1 -0
- package/dist/server/result.d.ts +12 -0
- package/dist/server/result.d.ts.map +1 -0
- package/dist/server/result.js +18 -0
- package/dist/server/result.js.map +1 -0
- package/dist/server/schemas.d.ts +191 -0
- package/dist/server/schemas.d.ts.map +1 -0
- package/dist/server/schemas.js +72 -0
- package/dist/server/schemas.js.map +1 -0
- package/dist/server/server.d.ts +14 -0
- package/dist/server/server.d.ts.map +1 -0
- package/dist/server/server.js +37 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/tools/act.d.ts +10 -0
- package/dist/server/tools/act.d.ts.map +1 -0
- package/dist/server/tools/act.js +62 -0
- package/dist/server/tools/act.js.map +1 -0
- package/dist/server/tools/connect.d.ts +10 -0
- package/dist/server/tools/connect.d.ts.map +1 -0
- package/dist/server/tools/connect.js +37 -0
- package/dist/server/tools/connect.js.map +1 -0
- package/dist/server/tools/extract-schema.d.ts +9 -0
- package/dist/server/tools/extract-schema.d.ts.map +1 -0
- package/dist/server/tools/extract-schema.js +29 -0
- package/dist/server/tools/extract-schema.js.map +1 -0
- package/dist/server/tools/extract.d.ts +9 -0
- package/dist/server/tools/extract.d.ts.map +1 -0
- package/dist/server/tools/extract.js +35 -0
- package/dist/server/tools/extract.js.map +1 -0
- package/dist/server/tools/navigate.d.ts +9 -0
- package/dist/server/tools/navigate.d.ts.map +1 -0
- package/dist/server/tools/navigate.js +27 -0
- package/dist/server/tools/navigate.js.map +1 -0
- package/dist/server/tools/probe.d.ts +8 -0
- package/dist/server/tools/probe.d.ts.map +1 -0
- package/dist/server/tools/probe.js +44 -0
- package/dist/server/tools/probe.js.map +1 -0
- package/dist/server/tools/run.d.ts +10 -0
- package/dist/server/tools/run.d.ts.map +1 -0
- package/dist/server/tools/run.js +30 -0
- package/dist/server/tools/run.js.map +1 -0
- package/dist/server/tools/screenshot.d.ts +10 -0
- package/dist/server/tools/screenshot.d.ts.map +1 -0
- package/dist/server/tools/screenshot.js +26 -0
- package/dist/server/tools/screenshot.js.map +1 -0
- package/dist/server/tools/session.d.ts +9 -0
- package/dist/server/tools/session.d.ts.map +1 -0
- package/dist/server/tools/session.js +33 -0
- package/dist/server/tools/session.js.map +1 -0
- package/dist/server/tools/snapshot.d.ts +12 -0
- package/dist/server/tools/snapshot.d.ts.map +1 -0
- package/dist/server/tools/snapshot.js +59 -0
- package/dist/server/tools/snapshot.js.map +1 -0
- package/dist/server/tools/wait.d.ts +9 -0
- package/dist/server/tools/wait.d.ts.map +1 -0
- package/dist/server/tools/wait.js +32 -0
- package/dist/server/tools/wait.js.map +1 -0
- package/dist/server/tools/with-session.d.ts +10 -0
- package/dist/server/tools/with-session.d.ts.map +1 -0
- package/dist/server/tools/with-session.js +16 -0
- package/dist/server/tools/with-session.js.map +1 -0
- package/dist/session/manager.d.ts +39 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +76 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/session.d.ts +28 -0
- package/dist/session/session.d.ts.map +1 -0
- package/dist/session/session.js +51 -0
- package/dist/session/session.js.map +1 -0
- package/dist/state/dom-signature.d.ts +8 -0
- package/dist/state/dom-signature.d.ts.map +1 -0
- package/dist/state/dom-signature.js +13 -0
- package/dist/state/dom-signature.js.map +1 -0
- package/dist/state/realtime.d.ts +11 -0
- package/dist/state/realtime.d.ts.map +1 -0
- package/dist/state/realtime.js +34 -0
- package/dist/state/realtime.js.map +1 -0
- package/dist/state/replay.d.ts +4 -0
- package/dist/state/replay.d.ts.map +1 -0
- package/dist/state/replay.js +21 -0
- package/dist/state/replay.js.map +1 -0
- package/dist/state/site-memory.d.ts +35 -0
- package/dist/state/site-memory.d.ts.map +1 -0
- package/dist/state/site-memory.js +56 -0
- package/dist/state/site-memory.js.map +1 -0
- package/package.json +70 -0
- package/proxies.example.json +9 -0
- package/scripts/postinstall.mjs +24 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Default macOS binary paths for common Chromium browsers. */
|
|
2
|
+
export declare const KNOWN_BROWSERS: Record<string, string>;
|
|
3
|
+
/**
|
|
4
|
+
* Spawn a browser binary with remote debugging, fully detached from the parent.
|
|
5
|
+
* Runs without a shell (no shell injection); `binary`/`userDataDir` are passed
|
|
6
|
+
* as native argv. The opened debug port is a local attack surface (see module).
|
|
7
|
+
*/
|
|
8
|
+
export declare function spawnBrowser(binary: string, port: number, userDataDir?: string): void;
|
|
9
|
+
/** Poll http://localhost:PORT/json/version until it responds or retries run out. */
|
|
10
|
+
export declare function waitForCdp(port: number, retries?: number, intervalMs?: number): Promise<string>;
|
|
11
|
+
//# sourceMappingURL=cdp-launch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdp-launch.d.ts","sourceRoot":"","sources":["../../src/engine/cdp-launch.ts"],"names":[],"mappings":"AAcA,+DAA+D;AAC/D,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAMjD,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAMrF;AAED,oFAAoF;AACpF,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,SAAK,EAAE,UAAU,SAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAe9F"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Launch an installed browser with a remote-debugging port, detached, then
|
|
3
|
+
* poll its CDP endpoint until ready. Powers `browser_connect` so an agent can
|
|
4
|
+
* attach to the user's real browser (Chrome/Edge/Dia/Arc) without manual setup.
|
|
5
|
+
*
|
|
6
|
+
* SECURITY: opening a remote-debugging port binds a CDP server on localhost.
|
|
7
|
+
* Any local process can then connect and fully control the browser (read
|
|
8
|
+
* cookies/sessions, execute JS). Use a dedicated `userDataDir` for automation,
|
|
9
|
+
* never bind to 0.0.0.0, and treat the port as a local attack surface.
|
|
10
|
+
* @module engine/cdp-launch
|
|
11
|
+
*/
|
|
12
|
+
import { spawn } from "node:child_process";
|
|
13
|
+
import { logger } from "../lib/logger.js";
|
|
14
|
+
/** Default macOS binary paths for common Chromium browsers. */
|
|
15
|
+
export const KNOWN_BROWSERS = {
|
|
16
|
+
dia: "/Applications/Dia.app/Contents/MacOS/Dia",
|
|
17
|
+
chrome: "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
18
|
+
edge: "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
|
|
19
|
+
brave: "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser",
|
|
20
|
+
arc: "/Applications/Arc.app/Contents/MacOS/Arc",
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Spawn a browser binary with remote debugging, fully detached from the parent.
|
|
24
|
+
* Runs without a shell (no shell injection); `binary`/`userDataDir` are passed
|
|
25
|
+
* as native argv. The opened debug port is a local attack surface (see module).
|
|
26
|
+
*/
|
|
27
|
+
export function spawnBrowser(binary, port, userDataDir) {
|
|
28
|
+
const args = [`--remote-debugging-port=${port}`, "--no-first-run", "--no-default-browser-check"];
|
|
29
|
+
if (userDataDir)
|
|
30
|
+
args.push(`--user-data-dir=${userDataDir}`);
|
|
31
|
+
const child = spawn(binary, args, { detached: true, stdio: "ignore" });
|
|
32
|
+
child.unref();
|
|
33
|
+
logger.info("spawned browser for CDP", { binary, port });
|
|
34
|
+
}
|
|
35
|
+
/** Poll http://localhost:PORT/json/version until it responds or retries run out. */
|
|
36
|
+
export async function waitForCdp(port, retries = 25, intervalMs = 300) {
|
|
37
|
+
const url = `http://localhost:${port}/json/version`;
|
|
38
|
+
for (let i = 0; i < retries; i += 1) {
|
|
39
|
+
try {
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
const timer = setTimeout(() => controller.abort(), 1_000);
|
|
42
|
+
const res = await fetch(url, { signal: controller.signal });
|
|
43
|
+
clearTimeout(timer);
|
|
44
|
+
if (res.ok)
|
|
45
|
+
return url.replace("/json/version", "");
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
/* not ready yet */
|
|
49
|
+
}
|
|
50
|
+
await new Promise((r) => setTimeout(r, intervalMs));
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`CDP endpoint not ready on port ${port} after ${retries} attempts`);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=cdp-launch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cdp-launch.js","sourceRoot":"","sources":["../../src/engine/cdp-launch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,+DAA+D;AAC/D,MAAM,CAAC,MAAM,cAAc,GAA2B;IACpD,GAAG,EAAE,0CAA0C;IAC/C,MAAM,EAAE,8DAA8D;IACtE,IAAI,EAAE,gEAAgE;IACtE,KAAK,EAAE,8DAA8D;IACrE,GAAG,EAAE,0CAA0C;CAChD,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,IAAY,EAAE,WAAoB;IAC7E,MAAM,IAAI,GAAG,CAAC,2BAA2B,IAAI,EAAE,EAAE,gBAAgB,EAAE,4BAA4B,CAAC,CAAC;IACjG,IAAI,WAAW;QAAE,IAAI,CAAC,IAAI,CAAC,mBAAmB,WAAW,EAAE,CAAC,CAAC;IAC7D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACvE,KAAK,CAAC,KAAK,EAAE,CAAC;IACd,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,OAAO,GAAG,EAAE,EAAE,UAAU,GAAG,GAAG;IAC3E,MAAM,GAAG,GAAG,oBAAoB,IAAI,eAAe,CAAC;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;YAC1D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5D,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,GAAG,CAAC,EAAE;gBAAE,OAAO,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,mBAAmB;QACrB,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,kCAAkC,IAAI,UAAU,OAAO,WAAW,CAAC,CAAC;AACtF,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build the browser context options (identity, viewport, headers).
|
|
3
|
+
* @module engine/context
|
|
4
|
+
*/
|
|
5
|
+
import type { BrowserContextOptions } from "playwright";
|
|
6
|
+
import type { ResolvedIdentity } from "../identity/resolve.js";
|
|
7
|
+
/** Shared viewport/screen dimensions (context + visual observation). */
|
|
8
|
+
export declare const VIEWPORT: {
|
|
9
|
+
readonly width: 1365;
|
|
10
|
+
readonly height: 900;
|
|
11
|
+
};
|
|
12
|
+
/** Assemble `newContext` options from the resolved identity. */
|
|
13
|
+
export declare function buildContextOptions(identity: ResolvedIdentity, realisticProfile: boolean): BrowserContextOptions;
|
|
14
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/engine/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,wEAAwE;AACxE,eAAO,MAAM,QAAQ;;;CAAwC,CAAC;AAE9D,gEAAgE;AAChE,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,gBAAgB,EAC1B,gBAAgB,EAAE,OAAO,GACxB,qBAAqB,CAevB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { REALISTIC_DESKTOP_UA } from "../identity/country-profiles.js";
|
|
2
|
+
/** Shared viewport/screen dimensions (context + visual observation). */
|
|
3
|
+
export const VIEWPORT = { width: 1365, height: 900 };
|
|
4
|
+
/** Assemble `newContext` options from the resolved identity. */
|
|
5
|
+
export function buildContextOptions(identity, realisticProfile) {
|
|
6
|
+
const opts = {
|
|
7
|
+
viewport: { ...VIEWPORT },
|
|
8
|
+
screen: { ...VIEWPORT },
|
|
9
|
+
deviceScaleFactor: 1,
|
|
10
|
+
isMobile: false,
|
|
11
|
+
hasTouch: false,
|
|
12
|
+
locale: identity.locale,
|
|
13
|
+
timezoneId: identity.timezoneId,
|
|
14
|
+
geolocation: identity.geolocation,
|
|
15
|
+
permissions: ["geolocation"],
|
|
16
|
+
extraHTTPHeaders: { "Accept-Language": identity.acceptLanguage },
|
|
17
|
+
};
|
|
18
|
+
if (realisticProfile)
|
|
19
|
+
opts.userAgent = REALISTIC_DESKTOP_UA;
|
|
20
|
+
return opts;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/engine/context.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,wEAAwE;AACxE,MAAM,CAAC,MAAM,QAAQ,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAW,CAAC;AAE9D,gEAAgE;AAChE,MAAM,UAAU,mBAAmB,CACjC,QAA0B,EAC1B,gBAAyB;IAEzB,MAAM,IAAI,GAA0B;QAClC,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE;QACzB,MAAM,EAAE,EAAE,GAAG,QAAQ,EAAE;QACvB,iBAAiB,EAAE,CAAC;QACpB,QAAQ,EAAE,KAAK;QACf,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,QAAQ,CAAC,MAAM;QACvB,UAAU,EAAE,QAAQ,CAAC,UAAU;QAC/B,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,WAAW,EAAE,CAAC,aAAa,CAAC;QAC5B,gBAAgB,EAAE,EAAE,iBAAiB,EAAE,QAAQ,CAAC,cAAc,EAAE;KACjE,CAAC;IACF,IAAI,gBAAgB;QAAE,IAAI,CAAC,SAAS,GAAG,oBAAoB,CAAC;IAC5D,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { BrowserType } from "playwright";
|
|
2
|
+
import type { ResolvedConfig } from "../agent/config.js";
|
|
3
|
+
import type { OpenedContext } from "../interfaces/engine.js";
|
|
4
|
+
/** Launch the given engine (persistent or ephemeral) and return a ready context. */
|
|
5
|
+
export declare function launchBrowser(browserType: BrowserType, config: ResolvedConfig): Promise<OpenedContext>;
|
|
6
|
+
//# sourceMappingURL=launch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/engine/launch.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,YAAY,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AA+B7D,oFAAoF;AACpF,wBAAsB,aAAa,CACjC,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,aAAa,CAAC,CAiBxB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared launch logic (persistent or ephemeral context), engine-aware.
|
|
3
|
+
* Chromium-only options (args, channel) are NOT passed to Firefox/WebKit, which
|
|
4
|
+
* reject unknown Chromium flags (e.g. WebKit throws on `--no-sandbox`).
|
|
5
|
+
* @module engine/launch
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync } from "node:fs";
|
|
8
|
+
import { logger } from "../lib/logger.js";
|
|
9
|
+
import { buildContextOptions } from "./context.js";
|
|
10
|
+
import { isChromiumEngine } from "./loader.js";
|
|
11
|
+
const CHROMIUM_ARGS = ["--no-sandbox", "--disable-blink-features=AutomationControlled"];
|
|
12
|
+
/** Build LaunchOptions, applying Chromium-only fields only for Chromium engines. */
|
|
13
|
+
function buildLaunchOptions(config) {
|
|
14
|
+
const opts = { headless: config.headless };
|
|
15
|
+
if (isChromiumEngine(config.engine)) {
|
|
16
|
+
opts.args = CHROMIUM_ARGS;
|
|
17
|
+
if (config.channel)
|
|
18
|
+
opts.channel = config.channel;
|
|
19
|
+
}
|
|
20
|
+
if (config.executablePath)
|
|
21
|
+
opts.executablePath = config.executablePath;
|
|
22
|
+
if (config.proxyUrl)
|
|
23
|
+
opts.proxy = { server: config.proxyUrl };
|
|
24
|
+
return opts;
|
|
25
|
+
}
|
|
26
|
+
const INSTALL_HINT = "Chromium is not installed. Run: npx patchright install chromium";
|
|
27
|
+
/** Rethrow a launch failure with an actionable hint when the browser binary is missing. */
|
|
28
|
+
function enrichLaunchError(err) {
|
|
29
|
+
const message = String(err?.message ?? err);
|
|
30
|
+
if (message.includes("Executable doesn't exist")) {
|
|
31
|
+
logger.error("browser binary missing", { hint: INSTALL_HINT });
|
|
32
|
+
throw new Error(`${INSTALL_HINT}\n${message}`);
|
|
33
|
+
}
|
|
34
|
+
throw err;
|
|
35
|
+
}
|
|
36
|
+
/** Launch the given engine (persistent or ephemeral) and return a ready context. */
|
|
37
|
+
export async function launchBrowser(browserType, config) {
|
|
38
|
+
const launchOptions = buildLaunchOptions(config);
|
|
39
|
+
const contextOptions = buildContextOptions(config.identity, config.realisticProfile);
|
|
40
|
+
if (config.userDataDir) {
|
|
41
|
+
const context = await browserType
|
|
42
|
+
.launchPersistentContext(config.userDataDir, { ...launchOptions, ...contextOptions })
|
|
43
|
+
.catch(enrichLaunchError);
|
|
44
|
+
return { context, browser: null };
|
|
45
|
+
}
|
|
46
|
+
const browser = await browserType.launch(launchOptions).catch(enrichLaunchError);
|
|
47
|
+
if (config.storageStatePath && existsSync(config.storageStatePath)) {
|
|
48
|
+
contextOptions.storageState = config.storageStatePath;
|
|
49
|
+
}
|
|
50
|
+
const context = await browser.newContext(contextOptions);
|
|
51
|
+
return { context, browser };
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=launch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/engine/launch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIrC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,aAAa,GAAG,CAAC,cAAc,EAAE,+CAA+C,CAAC,CAAC;AAExF,oFAAoF;AACpF,SAAS,kBAAkB,CAAC,MAAsB;IAChD,MAAM,IAAI,GAAkB,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC1D,IAAI,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,MAAM,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;IACpD,CAAC;IACD,IAAI,MAAM,CAAC,cAAc;QAAE,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IACvE,IAAI,MAAM,CAAC,QAAQ;QAAE,IAAI,CAAC,KAAK,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;IAC9D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,YAAY,GAAG,iEAAiE,CAAC;AAEvF,2FAA2F;AAC3F,SAAS,iBAAiB,CAAC,GAAY;IACrC,MAAM,OAAO,GAAG,MAAM,CAAE,GAAa,EAAE,OAAO,IAAI,GAAG,CAAC,CAAC;IACvD,IAAI,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,GAAG,YAAY,KAAK,OAAO,EAAE,CAAC,CAAC;IACjD,CAAC;IACD,MAAM,GAAY,CAAC;AACrB,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAwB,EACxB,MAAsB;IAEtB,MAAM,aAAa,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,cAAc,GAAG,mBAAmB,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAErF,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,MAAM,WAAW;aAC9B,uBAAuB,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,GAAG,aAAa,EAAE,GAAG,cAAc,EAAE,CAAC;aACpF,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACpC,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACjF,IAAI,MAAM,CAAC,gBAAgB,IAAI,UAAU,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACnE,cAAc,CAAC,YAAY,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACxD,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;IACzD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser engine loader. Resolves the Playwright/Patchright BrowserType for a
|
|
3
|
+
* given engine name. Patchright (stealth) is Chromium-only with a Playwright
|
|
4
|
+
* fallback; firefox/webkit come from Playwright.
|
|
5
|
+
* @module engine/loader
|
|
6
|
+
*/
|
|
7
|
+
import type { BrowserType } from "playwright";
|
|
8
|
+
import type { EngineName } from "../interfaces/engine-types.js";
|
|
9
|
+
/** True for engines backed by a Chromium browser (stealth/channel/CDP capable). */
|
|
10
|
+
export declare function isChromiumEngine(engine: EngineName): boolean;
|
|
11
|
+
/** Resolve the BrowserType (chromium/firefox/webkit) for the requested engine. */
|
|
12
|
+
export declare function loadBrowserType(engine: EngineName): Promise<BrowserType>;
|
|
13
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/engine/loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAGhE,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAE5D;AAED,kFAAkF;AAClF,wBAAsB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,CAa9E"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { logger } from "../lib/logger.js";
|
|
2
|
+
/** True for engines backed by a Chromium browser (stealth/channel/CDP capable). */
|
|
3
|
+
export function isChromiumEngine(engine) {
|
|
4
|
+
return engine === "patchright" || engine === "playwright";
|
|
5
|
+
}
|
|
6
|
+
/** Resolve the BrowserType (chromium/firefox/webkit) for the requested engine. */
|
|
7
|
+
export async function loadBrowserType(engine) {
|
|
8
|
+
if (engine === "patchright") {
|
|
9
|
+
try {
|
|
10
|
+
const mod = (await import("patchright"));
|
|
11
|
+
return mod.chromium;
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
logger.warn("patchright unavailable, falling back to playwright chromium", { err: String(err) });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const pw = await import("playwright");
|
|
18
|
+
if (engine === "firefox")
|
|
19
|
+
return pw.firefox;
|
|
20
|
+
if (engine === "webkit")
|
|
21
|
+
return pw.webkit;
|
|
22
|
+
return pw.chromium;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/engine/loader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAAC,MAAkB;IACjD,OAAO,MAAM,KAAK,YAAY,IAAI,MAAM,KAAK,YAAY,CAAC;AAC5D,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAkB;IACtD,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;QAC5B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,CAAyC,CAAC;YACjF,OAAO,GAAG,CAAC,QAAQ,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,CAAC,6DAA6D,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACnG,CAAC;IACH,CAAC;IACD,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;IACtC,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC,OAAO,CAAC;IAC5C,IAAI,MAAM,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,CAAC,QAAQ,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patchright-engine.d.ts","sourceRoot":"","sources":["../../src/engine/patchright-engine.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,yBAAyB,CAAC;AAI5E,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,EAAE,aAK9B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { launchBrowser } from "./launch.js";
|
|
2
|
+
import { loadBrowserType } from "./loader.js";
|
|
3
|
+
/** Engine backed by Patchright (falls back to Playwright if unavailable). */
|
|
4
|
+
export const patchrightEngine = {
|
|
5
|
+
name: "patchright",
|
|
6
|
+
async open(config) {
|
|
7
|
+
return launchBrowser(await loadBrowserType("patchright"), config);
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=patchright-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patchright-engine.js","sourceRoot":"","sources":["../../src/engine/patchright-engine.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,6EAA6E;AAC7E,MAAM,CAAC,MAAM,gBAAgB,GAAkB;IAC7C,IAAI,EAAE,YAAY;IAClB,KAAK,CAAC,IAAI,CAAC,MAAsB;QAC/B,OAAO,aAAa,CAAC,MAAM,eAAe,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { BrowserEngine } from "../interfaces/engine.js";
|
|
2
|
+
/** Engine backed by the official Playwright Chromium. */
|
|
3
|
+
export declare const playwrightEngine: BrowserEngine;
|
|
4
|
+
/** Engine backed by Playwright Firefox (Gecko). No stealth, no CDP/channel. */
|
|
5
|
+
export declare const firefoxEngine: BrowserEngine;
|
|
6
|
+
/** Engine backed by Playwright WebKit (Safari engine). No stealth, no CDP/channel. */
|
|
7
|
+
export declare const webkitEngine: BrowserEngine;
|
|
8
|
+
//# sourceMappingURL=playwright-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-engine.d.ts","sourceRoot":"","sources":["../../src/engine/playwright-engine.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAiB,MAAM,yBAAyB,CAAC;AAI5E,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,EAAE,aAK9B,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,aAAa,EAAE,aAK3B,CAAC;AAEF,sFAAsF;AACtF,eAAO,MAAM,YAAY,EAAE,aAK1B,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { launchBrowser } from "./launch.js";
|
|
2
|
+
import { loadBrowserType } from "./loader.js";
|
|
3
|
+
/** Engine backed by the official Playwright Chromium. */
|
|
4
|
+
export const playwrightEngine = {
|
|
5
|
+
name: "playwright",
|
|
6
|
+
async open(config) {
|
|
7
|
+
return launchBrowser(await loadBrowserType("playwright"), config);
|
|
8
|
+
},
|
|
9
|
+
};
|
|
10
|
+
/** Engine backed by Playwright Firefox (Gecko). No stealth, no CDP/channel. */
|
|
11
|
+
export const firefoxEngine = {
|
|
12
|
+
name: "firefox",
|
|
13
|
+
async open(config) {
|
|
14
|
+
return launchBrowser(await loadBrowserType("firefox"), config);
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
/** Engine backed by Playwright WebKit (Safari engine). No stealth, no CDP/channel. */
|
|
18
|
+
export const webkitEngine = {
|
|
19
|
+
name: "webkit",
|
|
20
|
+
async open(config) {
|
|
21
|
+
return launchBrowser(await loadBrowserType("webkit"), config);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=playwright-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwright-engine.js","sourceRoot":"","sources":["../../src/engine/playwright-engine.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,yDAAyD;AACzD,MAAM,CAAC,MAAM,gBAAgB,GAAkB;IAC7C,IAAI,EAAE,YAAY;IAClB,KAAK,CAAC,IAAI,CAAC,MAAsB;QAC/B,OAAO,aAAa,CAAC,MAAM,eAAe,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC;CACF,CAAC;AAEF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,IAAI,EAAE,SAAS;IACf,KAAK,CAAC,IAAI,CAAC,MAAsB;QAC/B,OAAO,aAAa,CAAC,MAAM,eAAe,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,CAAC;IACjE,CAAC;CACF,CAAC;AAEF,sFAAsF;AACtF,MAAM,CAAC,MAAM,YAAY,GAAkB;IACzC,IAAI,EAAE,QAAQ;IACd,KAAK,CAAC,IAAI,CAAC,MAAsB;QAC/B,OAAO,aAAa,CAAC,MAAM,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,CAAC;IAChE,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Engine registry: choose the browser engine for a resolved config.
|
|
3
|
+
* A `cdpEndpoint` forces the CDP attach engine regardless of `engine`.
|
|
4
|
+
* @module engine/registry
|
|
5
|
+
*/
|
|
6
|
+
import type { ResolvedConfig } from "../agent/config.js";
|
|
7
|
+
import type { BrowserEngine } from "../interfaces/engine.js";
|
|
8
|
+
import type { EngineName } from "../interfaces/engine-types.js";
|
|
9
|
+
/** Select the launch engine for `name`, defaulting to Patchright (stealth). */
|
|
10
|
+
export declare function selectEngine(name: EngineName): BrowserEngine;
|
|
11
|
+
/** Select the engine for a config: CDP attach if `cdpEndpoint`, else launch. */
|
|
12
|
+
export declare function selectEngineForConfig(config: ResolvedConfig): BrowserEngine;
|
|
13
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/engine/registry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAYhE,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa,CAE5D;AAED,gFAAgF;AAChF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,cAAc,GAAG,aAAa,CAE3E"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { cdpEngine } from "./cdp-engine.js";
|
|
2
|
+
import { patchrightEngine } from "./patchright-engine.js";
|
|
3
|
+
import { firefoxEngine, playwrightEngine, webkitEngine } from "./playwright-engine.js";
|
|
4
|
+
const ENGINES = {
|
|
5
|
+
playwright: playwrightEngine,
|
|
6
|
+
patchright: patchrightEngine,
|
|
7
|
+
firefox: firefoxEngine,
|
|
8
|
+
webkit: webkitEngine,
|
|
9
|
+
};
|
|
10
|
+
/** Select the launch engine for `name`, defaulting to Patchright (stealth). */
|
|
11
|
+
export function selectEngine(name) {
|
|
12
|
+
return ENGINES[name] ?? patchrightEngine;
|
|
13
|
+
}
|
|
14
|
+
/** Select the engine for a config: CDP attach if `cdpEndpoint`, else launch. */
|
|
15
|
+
export function selectEngineForConfig(config) {
|
|
16
|
+
return config.cdpEndpoint ? cdpEngine : selectEngine(config.engine);
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/engine/registry.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEvF,MAAM,OAAO,GAAsC;IACjD,UAAU,EAAE,gBAAgB;IAC5B,UAAU,EAAE,gBAAgB;IAC5B,OAAO,EAAE,aAAa;IACtB,MAAM,EAAE,YAAY;CACrB,CAAC;AAEF,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAC,IAAgB;IAC3C,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC;AAC3C,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,qBAAqB,CAAC,MAAsB;IAC1D,OAAO,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detection of anti-bot and authentication challenges.
|
|
3
|
+
* @module extraction/challenges
|
|
4
|
+
*/
|
|
5
|
+
import type { Page } from "playwright";
|
|
6
|
+
import type { Challenges } from "../interfaces/extraction.js";
|
|
7
|
+
/** Combine DOM and text signals to detect captcha, Cloudflare, login, OTP. */
|
|
8
|
+
export declare function detectChallenges(page: Page, text: string): Promise<Challenges>;
|
|
9
|
+
//# sourceMappingURL=challenges.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenges.d.ts","sourceRoot":"","sources":["../../src/extraction/challenges.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAiB9D,8EAA8E;AAC9E,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAkBpF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { evalScript } from "../lib/evaluate.js";
|
|
2
|
+
const DOM_FLAGS_SCRIPT = `() => ({
|
|
3
|
+
recaptcha: Boolean(document.querySelector('.g-recaptcha, iframe[src*="recaptcha"]')),
|
|
4
|
+
turnstile: Boolean(document.querySelector('input[name="cf-turnstile-response"], iframe[src*="turnstile"]')),
|
|
5
|
+
hcaptcha: Boolean(document.querySelector('.h-captcha, iframe[src*="hcaptcha"]')),
|
|
6
|
+
password: Boolean(document.querySelector('input[type="password"]')),
|
|
7
|
+
})`;
|
|
8
|
+
/** Combine DOM and text signals to detect captcha, Cloudflare, login, OTP. */
|
|
9
|
+
export async function detectChallenges(page, text) {
|
|
10
|
+
const lowered = text.toLowerCase();
|
|
11
|
+
const flags = await evalScript(page, DOM_FLAGS_SCRIPT);
|
|
12
|
+
const captcha = Boolean(flags.recaptcha || flags.hcaptcha || lowered.includes("captcha") || lowered.includes("i'm not a robot"));
|
|
13
|
+
return {
|
|
14
|
+
captcha,
|
|
15
|
+
turnstile: Boolean(flags.turnstile || lowered.includes("turnstile")),
|
|
16
|
+
hcaptcha: Boolean(flags.hcaptcha || lowered.includes("hcaptcha")),
|
|
17
|
+
cloudflare: lowered.includes("checking if the site connection is secure") || lowered.includes("cloudflare"),
|
|
18
|
+
login: Boolean(flags.password || lowered.includes("sign in") || lowered.includes("log in")),
|
|
19
|
+
otp: lowered.includes("one-time") ||
|
|
20
|
+
lowered.includes("verification code") ||
|
|
21
|
+
lowered.includes("code de vérification"),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=challenges.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"challenges.js","sourceRoot":"","sources":["../../src/extraction/challenges.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,MAAM,gBAAgB,GAAG;;;;;GAKtB,CAAC;AASJ,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAU,EAAE,IAAY;IAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,UAAU,CAAW,IAAI,EAAE,gBAAgB,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,OAAO,CACrB,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CACxG,CAAC;IACF,OAAO;QACL,OAAO;QACP,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACpE,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;QACjE,UAAU,EACR,OAAO,CAAC,QAAQ,CAAC,2CAA2C,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QACjG,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC3F,GAAG,EACD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;YAC5B,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YACrC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC;KAC3C,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hotel offers aggregation from visible page text (Google Hotels style).
|
|
3
|
+
* @module extraction/hotel-offers
|
|
4
|
+
*/
|
|
5
|
+
import type { HotelOffers } from "../interfaces/extraction.js";
|
|
6
|
+
/**
|
|
7
|
+
* Extract the headline offer (before "All options") and the list of offers
|
|
8
|
+
* (each block terminated by "Visit site"), plus the best total.
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractHotelOffers(text: string): HotelOffers;
|
|
11
|
+
//# sourceMappingURL=hotel-offers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotel-offers.d.ts","sourceRoot":"","sources":["../../src/extraction/hotel-offers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,6BAA6B,CAAC;AA0B3E;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAoC5D"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { parseSinglePrice } from "./prices.js";
|
|
2
|
+
const STOP_MARKERS = ["top things", "prices are currently", "show price range", "nearby places"];
|
|
3
|
+
/** Build an offer from a block of lines (provider + best price). */
|
|
4
|
+
function offerFromChunk(chunk) {
|
|
5
|
+
const prices = chunk.map(parseSinglePrice).filter((p) => p !== null);
|
|
6
|
+
if (prices.length === 0)
|
|
7
|
+
return null;
|
|
8
|
+
const price = prices.reduce((a, b) => (b.amount < a.amount ? b : a));
|
|
9
|
+
const providerLines = chunk.filter((line) => !parseSinglePrice(line) &&
|
|
10
|
+
!line.startsWith(",") &&
|
|
11
|
+
!line.toLowerCase().includes("save ") &&
|
|
12
|
+
!line.toLowerCase().includes("free cancellation"));
|
|
13
|
+
let provider;
|
|
14
|
+
if (providerLines.length >= 2 && providerLines[1]?.toLowerCase() === "official site") {
|
|
15
|
+
provider = `${providerLines[0]} Official site`;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
provider = providerLines[0] ?? "unknown";
|
|
19
|
+
}
|
|
20
|
+
return { provider, currency: price.currency, amount: price.amount };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Extract the headline offer (before "All options") and the list of offers
|
|
24
|
+
* (each block terminated by "Visit site"), plus the best total.
|
|
25
|
+
*/
|
|
26
|
+
export function extractHotelOffers(text) {
|
|
27
|
+
const lines = text
|
|
28
|
+
.split("\n")
|
|
29
|
+
.map((l) => l.trim())
|
|
30
|
+
.filter((l) => l.length > 0);
|
|
31
|
+
const allOptionsIndex = lines.includes("All options") ? lines.indexOf("All options") : lines.length;
|
|
32
|
+
let headline = null;
|
|
33
|
+
for (const line of lines.slice(0, allOptionsIndex)) {
|
|
34
|
+
const price = parseSinglePrice(line);
|
|
35
|
+
if (price) {
|
|
36
|
+
headline = price;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const options = [];
|
|
41
|
+
if (allOptionsIndex < lines.length) {
|
|
42
|
+
let chunk = [];
|
|
43
|
+
for (const line of lines.slice(allOptionsIndex + 1)) {
|
|
44
|
+
if (STOP_MARKERS.some((m) => line.toLowerCase().includes(m)))
|
|
45
|
+
break;
|
|
46
|
+
if (line === "Visit site") {
|
|
47
|
+
const offer = offerFromChunk(chunk);
|
|
48
|
+
if (offer)
|
|
49
|
+
options.push(offer);
|
|
50
|
+
chunk = [];
|
|
51
|
+
}
|
|
52
|
+
else if (line.startsWith("View more options")) {
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
chunk.push(line);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const bestTotal = options.length > 0 ? options.reduce((a, b) => (b.amount < a.amount ? b : a)) : null;
|
|
61
|
+
return { headline, options, bestTotal };
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=hotel-offers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotel-offers.js","sourceRoot":"","sources":["../../src/extraction/hotel-offers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read the page's MAIN content text, excluding duplicated nav/menu/footer.
|
|
3
|
+
* Targets the main landmark first (structural filter — survives hidden mobile
|
|
4
|
+
* menus that innerText would otherwise include), falling back to <body>.
|
|
5
|
+
* @module extraction/main-text
|
|
6
|
+
*/
|
|
7
|
+
import type { Page } from "playwright";
|
|
8
|
+
/**
|
|
9
|
+
* Return the trimmed innerText of the first matching main-content landmark,
|
|
10
|
+
* or the whole body if none is present.
|
|
11
|
+
*/
|
|
12
|
+
export declare function mainText(page: Page, timeout?: number): Promise<string>;
|
|
13
|
+
//# sourceMappingURL=main-text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-text.d.ts","sourceRoot":"","sources":["../../src/extraction/main-text.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAKvC;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,SAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAU3E"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Main-content selectors, most to least specific; `body` is the fallback. */
|
|
2
|
+
const MAIN_SELECTORS = ["main", "[role=main]", "article"];
|
|
3
|
+
/**
|
|
4
|
+
* Return the trimmed innerText of the first matching main-content landmark,
|
|
5
|
+
* or the whole body if none is present.
|
|
6
|
+
*/
|
|
7
|
+
export async function mainText(page, timeout = 3_000) {
|
|
8
|
+
for (const selector of MAIN_SELECTORS) {
|
|
9
|
+
const loc = page.locator(selector).first();
|
|
10
|
+
try {
|
|
11
|
+
if ((await loc.count()) > 0)
|
|
12
|
+
return await loc.innerText({ timeout });
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
/* try the next selector */
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return page.locator("body").innerText({ timeout });
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=main-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main-text.js","sourceRoot":"","sources":["../../src/extraction/main-text.ts"],"names":[],"mappings":"AAQA,8EAA8E;AAC9E,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC;AAE1D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAU,EAAE,OAAO,GAAG,KAAK;IACxD,KAAK,MAAM,QAAQ,IAAI,cAAc,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;QAC3C,IAAI,CAAC;YACH,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC;gBAAE,OAAO,MAAM,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-currency visible price extraction from page text.
|
|
3
|
+
* @module extraction/prices
|
|
4
|
+
*/
|
|
5
|
+
import type { Price } from "../interfaces/extraction.js";
|
|
6
|
+
/** Normalize a raw amount: float when it has decimals, otherwise integer (separators stripped). */
|
|
7
|
+
export declare function normaliseAmount(raw: string): number;
|
|
8
|
+
/**
|
|
9
|
+
* Extract visible prices, skipping ranges (e.g. "20–30") and irrelevant lines
|
|
10
|
+
* (restaurant, parking…). Deduplicates by currency+amount.
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractPrices(text: string): Price[];
|
|
13
|
+
/** First price of a line, or null. */
|
|
14
|
+
export declare function parseSinglePrice(line: string): {
|
|
15
|
+
currency: string;
|
|
16
|
+
amount: number;
|
|
17
|
+
} | null;
|
|
18
|
+
//# sourceMappingURL=prices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prices.d.ts","sourceRoot":"","sources":["../../src/extraction/prices.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAuCzD,mGAAmG;AACnG,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAInD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,EAAE,CAmBnD;AAED,sCAAsC;AACtC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI1F"}
|