@ap3x/browser 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.
Files changed (88) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/dist/cdp/connection.d.ts +53 -0
  4. package/dist/cdp/connection.d.ts.map +1 -0
  5. package/dist/cdp/endpoint.d.ts +18 -0
  6. package/dist/cdp/endpoint.d.ts.map +1 -0
  7. package/dist/cdp/reconnect.d.ts +22 -0
  8. package/dist/cdp/reconnect.d.ts.map +1 -0
  9. package/dist/chunk-DXCP25KX.js +77 -0
  10. package/dist/config.d.ts +91 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/dialogs/handler.d.ts +43 -0
  13. package/dist/dialogs/handler.d.ts.map +1 -0
  14. package/dist/dom/clickability.d.ts +4 -0
  15. package/dist/dom/clickability.d.ts.map +1 -0
  16. package/dist/dom/compound.d.ts +4 -0
  17. package/dist/dom/compound.d.ts.map +1 -0
  18. package/dist/dom/constants.d.ts +28 -0
  19. package/dist/dom/constants.d.ts.map +1 -0
  20. package/dist/dom/dom-service.d.ts +65 -0
  21. package/dist/dom/dom-service.d.ts.map +1 -0
  22. package/dist/dom/enhanced-tree.d.ts +52 -0
  23. package/dist/dom/enhanced-tree.d.ts.map +1 -0
  24. package/dist/dom/hashing.d.ts +21 -0
  25. package/dist/dom/hashing.d.ts.map +1 -0
  26. package/dist/dom/node.d.ts +43 -0
  27. package/dist/dom/node.d.ts.map +1 -0
  28. package/dist/dom/overlay.d.ts +11 -0
  29. package/dist/dom/overlay.d.ts.map +1 -0
  30. package/dist/dom/paint-order.d.ts +25 -0
  31. package/dist/dom/paint-order.d.ts.map +1 -0
  32. package/dist/dom/serialize-text.d.ts +16 -0
  33. package/dist/dom/serialize-text.d.ts.map +1 -0
  34. package/dist/dom/serializer.d.ts +33 -0
  35. package/dist/dom/serializer.d.ts.map +1 -0
  36. package/dist/dom/snapshot.d.ts +37 -0
  37. package/dist/dom/snapshot.d.ts.map +1 -0
  38. package/dist/dom/types.d.ts +178 -0
  39. package/dist/dom/types.d.ts.map +1 -0
  40. package/dist/downloads/sanitize.d.ts +13 -0
  41. package/dist/downloads/sanitize.d.ts.map +1 -0
  42. package/dist/driver.d.ts +88 -0
  43. package/dist/driver.d.ts.map +1 -0
  44. package/dist/errors.d.ts +71 -0
  45. package/dist/errors.d.ts.map +1 -0
  46. package/dist/events.d.ts +8 -0
  47. package/dist/events.d.ts.map +1 -0
  48. package/dist/index.d.ts +55 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +5066 -0
  51. package/dist/input/dispatcher.d.ts +196 -0
  52. package/dist/input/dispatcher.d.ts.map +1 -0
  53. package/dist/input/keys.d.ts +20 -0
  54. package/dist/input/keys.d.ts.map +1 -0
  55. package/dist/launch/discovery.d.ts +14 -0
  56. package/dist/launch/discovery.d.ts.map +1 -0
  57. package/dist/launch/local-browser.d.ts +59 -0
  58. package/dist/launch/local-browser.d.ts.map +1 -0
  59. package/dist/navigation/navigator.d.ts +37 -0
  60. package/dist/navigation/navigator.d.ts.map +1 -0
  61. package/dist/navigation/policy.d.ts +61 -0
  62. package/dist/navigation/policy.d.ts.map +1 -0
  63. package/dist/providers/cloak.d.ts +26 -0
  64. package/dist/providers/cloak.d.ts.map +1 -0
  65. package/dist/providers/factory.d.ts +17 -0
  66. package/dist/providers/factory.d.ts.map +1 -0
  67. package/dist/providers/index.d.ts +5 -0
  68. package/dist/providers/index.d.ts.map +1 -0
  69. package/dist/providers/local.d.ts +13 -0
  70. package/dist/providers/local.d.ts.map +1 -0
  71. package/dist/providers/types.d.ts +8 -0
  72. package/dist/providers/types.d.ts.map +1 -0
  73. package/dist/recording/har.d.ts +94 -0
  74. package/dist/recording/har.d.ts.map +1 -0
  75. package/dist/recording/screencast.d.ts +40 -0
  76. package/dist/recording/screencast.d.ts.map +1 -0
  77. package/dist/screenshot/service.d.ts +34 -0
  78. package/dist/screenshot/service.d.ts.map +1 -0
  79. package/dist/session.d.ts +130 -0
  80. package/dist/session.d.ts.map +1 -0
  81. package/dist/targets/registry.d.ts +99 -0
  82. package/dist/targets/registry.d.ts.map +1 -0
  83. package/dist/testing.d.ts +53 -0
  84. package/dist/testing.d.ts.map +1 -0
  85. package/dist/testing.js +8 -0
  86. package/dist/types.d.ts +88 -0
  87. package/dist/types.d.ts.map +1 -0
  88. package/package.json +42 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AP3X
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # @ap3x/browser
2
+
3
+ Primitives for driving Chromium over the Chrome DevTools Protocol: sessions, navigation, DOM extraction, input, screenshots, and recording.
4
+
5
+ Part of [AP3X](https://github.com/AP3X-Dev/AP3X) — a TypeScript multi-agent framework.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @ap3x/browser
11
+ ```
12
+
13
+ ## What's inside
14
+
15
+ - **`openBrowserSession(config)`** — the entry point; resolves to a local launch or a remote CDP endpoint.
16
+ - **CDP transport** — typed protocol access with a target registry and reconnect handling.
17
+ - **DOM** — extraction, serialization, clickability and paint-order analysis, and stable element hashing.
18
+ - **Navigation** — a navigation policy with domain allow-lists and IP-blocking rules.
19
+ - **Input** — human-like input dispatch with dialog resilience.
20
+ - **Capture** — screenshots, HAR recording, and screencast.
21
+
22
+ The agent that drives these lives in [`@ap3x/browser-agent`](https://www.npmjs.com/package/@ap3x/browser-agent).
23
+
24
+ ## Documentation
25
+
26
+ See the [AP3X repository](https://github.com/AP3X-Dev/AP3X) for architecture notes, the full package map, and examples.
27
+
28
+ ## License
29
+
30
+ MIT
@@ -0,0 +1,53 @@
1
+ import { CdpConnectionError } from "../errors";
2
+ import type { CdpCommand, CdpCommandParams, CdpCommandReturn, CdpEventListener, CdpEventName, CdpSendOptions, CdpTransport } from "../types";
3
+ /**
4
+ * The minimal socket surface {@link CdpConnection} needs. `ws` is adapted to it
5
+ * by {@link openWebSocket}; tests inject a fake so no real browser is required.
6
+ */
7
+ export interface CdpSocket {
8
+ send(data: string): void;
9
+ close(): void;
10
+ onMessage(cb: (data: string) => void): void;
11
+ onClose(cb: () => void): void;
12
+ onError(cb: (err: Error) => void): void;
13
+ }
14
+ export interface OpenWebSocketOptions {
15
+ headers?: Record<string, string>;
16
+ maxPayload?: number;
17
+ signal?: AbortSignal;
18
+ }
19
+ /** Open a real `ws` WebSocket and adapt it to {@link CdpSocket}. */
20
+ export declare function openWebSocket(url: string, options?: OpenWebSocketOptions): Promise<CdpSocket>;
21
+ export interface CdpConnectionOptions {
22
+ /** Default per-request timeout in ms (default 60000). */
23
+ defaultTimeoutMs?: number;
24
+ /**
25
+ * Debug-level diagnostic sink (e.g. a dropped malformed frame). Default:
26
+ * silent — this is a library, not a host; callers opt in.
27
+ */
28
+ onDebug?: (message: string, fields?: Record<string, unknown>) => void;
29
+ }
30
+ export declare class CdpConnection implements CdpTransport {
31
+ private readonly socket;
32
+ private nextId;
33
+ private readonly pending;
34
+ private readonly registrations;
35
+ private readonly disconnectListeners;
36
+ private readonly defaultTimeoutMs;
37
+ private readonly onDebug;
38
+ private closedError;
39
+ private intentional;
40
+ constructor(socket: CdpSocket, options?: CdpConnectionOptions);
41
+ /** Open a live connection to a `ws://` DevTools endpoint. */
42
+ static connect(wsUrl: string, options?: CdpConnectionOptions & OpenWebSocketOptions): Promise<CdpConnection>;
43
+ get isClosed(): boolean;
44
+ /** Fired once when the socket drops unexpectedly (not on {@link close}). */
45
+ onDisconnect(cb: (err: CdpConnectionError) => void): () => void;
46
+ send<T extends CdpCommand>(method: T, params?: CdpCommandParams<T>, options?: CdpSendOptions): Promise<CdpCommandReturn<T>>;
47
+ on<M extends CdpEventName>(method: M, listener: CdpEventListener<M>, sessionId?: string): () => void;
48
+ close(): Promise<void>;
49
+ private handleMessage;
50
+ private dispatchEvent;
51
+ private handleClose;
52
+ }
53
+ //# sourceMappingURL=connection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/cdp/connection.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,YAAY,EACb,MAAM,UAAU,CAAC;AAMlB;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,IAAI,IAAI,CAAC;IACd,SAAS,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,oEAAoE;AACpE,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,SAAS,CAAC,CAiC7F;AAaD,MAAM,WAAW,oBAAoB;IACnC,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACvE;AAED,qBAAa,aAAc,YAAW,YAAY;IAW9C,OAAO,CAAC,QAAQ,CAAC,MAAM;IAVzB,OAAO,CAAC,MAAM,CAAK;IACnB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqC;IAC7D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwC;IACtE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAgD;IACpF,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8D;IACtF,OAAO,CAAC,WAAW,CAAiC;IACpD,OAAO,CAAC,WAAW,CAAS;gBAGT,MAAM,EAAE,SAAS,EAClC,OAAO,CAAC,EAAE,oBAAoB;IAUhC,6DAA6D;WAChD,OAAO,CAClB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,oBAAoB,GAAG,oBAAoB,GACpD,OAAO,CAAC,aAAa,CAAC;IAKzB,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,4EAA4E;IAC5E,YAAY,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,GAAG,MAAM,IAAI;IAOzD,IAAI,CAAC,CAAC,SAAS,UAAU,EAC7B,MAAM,EAAE,CAAC,EACT,MAAM,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC5B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;IA4C/B,EAAE,CAAC,CAAC,SAAS,YAAY,EACvB,MAAM,EAAE,CAAC,EACT,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC7B,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,IAAI;IAiBP,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B,OAAO,CAAC,aAAa;IA0DrB,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,WAAW;CAapB"}
@@ -0,0 +1,18 @@
1
+ export interface ResolveCdpOptions {
2
+ /** Injected fetch (tests / proxy control). Defaults to the global fetch. */
3
+ fetch?: typeof fetch;
4
+ }
5
+ /**
6
+ * Resolve a CDP endpoint to a `ws(s)://` debugger url.
7
+ *
8
+ * - `ws://` / `wss://` → returned as-is.
9
+ * - `http://` / `https://` → fetch `<base>/json/version` and read
10
+ * `webSocketDebuggerUrl`.
11
+ *
12
+ * localhost DevTools is proxy-exempt (design §7.3.1 `trust_env=False`): Node's
13
+ * global fetch (undici) does not honour HTTP(S)_PROXY env by default, so no
14
+ * proxy stripping is needed for 127.0.0.1/localhost/::1.
15
+ * ponytail: revisit only if a global undici ProxyAgent is ever installed.
16
+ */
17
+ export declare function resolveCdpWebSocketUrl(url: string, options?: ResolveCdpOptions): Promise<string>;
18
+ //# sourceMappingURL=endpoint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"endpoint.d.ts","sourceRoot":"","sources":["../../src/cdp/endpoint.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,iBAAiB;IAChC,4EAA4E;IAC5E,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAMD;;;;;;;;;;;GAWG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAsDjB"}
@@ -0,0 +1,22 @@
1
+ import { CdpConnectionError } from "../errors";
2
+ import type { CdpConnection } from "./connection";
3
+ export interface ReconnectEvents {
4
+ onReconnecting?: (attempt: number, max: number) => void;
5
+ onReconnected?: (connection: CdpConnection) => void;
6
+ onFailed?: (err: CdpConnectionError) => void;
7
+ }
8
+ export interface ReconnectOptions {
9
+ /** Number of attempts (default 3). */
10
+ attempts?: number;
11
+ /** Backoff before attempts 2..N (default [1000, 2000, 4000] ms). */
12
+ delaysMs?: number[];
13
+ /** Per-attempt timeout (default 15000 ms). */
14
+ attemptTimeoutMs?: number;
15
+ }
16
+ /**
17
+ * Rebuild a connection with bounded retries. `connect` receives an AbortSignal
18
+ * that fires when the per-attempt budget is exceeded. Resolves with the first
19
+ * successful connection or throws a `reconnect_failed` {@link CdpConnectionError}.
20
+ */
21
+ export declare function reconnectWithBackoff(connect: (signal: AbortSignal) => Promise<CdpConnection>, events?: ReconnectEvents, options?: ReconnectOptions): Promise<CdpConnection>;
22
+ //# sourceMappingURL=reconnect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconnect.d.ts","sourceRoot":"","sources":["../../src/cdp/reconnect.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,MAAM,WAAW,eAAe;IAC9B,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IACxD,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,aAAa,KAAK,IAAI,CAAC;IACpD,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,8CAA8C;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAiBD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,aAAa,CAAC,EACxD,MAAM,CAAC,EAAE,eAAe,EACxB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,aAAa,CAAC,CA2BxB"}
@@ -0,0 +1,77 @@
1
+ // src/testing.ts
2
+ var FakeCdpTransport = class {
3
+ constructor(responses = /* @__PURE__ */ new Map()) {
4
+ this.responses = responses;
5
+ }
6
+ responses;
7
+ /** Every `send` in order, for assertions. */
8
+ calls = [];
9
+ registrations = /* @__PURE__ */ new Map();
10
+ disconnectListeners = /* @__PURE__ */ new Set();
11
+ async send(method, params, options) {
12
+ this.calls.push({ method, params, sessionId: options?.sessionId });
13
+ const responder = this.responses.get(method);
14
+ const value = typeof responder === "function" ? responder(params, options?.sessionId) : responder;
15
+ return value ?? {};
16
+ }
17
+ on(method, listener, sessionId) {
18
+ const key = method;
19
+ let set = this.registrations.get(key);
20
+ if (!set) {
21
+ set = /* @__PURE__ */ new Set();
22
+ this.registrations.set(key, set);
23
+ }
24
+ const registration = {
25
+ listener,
26
+ sessionId
27
+ };
28
+ set.add(registration);
29
+ return () => {
30
+ set.delete(registration);
31
+ };
32
+ }
33
+ /** Push a canned CDP event to matching subscribers. */
34
+ emitEvent(method, params, sessionId) {
35
+ const set = this.registrations.get(method);
36
+ if (!set) return;
37
+ for (const registration of [...set]) {
38
+ if (registration.sessionId === void 0 || registration.sessionId === sessionId) {
39
+ registration.listener(params, sessionId);
40
+ }
41
+ }
42
+ }
43
+ onDisconnect(cb) {
44
+ this.disconnectListeners.add(cb);
45
+ return () => {
46
+ this.disconnectListeners.delete(cb);
47
+ };
48
+ }
49
+ /** Simulate an unexpected socket drop for tests. */
50
+ emitDisconnect(err) {
51
+ for (const cb of [...this.disconnectListeners]) cb(err);
52
+ }
53
+ /** Number of `send`s recorded for a method. */
54
+ sendCount(method) {
55
+ return this.calls.filter((c) => c.method === method).length;
56
+ }
57
+ async close() {
58
+ this.registrations.clear();
59
+ }
60
+ };
61
+ function groundTruth(session) {
62
+ return {
63
+ /** Evaluate an arbitrary expression in the page and return the JSON value. */
64
+ evalInPage: (expression) => session.evaluate(expression),
65
+ /** `window.getClickCount()` — the golden-fixture click-counter contract (design/08-09 §9.3). */
66
+ clickCount: () => session.evaluate("window.getClickCount()"),
67
+ /** The live `.value` of the element matched by `selector`. */
68
+ inputValue: (selector) => session.evaluate(`document.querySelector(${JSON.stringify(selector)}).value`),
69
+ /** The live `.checked` of the element matched by `selector`. */
70
+ checked: (selector) => session.evaluate(`document.querySelector(${JSON.stringify(selector)}).checked`)
71
+ };
72
+ }
73
+
74
+ export {
75
+ FakeCdpTransport,
76
+ groundTruth
77
+ };
@@ -0,0 +1,91 @@
1
+ /** Cloak (CloakBrowser / cloakserve) connection settings. All optional here — the
2
+ * factory requires `endpoint` before building a {@link CloakProvider}. */
3
+ export interface CloakConfig {
4
+ /** cloakserve base URL or a launched CloakBrowser CDP url (http(s):// or ws(s)://). */
5
+ readonly endpoint?: string;
6
+ /** Fingerprint seed (cloakserve `fingerprint`). */
7
+ readonly fingerprint?: string;
8
+ /** Fingerprint platform (cloakserve `fingerprint-platform`). */
9
+ readonly platform?: "windows" | "macos";
10
+ /** Upstream proxy (cloakserve `proxy`). */
11
+ readonly proxy?: string;
12
+ /** Derive geo from the proxy IP (cloakserve `geoip`). */
13
+ readonly geoip?: string;
14
+ /** Humanize input timing (cloakserve `humanize`). */
15
+ readonly humanize?: boolean;
16
+ /** Spoofed timezone (cloakserve `timezone`). */
17
+ readonly timezone?: string;
18
+ /** Spoofed locale (cloakserve `locale`). */
19
+ readonly locale?: string;
20
+ }
21
+ /** The frozen configuration a {@link BrowserSession} is built from. */
22
+ export interface ResolvedBrowserConfig {
23
+ /** Which provider yields the session — stock local Chrome or a stealth CloakBrowser. */
24
+ readonly provider: "local" | "cloak";
25
+ /** Cloak connection settings (only used when `provider === "cloak"`). */
26
+ readonly cloak: CloakConfig;
27
+ /** Launch headless (only relevant to the launch path). */
28
+ readonly headless: boolean;
29
+ /** CDP endpoint to connect to (the connect path / CloakBrowser seam). */
30
+ readonly cdpUrl?: string;
31
+ /** Allow-list for navigation (empty = open). */
32
+ readonly allowedDomains: readonly string[];
33
+ /** Deny-list for navigation. */
34
+ readonly prohibitedDomains: readonly string[];
35
+ /** Block navigation to raw IP addresses (SSRF guard). */
36
+ readonly blockIpAddresses: boolean;
37
+ /** Opt-in (W27): permit `file://` navigation, otherwise unconditionally
38
+ * blocked by NavigationPolicy. Default-deny — reads local disk. */
39
+ readonly allowFileUrls: boolean;
40
+ /**
41
+ * C3 global dialog override: force-accept (true) or force-dismiss (false)
42
+ * ALL dialog types. When undefined (the default), each type uses its own
43
+ * per-type default (prompt→dismiss, others→accept).
44
+ */
45
+ readonly dialogAccept?: boolean;
46
+ /** Text for accepted `prompt()` dialogs. */
47
+ readonly dialogPromptText?: string;
48
+ /** Draw the numbered highlight overlay before screenshots (M5). */
49
+ readonly highlightElements: boolean;
50
+ /** Descend cross-origin (out-of-process) iframes during DOM capture. */
51
+ readonly crossOriginIframes: boolean;
52
+ /**
53
+ * The five DomServiceOptions perception knobs. Undefined (the default at
54
+ * every level) means DomService's own default stays authoritative — config
55
+ * never hardcodes a value that could drift from it.
56
+ */
57
+ readonly maxIframeDepth?: number;
58
+ readonly viewportThreshold?: number | null;
59
+ readonly includeAttributes?: readonly string[];
60
+ readonly paintOrderFiltering?: boolean;
61
+ readonly enableBboxFiltering?: boolean;
62
+ }
63
+ /** Overrides accepted by {@link resolveBrowserConfig} (all optional). */
64
+ export type BrowserConfigOverrides = Partial<{
65
+ provider: "local" | "cloak";
66
+ cloak: CloakConfig;
67
+ headless: boolean;
68
+ cdpUrl: string;
69
+ allowedDomains: readonly string[];
70
+ prohibitedDomains: readonly string[];
71
+ blockIpAddresses: boolean;
72
+ allowFileUrls: boolean;
73
+ dialogAccept: boolean;
74
+ dialogPromptText: string;
75
+ highlightElements: boolean;
76
+ crossOriginIframes: boolean;
77
+ maxIframeDepth: number;
78
+ viewportThreshold: number | null;
79
+ includeAttributes: readonly string[];
80
+ paintOrderFiltering: boolean;
81
+ enableBboxFiltering: boolean;
82
+ }>;
83
+ /** The env source read by {@link resolveBrowserConfig} (a subset of process.env). */
84
+ export type EnvSource = Record<string, string | undefined>;
85
+ /**
86
+ * Merge overrides over the `AP3X_BROWSER_*` environment over the defaults and
87
+ * freeze the result. Call once per session; the object never re-reads env. The
88
+ * env source is injectable (defaults to `process.env`) for pure testing.
89
+ */
90
+ export declare function resolveBrowserConfig(overrides?: BrowserConfigOverrides, source?: EnvSource): ResolvedBrowserConfig;
91
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ import { TypedEmitter } from "../events";
2
+ import type { CdpTransport } from "../types";
3
+ /** A dialog that opened and was auto-answered. */
4
+ export interface DialogNotification {
5
+ type: string;
6
+ message: string;
7
+ accepted: boolean;
8
+ sessionId?: string;
9
+ }
10
+ export interface DialogHandlerEvents {
11
+ dialog: DialogNotification;
12
+ }
13
+ export interface DialogHandlerOptions {
14
+ /**
15
+ * C3 global override: force-accept (true) or force-dismiss (false) EVERY
16
+ * dialog type. When undefined (the default), each type uses its own per-type
17
+ * default — see {@link DialogHandler.policyFor}.
18
+ */
19
+ accept?: boolean;
20
+ /** Text supplied to `prompt()` dialogs when accepting. */
21
+ promptText?: string;
22
+ }
23
+ export declare class DialogHandler {
24
+ private readonly transport;
25
+ readonly events: TypedEmitter<DialogHandlerEvents>;
26
+ private readonly accept?;
27
+ private readonly promptText?;
28
+ private unsubscribe?;
29
+ constructor(transport: CdpTransport, options?: DialogHandlerOptions);
30
+ /**
31
+ * The accept/dismiss decision for a dialog type. The C3 global override wins
32
+ * when set; otherwise the per-type default applies: `prompt` is
33
+ * dismissed (accepting would send "" instead of null — no input available),
34
+ * everything else (alert / confirm / beforeunload) is accepted.
35
+ */
36
+ private policyFor;
37
+ /** Begin auto-answering dialogs across all sessions. Idempotent. */
38
+ start(): void;
39
+ /** Stop auto-answering. */
40
+ stop(): void;
41
+ private handle;
42
+ }
43
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/dialogs/handler.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,kDAAkD;AAClD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,kBAAkB,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,aAAa;IAOtB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAN5B,QAAQ,CAAC,MAAM,oCAA2C;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAU;IAClC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAS;IACrC,OAAO,CAAC,WAAW,CAAC,CAAa;gBAGd,SAAS,EAAE,YAAY,EACxC,OAAO,GAAE,oBAAyB;IAMpC;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAKjB,oEAAoE;IACpE,KAAK,IAAI,IAAI;IAOb,2BAA2B;IAC3B,IAAI,IAAI,IAAI;YAKE,MAAM;CAoBrB"}
@@ -0,0 +1,4 @@
1
+ import { type EnhancedDOMTreeNode } from "./types";
2
+ /** True iff the node is treated as clickable/interactive. Pure. */
3
+ export declare function isInteractive(node: EnhancedDOMTreeNode): boolean;
4
+ //# sourceMappingURL=clickability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clickability.d.ts","sourceRoot":"","sources":["../../src/dom/clickability.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,mBAAmB,EAAY,MAAM,SAAS,CAAC;AAwE7D,mEAAmE;AACnE,wBAAgB,aAAa,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAiHhE"}
@@ -0,0 +1,4 @@
1
+ import { type EnhancedDOMTreeNode, type SimplifiedNode } from "./types";
2
+ /** Append compound sub-components to `node.compoundChildren`; mark `simplified`. */
3
+ export declare function addCompoundComponents(simplified: SimplifiedNode, node: EnhancedDOMTreeNode): void;
4
+ //# sourceMappingURL=compound.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compound.d.ts","sourceRoot":"","sources":["../../src/dom/compound.ts"],"names":[],"mappings":"AAOA,OAAO,EAEL,KAAK,mBAAmB,EAExB,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;AA+FjB,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,cAAc,EAAE,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAsGjG"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The ~55 attributes the serializer surfaces to the LLM by default, in the
3
+ * order they are emitted. Mixes HTML attributes, synthetic format hints, and
4
+ * AX-derived properties (see design/04a §4.25). `class` is intentionally omitted
5
+ * (deliberately omitted, to force structural rather than class-name reasoning).
6
+ */
7
+ export declare const DEFAULT_INCLUDE_ATTRIBUTES: readonly string[];
8
+ /** Attributes considered identity-stable, fed into element hashing (design/05). */
9
+ export declare const STATIC_ATTRIBUTES: ReadonlySet<string>;
10
+ /** Substrings marking transient CSS-state classes, dropped from the stable hash. */
11
+ export declare const DYNAMIC_CLASS_PATTERNS: ReadonlySet<string>;
12
+ /**
13
+ * The 10 computed styles requested from `DOMSnapshot.captureSnapshot`, in order.
14
+ * The response returns style values positionally aligned to THIS list, so the
15
+ * order is load-bearing. Deliberately minimal: requesting more crashes Chrome on
16
+ * heavy pages (design/04a §4.26).
17
+ */
18
+ export declare const REQUIRED_COMPUTED_STYLES: readonly string[];
19
+ /** Elements never serialized (no interaction / content value). */
20
+ export declare const DISABLED_ELEMENTS: ReadonlySet<string>;
21
+ /** SVG child elements skipped as decorative. */
22
+ export declare const SVG_ELEMENTS: ReadonlySet<string>;
23
+ /**
24
+ * AP3X's opt-out attribute — AP3X-branded, per Hard Constraint 1. An element whose
25
+ * value is "true" (case-insensitive) is dropped from serialization.
26
+ */
27
+ export declare const EXCLUDE_ATTRIBUTE = "data-ap3x-exclude";
28
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/dom/constants.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAyDvD,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAkDhD,CAAC;AAEH,oFAAoF;AACpF,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,MAAM,CAqBrD,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,EAAE,SAAS,MAAM,EAWrD,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,MAAM,CAOhD,CAAC;AAEH,gDAAgD;AAChD,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,MAAM,CAiB3C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,iBAAiB,sBAAsB,CAAC"}
@@ -0,0 +1,65 @@
1
+ import type { CdpTransport } from "../types";
2
+ import type { BackendNodeId, TargetId } from "../types";
3
+ import { type SerializerOptions } from "./serializer";
4
+ import type { DomSelectorMap, EnhancedDOMTreeNode, TargetAllTrees } from "./types";
5
+ /** The serialized page state the agent consumes. */
6
+ export interface SerializedDom {
7
+ /** The numbered/indented text projection the LLM reads. */
8
+ serializedText: string;
9
+ /** backendNodeId → node. The `[N]` in `serializedText` == a key here. */
10
+ selectorMap: DomSelectorMap;
11
+ /** The raw merged tree root (kept for downstream geometry/coordinate needs). */
12
+ enhancedTree: EnhancedDOMTreeNode;
13
+ }
14
+ export interface SerializeFromSnapshotOptions extends SerializerOptions {
15
+ targetId: TargetId;
16
+ includeAttributes?: readonly string[];
17
+ viewportThreshold?: number | null;
18
+ }
19
+ /**
20
+ * Pure pipeline: raw trees → { serializedText, selectorMap, enhancedTree }. No
21
+ * CDP, no I/O. Handles same-origin iframe content and shadow roots inline (both
22
+ * present in the pierce:true capture). Cross-origin iframes must be pre-attached
23
+ * to the trees' DOM (the live orchestrator does this).
24
+ */
25
+ export declare function serializeFromSnapshot(trees: TargetAllTrees, opts: SerializeFromSnapshotOptions): SerializedDom;
26
+ /** Resolves a cross-origin iframe's frame to its own CDP target/session. */
27
+ export type FrameTargetResolver = (frameId: string | undefined, src: string | undefined) => {
28
+ targetId: TargetId;
29
+ sessionId?: string;
30
+ } | undefined;
31
+ export interface DomServiceOptions {
32
+ /** Descend into out-of-process (cross-origin) iframes. Default false. */
33
+ crossOriginIframes?: boolean;
34
+ maxIframeDepth?: number;
35
+ viewportThreshold?: number | null;
36
+ includeAttributes?: readonly string[];
37
+ paintOrderFiltering?: boolean;
38
+ enableBboxFiltering?: boolean;
39
+ /** Required to descend OOPIFs when `crossOriginIframes` is on. */
40
+ resolveFrameTarget?: FrameTargetResolver;
41
+ }
42
+ /**
43
+ * Orchestrates the live capture + serialize for a focus target. Reuses one
44
+ * transport across steps. OOPIF descent recurses into child targets, threading
45
+ * the accumulated frame offset so child coordinates land in main-page space.
46
+ */
47
+ export declare class DomService {
48
+ private readonly transport;
49
+ private readonly opts;
50
+ constructor(transport: CdpTransport, opts?: DomServiceOptions);
51
+ getSerializedDom(targetId: TargetId, sessionId: string | undefined, serializerOpts?: SerializerOptions, opts?: {
52
+ signal?: AbortSignal;
53
+ }): Promise<SerializedDom>;
54
+ /** Build the merged tree, descending OOPIFs (recursively — an OOPIF's own
55
+ * subtree may itself contain further OOPIFs) when enabled. Bounded by
56
+ * `maxIframeDepth` (default 5, via `buildEnhancedTree`'s own gate), so a
57
+ * cyclic frame graph cannot recurse forever. */
58
+ private buildWithOopif;
59
+ }
60
+ /**
61
+ * Resolve an element by its map key — the CDP backendNodeId, i.e. the `[N]` the
62
+ * LLM emitted. Same integer everywhere (design/10 gap #1).
63
+ */
64
+ export declare function getElementByIndex(selectorMap: DomSelectorMap, index: BackendNodeId): EnhancedDOMTreeNode | undefined;
65
+ //# sourceMappingURL=dom-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-service.d.ts","sourceRoot":"","sources":["../../src/dom/dom-service.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAIxD,OAAO,EAAiB,KAAK,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAErE,OAAO,KAAK,EAAW,cAAc,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAI5F,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B,2DAA2D;IAC3D,cAAc,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,WAAW,EAAE,cAAc,CAAC;IAC5B,gFAAgF;IAChF,YAAY,EAAE,mBAAmB,CAAC;CACnC;AAED,MAAM,WAAW,4BAA6B,SAAQ,iBAAiB;IACrE,QAAQ,EAAE,QAAQ,CAAC;IACnB,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,4BAA4B,GACjC,aAAa,CAUf;AAED,4EAA4E;AAC5E,MAAM,MAAM,mBAAmB,GAAG,CAChC,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,GAAG,EAAE,MAAM,GAAG,SAAS,KACpB;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,kEAAkE;IAClE,kBAAkB,CAAC,EAAE,mBAAmB,CAAC;CAC1C;AAED;;;;GAIG;AACH,qBAAa,UAAU;IAEnB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,IAAI;gBADJ,SAAS,EAAE,YAAY,EACvB,IAAI,GAAE,iBAAsB;IAGzC,gBAAgB,CACpB,QAAQ,EAAE,QAAQ,EAClB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,cAAc,GAAE,iBAAsB,EACtC,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAO,GAClC,OAAO,CAAC,aAAa,CAAC;IAmBzB;;;oDAGgD;YAClC,cAAc;CA2C7B;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,cAAc,EAC3B,KAAK,EAAE,aAAa,GACnB,mBAAmB,GAAG,SAAS,CAEjC"}
@@ -0,0 +1,52 @@
1
+ import type { TargetId } from "../types";
2
+ import { type DOMRect, type EnhancedDOMTreeNode, type TargetAllTrees } from "./types";
3
+ export interface BuildTreeOptions {
4
+ targetId: TargetId;
5
+ viewportThreshold?: number | null;
6
+ crossOriginIframes?: boolean;
7
+ maxIframeDepth?: number;
8
+ iframeDepth?: number;
9
+ /** Carried into an OOPIF recursion so its coordinates land in main-page space. */
10
+ initialFrameOffset?: DOMRect;
11
+ /**
12
+ * The CDP session this capture was taken from. Stamped on every node built by
13
+ * this call so `InputDispatcher` routes a backendNodeId to the session that
14
+ * minted it (design §4.23) — required for OOPIF subtrees, which are captured
15
+ * against a different target/session than the main page. Leave unset for the
16
+ * main-page build; same-origin iframe content (arrives inline via
17
+ * `pierce:true`) legitimately belongs to the parent session.
18
+ */
19
+ sessionId?: string;
20
+ /**
21
+ * Seam for cross-origin (out-of-process) iframes: called for each IFRAME with
22
+ * no inline content document, passing the node and the accumulated frame
23
+ * offset. The orchestrator captures that frame's target and attaches the built
24
+ * subtree as `contentDocument`. Same-origin iframes never reach here (their
25
+ * content arrives inline via `pierce:true`).
26
+ */
27
+ onOopifIframe?: (node: EnhancedDOMTreeNode, frameOffset: DOMRect) => void;
28
+ }
29
+ /**
30
+ * Element visibility per its full frame chain. CSS excludes first
31
+ * (display/visibility/opacity), then a geometric viewport-intersection test at
32
+ * each ancestor HTML frame. `viewportThreshold === null` skips geometry
33
+ * (CSS-only mode). Faithful to design/04a §4.24.
34
+ */
35
+ export declare function isElementVisibleAccordingToAllParents(node: EnhancedDOMTreeNode, htmlFrames: EnhancedDOMTreeNode[], viewportThreshold?: number | null): boolean;
36
+ /**
37
+ * Build the merged tree for one target's captures. Same-origin iframe content
38
+ * and shadow roots (both present in the `pierce:true` document) are recursed
39
+ * inline; cross-origin iframes are surfaced to `opts.onOopifIframe`.
40
+ */
41
+ export declare function buildEnhancedTree(trees: TargetAllTrees, opts: BuildTreeOptions): EnhancedDOMTreeNode;
42
+ /**
43
+ * Annotate every IFRAME/FRAME node that has a content document with hints about
44
+ * interactive elements hidden below its viewport: `hiddenElementsInfo` (sorted by
45
+ * pages-down, capped at 10) and `hasHiddenContent` (set when no interactive
46
+ * element is hidden but some non-interactive content is). Run on the fully
47
+ * assembled tree, AFTER build (and OOPIF attach), BEFORE serialization — the
48
+ * serializer reads these off the iframe node to emit scroll hints. Faithful to
49
+ * design/04a §4.24 (hidden-element counting across iframes).
50
+ */
51
+ export declare function countHiddenElementsInIframes(node: EnhancedDOMTreeNode): void;
52
+ //# sourceMappingURL=enhanced-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enhanced-tree.d.ts","sourceRoot":"","sources":["../../src/dom/enhanced-tree.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAIzC,OAAO,EACL,KAAK,OAAO,EAGZ,KAAK,mBAAmB,EAIxB,KAAK,cAAc,EACpB,MAAM,SAAS,CAAC;AAKjB,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;;;OAOG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,mBAAmB,EAAE,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;CAC3E;AA+CD;;;;;GAKG;AACH,wBAAgB,qCAAqC,CACnD,IAAI,EAAE,mBAAmB,EACzB,UAAU,EAAE,mBAAmB,EAAE,EACjC,iBAAiB,GAAE,MAAM,GAAG,IAAiC,GAC5D,OAAO,CAyCT;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,IAAI,EAAE,gBAAgB,GACrB,mBAAmB,CAgJrB;AAmDD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAoB5E"}
@@ -0,0 +1,21 @@
1
+ import { type DOMInteractedElement, type EnhancedDOMTreeNode } from "./types";
2
+ /** Tag names of every ELEMENT ancestor, root → self. */
3
+ export declare function parentBranchPath(node: EnhancedDOMTreeNode): string[];
4
+ /**
5
+ * Drop transient CSS-state classes (any class whose lowercased form CONTAINS a
6
+ * dynamic pattern), then return the survivors sorted and space-joined — sorting
7
+ * makes the stable hash deterministic.
8
+ */
9
+ export declare function filterDynamicClasses(classStr: string | undefined): string;
10
+ /** Exact hash (MatchLevel.Exact): full static attributes, unfiltered. */
11
+ export declare function elementHash(node: EnhancedDOMTreeNode): string;
12
+ /** Stable hash (MatchLevel.Stable): dynamic classes filtered — survives class churn. */
13
+ export declare function stableHash(node: EnhancedDOMTreeNode): string;
14
+ /** Parent-branch hash: structural identity only (no attributes/ax). */
15
+ export declare function parentBranchHash(node: EnhancedDOMTreeNode): string;
16
+ /**
17
+ * Snapshot a node into a persisted interaction record. Both hashes are captured
18
+ * here so replay has a single source of truth (design/05 invariant).
19
+ */
20
+ export declare function buildInteractedElement(node: EnhancedDOMTreeNode): DOMInteractedElement;
21
+ //# sourceMappingURL=hashing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hashing.d.ts","sourceRoot":"","sources":["../../src/dom/hashing.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,oBAAoB,EAAE,KAAK,mBAAmB,EAAY,MAAM,SAAS,CAAC;AAMxF,wDAAwD;AACxD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,EAAE,CASpE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAWzE;AAuBD,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAG7D;AAED,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAG5D;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAElE;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,oBAAoB,CAgBtF"}
@@ -0,0 +1,43 @@
1
+ import { type DOMRect, type EnhancedDOMTreeNode } from "./types";
2
+ /** Lower-cased tag name. */
3
+ export declare function tagName(node: EnhancedDOMTreeNode): string;
4
+ /** Real children (never the shared array). */
5
+ export declare function children(node: EnhancedDOMTreeNode): EnhancedDOMTreeNode[];
6
+ /** Children plus shadow roots — a fresh array, safe to iterate/mutate. */
7
+ export declare function childrenAndShadowRoots(node: EnhancedDOMTreeNode): EnhancedDOMTreeNode[];
8
+ /**
9
+ * Scroll detection combining CDP's flag with a CSS/geometry heuristic — catches
10
+ * scrollable containers CDP misses (common in iframes and dynamically-sized
11
+ * elements). Faithful to design/04a §4.25.
12
+ */
13
+ export declare function isActuallyScrollable(node: EnhancedDOMTreeNode): boolean;
14
+ /**
15
+ * Whether to render scroll info for this node. Always for iframes; else the node
16
+ * must be scrollable and not nested inside another scrollable (avoids spam);
17
+ * always for iframe-content body/html.
18
+ */
19
+ export declare function shouldShowScrollInfo(node: EnhancedDOMTreeNode): boolean;
20
+ interface ScrollInfo {
21
+ scrollableHeight: number;
22
+ scrollableWidth: number;
23
+ visibleHeight: number;
24
+ visibleWidth: number;
25
+ pagesAbove: number;
26
+ pagesBelow: number;
27
+ verticalScrollPct: number;
28
+ horizontalScrollPct: number;
29
+ }
30
+ /** Scroll geometry (pages above/below, percentages) or undefined if not scrollable. */
31
+ export declare function scrollInfo(node: EnhancedDOMTreeNode): ScrollInfo | undefined;
32
+ /** Human-readable scroll text, e.g. "1.0 pages above, 3.0 pages below". */
33
+ export declare function getScrollInfoText(node: EnhancedDOMTreeNode): string;
34
+ /**
35
+ * XPath for a node, passing THROUGH shadow roots and stopping AT iframe
36
+ * boundaries (xpath is per-document). Position `[n]` is 1-based and only emitted
37
+ * when there is more than one same-tag sibling.
38
+ */
39
+ export declare function xpath(node: EnhancedDOMTreeNode): string;
40
+ /** Absolute bounds, if known. */
41
+ export declare function absoluteBounds(node: EnhancedDOMTreeNode): DOMRect | undefined;
42
+ export {};
43
+ //# sourceMappingURL=node.d.ts.map