@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.
- package/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/cdp/connection.d.ts +53 -0
- package/dist/cdp/connection.d.ts.map +1 -0
- package/dist/cdp/endpoint.d.ts +18 -0
- package/dist/cdp/endpoint.d.ts.map +1 -0
- package/dist/cdp/reconnect.d.ts +22 -0
- package/dist/cdp/reconnect.d.ts.map +1 -0
- package/dist/chunk-DXCP25KX.js +77 -0
- package/dist/config.d.ts +91 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/dialogs/handler.d.ts +43 -0
- package/dist/dialogs/handler.d.ts.map +1 -0
- package/dist/dom/clickability.d.ts +4 -0
- package/dist/dom/clickability.d.ts.map +1 -0
- package/dist/dom/compound.d.ts +4 -0
- package/dist/dom/compound.d.ts.map +1 -0
- package/dist/dom/constants.d.ts +28 -0
- package/dist/dom/constants.d.ts.map +1 -0
- package/dist/dom/dom-service.d.ts +65 -0
- package/dist/dom/dom-service.d.ts.map +1 -0
- package/dist/dom/enhanced-tree.d.ts +52 -0
- package/dist/dom/enhanced-tree.d.ts.map +1 -0
- package/dist/dom/hashing.d.ts +21 -0
- package/dist/dom/hashing.d.ts.map +1 -0
- package/dist/dom/node.d.ts +43 -0
- package/dist/dom/node.d.ts.map +1 -0
- package/dist/dom/overlay.d.ts +11 -0
- package/dist/dom/overlay.d.ts.map +1 -0
- package/dist/dom/paint-order.d.ts +25 -0
- package/dist/dom/paint-order.d.ts.map +1 -0
- package/dist/dom/serialize-text.d.ts +16 -0
- package/dist/dom/serialize-text.d.ts.map +1 -0
- package/dist/dom/serializer.d.ts +33 -0
- package/dist/dom/serializer.d.ts.map +1 -0
- package/dist/dom/snapshot.d.ts +37 -0
- package/dist/dom/snapshot.d.ts.map +1 -0
- package/dist/dom/types.d.ts +178 -0
- package/dist/dom/types.d.ts.map +1 -0
- package/dist/downloads/sanitize.d.ts +13 -0
- package/dist/downloads/sanitize.d.ts.map +1 -0
- package/dist/driver.d.ts +88 -0
- package/dist/driver.d.ts.map +1 -0
- package/dist/errors.d.ts +71 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/events.d.ts +8 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5066 -0
- package/dist/input/dispatcher.d.ts +196 -0
- package/dist/input/dispatcher.d.ts.map +1 -0
- package/dist/input/keys.d.ts +20 -0
- package/dist/input/keys.d.ts.map +1 -0
- package/dist/launch/discovery.d.ts +14 -0
- package/dist/launch/discovery.d.ts.map +1 -0
- package/dist/launch/local-browser.d.ts +59 -0
- package/dist/launch/local-browser.d.ts.map +1 -0
- package/dist/navigation/navigator.d.ts +37 -0
- package/dist/navigation/navigator.d.ts.map +1 -0
- package/dist/navigation/policy.d.ts +61 -0
- package/dist/navigation/policy.d.ts.map +1 -0
- package/dist/providers/cloak.d.ts +26 -0
- package/dist/providers/cloak.d.ts.map +1 -0
- package/dist/providers/factory.d.ts +17 -0
- package/dist/providers/factory.d.ts.map +1 -0
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/local.d.ts +13 -0
- package/dist/providers/local.d.ts.map +1 -0
- package/dist/providers/types.d.ts +8 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/recording/har.d.ts +94 -0
- package/dist/recording/har.d.ts.map +1 -0
- package/dist/recording/screencast.d.ts +40 -0
- package/dist/recording/screencast.d.ts.map +1 -0
- package/dist/screenshot/service.d.ts +34 -0
- package/dist/screenshot/service.d.ts.map +1 -0
- package/dist/session.d.ts +130 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/targets/registry.d.ts +99 -0
- package/dist/targets/registry.d.ts.map +1 -0
- package/dist/testing.d.ts +53 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +8 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +42 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { TargetRegistry } from "../targets/registry";
|
|
2
|
+
import type { CdpTransport } from "../types";
|
|
3
|
+
export interface ScreencastFrame {
|
|
4
|
+
/** Base64 PNG data, as CDP delivers it. */
|
|
5
|
+
data: string;
|
|
6
|
+
timestamp: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ScreencastRecorderOptions {
|
|
9
|
+
format?: "png" | "jpeg";
|
|
10
|
+
quality?: number;
|
|
11
|
+
maxWidth?: number;
|
|
12
|
+
maxHeight?: number;
|
|
13
|
+
everyNthFrame?: number;
|
|
14
|
+
/** Defensive cap on buffered frames (default 600 — e.g. 10min @ 1fps). */
|
|
15
|
+
maxFrames?: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class ScreencastRecorder {
|
|
18
|
+
private readonly transport;
|
|
19
|
+
private readonly registry;
|
|
20
|
+
private readonly options;
|
|
21
|
+
private frames;
|
|
22
|
+
private frameListener?;
|
|
23
|
+
private focusListener?;
|
|
24
|
+
private currentSessionId?;
|
|
25
|
+
private recording;
|
|
26
|
+
private droppedFrames;
|
|
27
|
+
constructor(transport: CdpTransport, registry: TargetRegistry, options?: ScreencastRecorderOptions);
|
|
28
|
+
get isRecording(): boolean;
|
|
29
|
+
/** Frames captured so far (or, after {@link stop}, the final buffer). */
|
|
30
|
+
get capturedFrames(): readonly ScreencastFrame[];
|
|
31
|
+
/** How many frames were dropped after hitting `maxFrames` (observability). */
|
|
32
|
+
get dropped(): number;
|
|
33
|
+
/** Begin capturing frames from the focused target, following focus changes. Idempotent. */
|
|
34
|
+
start(): void;
|
|
35
|
+
/** Stop capturing and return every buffered frame. */
|
|
36
|
+
stop(): ScreencastFrame[];
|
|
37
|
+
private onFrame;
|
|
38
|
+
private followFocus;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=screencast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screencast.d.ts","sourceRoot":"","sources":["../../src/recording/screencast.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAID,qBAAa,kBAAkB;IAc3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAd3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAGoC;IAE5D,OAAO,CAAC,MAAM,CAAyB;IACvC,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,gBAAgB,CAAC,CAAS;IAClC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,aAAa,CAAK;gBAGP,SAAS,EAAE,YAAY,EACvB,QAAQ,EAAE,cAAc,EACzC,OAAO,GAAE,yBAA8B;IAYzC,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,yEAAyE;IACzE,IAAI,cAAc,IAAI,SAAS,eAAe,EAAE,CAE/C;IAED,8EAA8E;IAC9E,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,2FAA2F;IAC3F,KAAK,IAAI,IAAI;IAeb,sDAAsD;IACtD,IAAI,IAAI,eAAe,EAAE;IAezB,OAAO,CAAC,OAAO;IAoBf,OAAO,CAAC,WAAW;CAwBpB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { DomSelectorMap } from "../dom/types";
|
|
2
|
+
import type { CdpTransport } from "../types";
|
|
3
|
+
/**
|
|
4
|
+
* A 4×4 transparent PNG, returned when no real screenshot is available. A
|
|
5
|
+
* non-empty base64 sentinel keeps downstream image handling total (design's
|
|
6
|
+
* placeholder semantics).
|
|
7
|
+
*/
|
|
8
|
+
export declare const PLACEHOLDER_SCREENSHOT = "iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==";
|
|
9
|
+
export interface ScreenshotCaptureOptions {
|
|
10
|
+
/** Capture beyond the viewport (the full scrollable page). */
|
|
11
|
+
fullPage?: boolean;
|
|
12
|
+
/** Draw numbered boxes over the interactive elements before capturing. */
|
|
13
|
+
highlight?: boolean;
|
|
14
|
+
/** Required when `highlight` is set — the map whose elements get boxed. */
|
|
15
|
+
selectorMap?: DomSelectorMap;
|
|
16
|
+
/** Session of the page being captured (the focused page). */
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
/** `"png"` (default) or `"jpeg"`. */
|
|
19
|
+
format?: "png" | "jpeg";
|
|
20
|
+
/** JPEG quality 0–100. */
|
|
21
|
+
quality?: number;
|
|
22
|
+
/** Caller abort, threaded into the CDP sends (composes with per-request timeout). */
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
export declare class ScreenshotService {
|
|
26
|
+
private readonly transport;
|
|
27
|
+
constructor(transport: CdpTransport);
|
|
28
|
+
/** Capture a screenshot (base64), optionally with a highlight overlay. */
|
|
29
|
+
capture(options?: ScreenshotCaptureOptions): Promise<string>;
|
|
30
|
+
/** Draw the overlay. Returns whether an inject was attempted; never throws. */
|
|
31
|
+
private injectHighlights;
|
|
32
|
+
private removeHighlights;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../src/screenshot/service.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAE7C;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,qGACiE,CAAC;AAIrG,MAAM,WAAW,wBAAwB;IACvC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2EAA2E;IAC3E,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;IACxB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,YAAY;IAEpD,0EAA0E;IACpE,OAAO,CAAC,OAAO,GAAE,wBAA6B,GAAG,OAAO,CAAC,MAAM,CAAC;IAgCtE,+EAA+E;YACjE,gBAAgB;YAkChB,gBAAgB;CAmB/B"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { type BrowserConfigOverrides, type ResolvedBrowserConfig } from "./config";
|
|
2
|
+
import { DialogHandler } from "./dialogs/handler";
|
|
3
|
+
import { DomService } from "./dom/dom-service";
|
|
4
|
+
import { ElementOverlay } from "./dom/overlay";
|
|
5
|
+
import type { DomSelectorMap, EnhancedDOMTreeNode } from "./dom/types";
|
|
6
|
+
import { type CdpConnectionError } from "./errors";
|
|
7
|
+
import { InputDispatcher } from "./input/dispatcher";
|
|
8
|
+
import { type LaunchedBrowser } from "./launch/local-browser";
|
|
9
|
+
import { type NavigateOptions, type NavigateResult, Navigator } from "./navigation/navigator";
|
|
10
|
+
import { NavigationPolicy } from "./navigation/policy";
|
|
11
|
+
import { HarRecorder } from "./recording/har";
|
|
12
|
+
import { ScreencastRecorder } from "./recording/screencast";
|
|
13
|
+
import { ScreenshotService } from "./screenshot/service";
|
|
14
|
+
import { TargetRegistry } from "./targets/registry";
|
|
15
|
+
import { type BackendNodeId, type BrowserStateSummary, type CdpTransport, type TabId, type TabInfo } from "./types";
|
|
16
|
+
export interface BrowserSessionOptions {
|
|
17
|
+
/** A launched browser to close when the session stops (launch path only). */
|
|
18
|
+
ownedBrowser?: LaunchedBrowser;
|
|
19
|
+
}
|
|
20
|
+
/** Injectable seams for {@link BrowserSession.connect} (tests / alt providers). */
|
|
21
|
+
export interface BrowserConnectOptions {
|
|
22
|
+
/** fetch used for http→ws resolution (defaults to the global fetch). */
|
|
23
|
+
fetch?: typeof fetch;
|
|
24
|
+
/** Build the transport from the resolved ws url (defaults to a real socket). */
|
|
25
|
+
openTransport?: (wsUrl: string) => Promise<CdpTransport>;
|
|
26
|
+
}
|
|
27
|
+
export interface BrowserStateOptions {
|
|
28
|
+
/** Include a base64 screenshot in the summary. */
|
|
29
|
+
screenshot?: boolean;
|
|
30
|
+
/** Caller abort, threaded into the DOM capture + screenshot CDP sends (§6.8). */
|
|
31
|
+
signal?: AbortSignal;
|
|
32
|
+
}
|
|
33
|
+
export declare class BrowserSession {
|
|
34
|
+
private readonly transport;
|
|
35
|
+
readonly config: ResolvedBrowserConfig;
|
|
36
|
+
readonly registry: TargetRegistry;
|
|
37
|
+
readonly policy: NavigationPolicy;
|
|
38
|
+
readonly navigator: Navigator;
|
|
39
|
+
readonly dom: DomService;
|
|
40
|
+
readonly input: InputDispatcher;
|
|
41
|
+
readonly dialogs: DialogHandler;
|
|
42
|
+
readonly screenshots: ScreenshotService;
|
|
43
|
+
/** Demo-mode single-element highlight (IMPROVEMENTS overlay). */
|
|
44
|
+
readonly overlay: ElementOverlay;
|
|
45
|
+
/** Network traffic -> HAR capture (M11). Off until `.start()` is called — never active by default. */
|
|
46
|
+
readonly har: HarRecorder;
|
|
47
|
+
/** CDP screencast frame capture, tab-follow (M11). Off until `.start()` is called. */
|
|
48
|
+
readonly screencast: ScreencastRecorder;
|
|
49
|
+
private lastSelectorMap;
|
|
50
|
+
private readonly ownedBrowser?;
|
|
51
|
+
private started;
|
|
52
|
+
constructor(transport: CdpTransport, config: ResolvedBrowserConfig, options?: BrowserSessionOptions);
|
|
53
|
+
/**
|
|
54
|
+
* {@link FrameTargetResolver} for OOPIF descent (W3/W3b). The registry
|
|
55
|
+
* already auto-attaches every target's session via `Target.setAutoAttach`
|
|
56
|
+
* (`TargetRegistry.handleAttached`), including cross-origin iframe targets —
|
|
57
|
+
* this only READS that bookkeeping, it never issues its own attach.
|
|
58
|
+
*
|
|
59
|
+
* Primary path: for OOPIF targets CDP guarantees `targetId == frameId` — an
|
|
60
|
+
* exact match against the surfaced node's own `frameId` is unambiguous by
|
|
61
|
+
* construction and needs no URL comparison at all.
|
|
62
|
+
*
|
|
63
|
+
* Fallback: match by url (ignoring query/hash and a trailing slash) when no
|
|
64
|
+
* exact frameId match is found (the same fallback design/04a documents for
|
|
65
|
+
* frames whose frameId can't be resolved directly). If MORE THAN ONE
|
|
66
|
+
* attached iframe target shares the same url key, the match is ambiguous —
|
|
67
|
+
* decline (`undefined`) rather than guess via first-attach order. An empty
|
|
68
|
+
* iframe is strictly better than grafting the wrong sibling frame's content.
|
|
69
|
+
*/
|
|
70
|
+
private resolveFrameTarget;
|
|
71
|
+
/** Launch a local Chromium subprocess and open a session against it. */
|
|
72
|
+
static launch(overrides?: BrowserConfigOverrides): Promise<BrowserSession>;
|
|
73
|
+
/**
|
|
74
|
+
* Attach to an existing CDP endpoint (`ws://…` or an `http://…/json/version`
|
|
75
|
+
* base). This is the first-class connect path — the same one a remote/cloud
|
|
76
|
+
* provider drives.
|
|
77
|
+
*/
|
|
78
|
+
static connect(cdpUrl: string, overrides?: BrowserConfigOverrides, options?: BrowserConnectOptions): Promise<BrowserSession>;
|
|
79
|
+
/** Discover targets, pick a focus, and begin auto-answering dialogs. Idempotent. */
|
|
80
|
+
start(): Promise<void>;
|
|
81
|
+
/** Tear down: stop dialogs, detach registry, close the socket and (if owned) the browser. */
|
|
82
|
+
stop(): Promise<void>;
|
|
83
|
+
/**
|
|
84
|
+
* Subscribe to the underlying CDP socket dropping unexpectedly (not on
|
|
85
|
+
* {@link stop}). Surfaces `CdpConnection.onDisconnect` at the session level so
|
|
86
|
+
* a host/provider can react — the seam to build a reconnect policy on
|
|
87
|
+
* (`reconnectWithBackoff` is the building block). The library takes NO reconnect
|
|
88
|
+
* action itself: on the `launch()` path a drop means the Chromium subprocess
|
|
89
|
+
* died (nothing to reconnect to), and on the `connect()` path the reconnect
|
|
90
|
+
* policy belongs to the provider that owns the endpoint. Returns an unsubscribe
|
|
91
|
+
* fn; a no-op if the transport doesn't surface disconnects.
|
|
92
|
+
*/
|
|
93
|
+
onDisconnect(cb: (err: CdpConnectionError) => void): () => void;
|
|
94
|
+
/** The open tabs (4-char ids). */
|
|
95
|
+
get tabs(): TabInfo[];
|
|
96
|
+
/** The selector map from the most recent {@link getBrowserStateSummary}. */
|
|
97
|
+
get selectorMap(): DomSelectorMap;
|
|
98
|
+
/** Resolve an element by its map key — the backendNodeId the LLM saw as `[N]`. */
|
|
99
|
+
getElementByIndex(index: number): EnhancedDOMTreeNode | undefined;
|
|
100
|
+
/** Navigate the focused tab (policy-checked before any CDP navigate — A3). */
|
|
101
|
+
navigate(url: string, options?: NavigateOptions): Promise<NavigateResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Assemble a full state summary for the focused tab: url + title + tabs +
|
|
104
|
+
* serialized numbered DOM text + selector map (+ optional screenshot). The
|
|
105
|
+
* selector map is cached so subsequent index-based actions resolve.
|
|
106
|
+
*/
|
|
107
|
+
getBrowserStateSummary(options?: BrowserStateOptions): Promise<BrowserStateSummary>;
|
|
108
|
+
/**
|
|
109
|
+
* Navigate the focused tab back one history entry (CDP navigation history).
|
|
110
|
+
* A no-op when there is nothing to go back to.
|
|
111
|
+
*/
|
|
112
|
+
goBack(): Promise<void>;
|
|
113
|
+
/**
|
|
114
|
+
* Evaluate a JS expression in the focused page and return the JSON value
|
|
115
|
+
* (`returnByValue`, promises awaited). Throws on a page-side exception
|
|
116
|
+
* instead of resolving to `undefined` — the seam {@link groundTruth}
|
|
117
|
+
* (`testing.ts`) builds on to assert real DOM effects (PRP T1) rather than
|
|
118
|
+
* a tool's self-report.
|
|
119
|
+
*/
|
|
120
|
+
evaluate<T = unknown>(expression: string): Promise<T>;
|
|
121
|
+
/** Open a new tab (browser-level Target.createTarget). Returns its 4-char id. */
|
|
122
|
+
openTab(url?: string): Promise<TabId>;
|
|
123
|
+
/** Focus another tab by its 4-char id, bringing it to the foreground. */
|
|
124
|
+
switchTab(tabId: TabId): Promise<void>;
|
|
125
|
+
/** Close a tab by its 4-char id (best-effort — a stale id is not an error). */
|
|
126
|
+
closeTab(tabId: TabId): Promise<void>;
|
|
127
|
+
/** Get the element by its backendNodeId key (branded overload of index access). */
|
|
128
|
+
nodeForKey(index: BackendNodeId): EnhancedDOMTreeNode | undefined;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../src/session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { TypedEmitter } from "../events";
|
|
2
|
+
import { type TabId, type TargetId } from "../types";
|
|
3
|
+
import type { CdpTransport } from "../types";
|
|
4
|
+
/** A recent Page lifecycle event kept in the per-target ring buffer. */
|
|
5
|
+
export interface LifecycleRecord {
|
|
6
|
+
name: string;
|
|
7
|
+
loaderId: string;
|
|
8
|
+
timestamp: number;
|
|
9
|
+
}
|
|
10
|
+
interface TargetRecord {
|
|
11
|
+
targetId: TargetId;
|
|
12
|
+
type: string;
|
|
13
|
+
url: string;
|
|
14
|
+
title: string;
|
|
15
|
+
}
|
|
16
|
+
/** Genuine target notifications (A1). */
|
|
17
|
+
export interface TargetRegistryEvents {
|
|
18
|
+
tabCreated: {
|
|
19
|
+
targetId: TargetId;
|
|
20
|
+
tabId: TabId;
|
|
21
|
+
url: string;
|
|
22
|
+
};
|
|
23
|
+
tabClosed: {
|
|
24
|
+
targetId: TargetId;
|
|
25
|
+
tabId: TabId;
|
|
26
|
+
};
|
|
27
|
+
focusChanged: {
|
|
28
|
+
targetId: TargetId;
|
|
29
|
+
url: string;
|
|
30
|
+
};
|
|
31
|
+
targetCrashed: {
|
|
32
|
+
targetId: TargetId;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** The last 4 chars of a target id — the only id the LLM ever sees (design/05). */
|
|
36
|
+
export declare const toTabId: (targetId: TargetId) => TabId;
|
|
37
|
+
export declare class TargetRegistry {
|
|
38
|
+
private readonly transport;
|
|
39
|
+
readonly events: TypedEmitter<TargetRegistryEvents>;
|
|
40
|
+
private readonly targets;
|
|
41
|
+
private readonly sessions;
|
|
42
|
+
private readonly targetSessions;
|
|
43
|
+
private readonly sessionToTarget;
|
|
44
|
+
private readonly lifecycleEvents;
|
|
45
|
+
private focusTargetId;
|
|
46
|
+
private recoveryInProgress;
|
|
47
|
+
private readonly unsubscribes;
|
|
48
|
+
constructor(transport: CdpTransport);
|
|
49
|
+
/** Register handlers and discover existing targets. */
|
|
50
|
+
start(): Promise<void>;
|
|
51
|
+
dispose(): void;
|
|
52
|
+
private handleAttached;
|
|
53
|
+
private handleDetached;
|
|
54
|
+
private handleInfoChanged;
|
|
55
|
+
private handleCrashed;
|
|
56
|
+
private handleLifecycle;
|
|
57
|
+
private enablePageMonitoring;
|
|
58
|
+
get focusedTargetId(): TargetId | undefined;
|
|
59
|
+
/** Focus a target. Only page-type targets may become the focus. */
|
|
60
|
+
setFocus(targetId: TargetId): boolean;
|
|
61
|
+
private recoverFocus;
|
|
62
|
+
getPageTargets(): TargetRecord[];
|
|
63
|
+
/** TabInfo-ready view of the page targets (4-char ids). */
|
|
64
|
+
getTabs(): Array<{
|
|
65
|
+
id: TabId;
|
|
66
|
+
url: string;
|
|
67
|
+
title: string;
|
|
68
|
+
}>;
|
|
69
|
+
getTargetIdFromTabId(tabId: TabId): TargetId | undefined;
|
|
70
|
+
getSessionIdForTarget(targetId: TargetId): string | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Attached targets of CDP type `"iframe"` (out-of-process/cross-origin
|
|
73
|
+
* iframes), with their url + session id. `Target.setAutoAttach` (called for
|
|
74
|
+
* every attached session in {@link handleAttached}) already cascades to these
|
|
75
|
+
* automatically — nothing here issues a new `attachToTarget`, so a caller
|
|
76
|
+
* matching a frame by url gets an existing session, never a fresh attach.
|
|
77
|
+
* Used by `BrowserSession`'s `FrameTargetResolver` (W3/W3b): for OOPIF
|
|
78
|
+
* targets CDP guarantees `targetId == frameId`, so the resolver's primary
|
|
79
|
+
* path matches `targetId` directly against the surfaced node's frameId.
|
|
80
|
+
* The `targetId` returned here is what makes that possible — url-matching
|
|
81
|
+
* (also exposed here) is only the fallback for when that invariant doesn't
|
|
82
|
+
* resolve a match; it is NOT the only resolution signal the registry offers.
|
|
83
|
+
*/
|
|
84
|
+
getIframeTargets(): Array<{
|
|
85
|
+
targetId: TargetId;
|
|
86
|
+
url: string;
|
|
87
|
+
sessionId: string;
|
|
88
|
+
}>;
|
|
89
|
+
getCurrentUrl(targetId: TargetId): string | undefined;
|
|
90
|
+
getLifecycleEvents(targetId: TargetId): LifecycleRecord[];
|
|
91
|
+
/** For the Navigator's focus provider. */
|
|
92
|
+
getFocusedSession(): {
|
|
93
|
+
targetId: TargetId;
|
|
94
|
+
sessionId: string;
|
|
95
|
+
} | undefined;
|
|
96
|
+
private getLifecycleBuffer;
|
|
97
|
+
}
|
|
98
|
+
export {};
|
|
99
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/targets/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { CdpConnectionError } from "./errors";
|
|
2
|
+
import type { CdpCommand, CdpCommandParams, CdpCommandReturn, CdpEventListener, CdpEventName, CdpEventParams, CdpSendOptions, CdpTransport } from "./types";
|
|
3
|
+
/** A scripted response: a fixed value, or a fn of the call's params/sessionId. */
|
|
4
|
+
export type FakeResponder = unknown | ((params: unknown, sessionId?: string) => unknown);
|
|
5
|
+
/**
|
|
6
|
+
* A {@link CdpTransport} backed by a scripted `method -> response` map, with a
|
|
7
|
+
* multi-listener event registry and an {@link emitEvent} to push canned events.
|
|
8
|
+
* Every `send` is recorded in {@link calls} so tests can assert what was (or was
|
|
9
|
+
* NOT) sent. Unknown methods resolve to `{}`.
|
|
10
|
+
*/
|
|
11
|
+
export declare class FakeCdpTransport implements CdpTransport {
|
|
12
|
+
private readonly responses;
|
|
13
|
+
/** Every `send` in order, for assertions. */
|
|
14
|
+
readonly calls: Array<{
|
|
15
|
+
method: string;
|
|
16
|
+
params?: unknown;
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
}>;
|
|
19
|
+
private readonly registrations;
|
|
20
|
+
private readonly disconnectListeners;
|
|
21
|
+
constructor(responses?: Map<string, FakeResponder>);
|
|
22
|
+
send<T extends CdpCommand>(method: T, params?: CdpCommandParams<T>, options?: CdpSendOptions): Promise<CdpCommandReturn<T>>;
|
|
23
|
+
on<M extends CdpEventName>(method: M, listener: CdpEventListener<M>, sessionId?: string): () => void;
|
|
24
|
+
/** Push a canned CDP event to matching subscribers. */
|
|
25
|
+
emitEvent<M extends CdpEventName>(method: M, params: CdpEventParams<M>, sessionId?: string): void;
|
|
26
|
+
onDisconnect(cb: (err: CdpConnectionError) => void): () => void;
|
|
27
|
+
/** Simulate an unexpected socket drop for tests. */
|
|
28
|
+
emitDisconnect(err: CdpConnectionError): void;
|
|
29
|
+
/** Number of `send`s recorded for a method. */
|
|
30
|
+
sendCount(method: string): number;
|
|
31
|
+
close(): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
/** The minimal session surface {@link groundTruth} needs — real `BrowserSession` satisfies it. */
|
|
34
|
+
export interface EvaluableSession {
|
|
35
|
+
evaluate<T = unknown>(expression: string): Promise<T>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Ground-truth assertions for interaction tests (PRP T1): reads the real DOM
|
|
39
|
+
* effect via CDP `Runtime.evaluate`, not the tool's self-report. Backed by
|
|
40
|
+
* `session.evaluate()`; unit-tested here against {@link FakeCdpTransport},
|
|
41
|
+
* driven against real Chromium once the W9(c) browser-gated tier exists.
|
|
42
|
+
*/
|
|
43
|
+
export declare function groundTruth(session: EvaluableSession): {
|
|
44
|
+
/** Evaluate an arbitrary expression in the page and return the JSON value. */
|
|
45
|
+
evalInPage: <T = unknown>(expression: string) => Promise<T>;
|
|
46
|
+
/** `window.getClickCount()` — the golden-fixture click-counter contract (design/08-09 §9.3). */
|
|
47
|
+
clickCount: () => Promise<number>;
|
|
48
|
+
/** The live `.value` of the element matched by `selector`. */
|
|
49
|
+
inputValue: (selector: string) => Promise<string>;
|
|
50
|
+
/** The live `.checked` of the element matched by `selector`. */
|
|
51
|
+
checked: (selector: string) => Promise<boolean>;
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=testing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AACnD,OAAO,KAAK,EACV,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB,kFAAkF;AAClF,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;AAOzF;;;;;GAKG;AACH,qBAAa,gBAAiB,YAAW,YAAY;IAMvC,OAAO,CAAC,QAAQ,CAAC,SAAS;IALtC,6CAA6C;IAC7C,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAM;IACrF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAA4C;IAC1E,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAgD;gBAEvD,SAAS,GAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAa;IAExE,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;IAU/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;IAiBb,uDAAuD;IACvD,SAAS,CAAC,CAAC,SAAS,YAAY,EAC9B,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,EACzB,SAAS,CAAC,EAAE,MAAM,GACjB,IAAI;IAUP,YAAY,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,GAAG,MAAM,IAAI;IAO/D,oDAAoD;IACpD,cAAc,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI;IAI7C,+CAA+C;IAC/C,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAI3B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B;AAED,kGAAkG;AAClG,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACvD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,gBAAgB;IAEjD,8EAA8E;iBACjE,CAAC,wBAAwB,MAAM,KAAG,OAAO,CAAC,CAAC,CAAC;IACzD,gGAAgG;sBAChF,OAAO,CAAC,MAAM,CAAC;IAC/B,8DAA8D;2BACvC,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;IAE/C,gEAAgE;wBAC5C,MAAM,KAAG,OAAO,CAAC,OAAO,CAAC;EAGhD"}
|
package/dist/testing.js
ADDED
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { ProtocolMapping } from "devtools-protocol/types/protocol-mapping";
|
|
2
|
+
import type { CdpConnectionError } from "./errors";
|
|
3
|
+
/** A stable index into the interactive-element selector map. */
|
|
4
|
+
export type ElementIndex = number & {
|
|
5
|
+
readonly __brand: "ElementIndex";
|
|
6
|
+
};
|
|
7
|
+
/** A CDP backend node id (`DOM.BackendNodeId`). */
|
|
8
|
+
export type BackendNodeId = number & {
|
|
9
|
+
readonly __brand: "BackendNodeId";
|
|
10
|
+
};
|
|
11
|
+
/** A CDP target id (`Target.TargetID`). */
|
|
12
|
+
export type TargetId = string & {
|
|
13
|
+
readonly __brand: "TargetId";
|
|
14
|
+
};
|
|
15
|
+
/** An AP3X-side tab identifier (the 4-char id the LLM sees). */
|
|
16
|
+
export type TabId = string & {
|
|
17
|
+
readonly __brand: "TabId";
|
|
18
|
+
};
|
|
19
|
+
export declare const asElementIndex: (n: number) => ElementIndex;
|
|
20
|
+
export declare const asBackendNodeId: (n: number) => BackendNodeId;
|
|
21
|
+
export declare const asTargetId: (s: string) => TargetId;
|
|
22
|
+
export declare const asTabId: (s: string) => TabId;
|
|
23
|
+
/** A CDP command method name (e.g. `"Page.navigate"`). */
|
|
24
|
+
export type CdpCommand = keyof ProtocolMapping.Commands;
|
|
25
|
+
/** A CDP event method name (e.g. `"Page.lifecycleEvent"`). */
|
|
26
|
+
export type CdpEventName = keyof ProtocolMapping.Events;
|
|
27
|
+
/**
|
|
28
|
+
* The params object for a CDP command. No-param commands resolve to `never`,
|
|
29
|
+
* so combined with an optional `params?` they simply take no argument.
|
|
30
|
+
*/
|
|
31
|
+
export type CdpCommandParams<T extends CdpCommand> = ProtocolMapping.Commands[T]["paramsType"][number];
|
|
32
|
+
/** The response object for a CDP command. */
|
|
33
|
+
export type CdpCommandReturn<T extends CdpCommand> = ProtocolMapping.Commands[T]["returnType"];
|
|
34
|
+
/** The params object carried by a CDP event. */
|
|
35
|
+
export type CdpEventParams<M extends CdpEventName> = ProtocolMapping.Events[M][number];
|
|
36
|
+
/** Per-request send options. */
|
|
37
|
+
export interface CdpSendOptions {
|
|
38
|
+
/** Route to a specific target session (flatten mode). */
|
|
39
|
+
sessionId?: string;
|
|
40
|
+
/** Caller abort; merged with the per-request timeout. */
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
/** Override the default per-request timeout (ms). */
|
|
43
|
+
timeoutMs?: number;
|
|
44
|
+
}
|
|
45
|
+
/** A CDP event listener; receives typed params and the originating sessionId. */
|
|
46
|
+
export type CdpEventListener<M extends CdpEventName> = (params: CdpEventParams<M>, sessionId: string | undefined) => void;
|
|
47
|
+
/**
|
|
48
|
+
* Typed Chrome DevTools Protocol transport. `send` is request/response-typed by
|
|
49
|
+
* the protocol; `on` is a multi-listener registry keyed on (method, sessionId?)
|
|
50
|
+
* — a listener with no `sessionId` sees every session's events for that method.
|
|
51
|
+
*/
|
|
52
|
+
export interface CdpTransport {
|
|
53
|
+
send<T extends CdpCommand>(method: T, params?: CdpCommandParams<T>, options?: CdpSendOptions): Promise<CdpCommandReturn<T>>;
|
|
54
|
+
/** Subscribe to a CDP event. Returns an unsubscribe fn. */
|
|
55
|
+
on<M extends CdpEventName>(method: M, listener: CdpEventListener<M>, sessionId?: string): () => void;
|
|
56
|
+
close(): Promise<void>;
|
|
57
|
+
/**
|
|
58
|
+
* Subscribe to the socket dropping unexpectedly (NOT on {@link close}). Returns
|
|
59
|
+
* an unsubscribe fn. Optional — a transport with no live socket (a bridge, a
|
|
60
|
+
* fake) may omit it. This is the seam a host/provider builds a reconnect policy
|
|
61
|
+
* on (see `reconnectWithBackoff`); the library takes no reconnect action itself.
|
|
62
|
+
*/
|
|
63
|
+
onDisconnect?(cb: (err: CdpConnectionError) => void): () => void;
|
|
64
|
+
}
|
|
65
|
+
/** One open tab in the controlled browser. `id` is the 4-char {@link TabId}. */
|
|
66
|
+
export interface TabInfo {
|
|
67
|
+
id: TabId;
|
|
68
|
+
url: string;
|
|
69
|
+
title: string;
|
|
70
|
+
/** Parent page for popups / OOPIFs, if any. */
|
|
71
|
+
parentId?: TabId;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* A snapshot of browser state handed to the agent — the @ap3x/browser ↔
|
|
75
|
+
* browser-agent seam (PRP A6). `serializedText` is the numbered/indented text
|
|
76
|
+
* projection the consumer reads; `selectorMap` is keyed by CDP backendNodeId
|
|
77
|
+
* (the `[N]` in the text == the key == what getElementByIndex resolves). No
|
|
78
|
+
* LLM-memory vocabulary lives here.
|
|
79
|
+
*/
|
|
80
|
+
export interface BrowserStateSummary {
|
|
81
|
+
url: string;
|
|
82
|
+
title: string;
|
|
83
|
+
tabs: TabInfo[];
|
|
84
|
+
screenshot?: string;
|
|
85
|
+
serializedText: string;
|
|
86
|
+
selectorMap: import("./dom/types").DomSelectorMap;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ap3x/browser",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Chrome DevTools Protocol browser control primitives",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/AP3X-Dev/AP3X.git",
|
|
8
|
+
"directory": "packages/browser"
|
|
9
|
+
},
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"publishConfig": {
|
|
12
|
+
"access": "public"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"default": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./testing": {
|
|
23
|
+
"types": "./dist/testing.d.ts",
|
|
24
|
+
"default": "./dist/testing.js"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"files": ["dist"],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsup src/index.ts src/testing.ts --format esm --clean --tsconfig tsconfig.build.json && tsc -p tsconfig.build.json",
|
|
30
|
+
"prepublishOnly": "node ../../scripts/publish-gate.mjs",
|
|
31
|
+
"test": "vitest run"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@sinclair/typebox": "^0.34.49",
|
|
35
|
+
"devtools-protocol": "^0.0.1464554",
|
|
36
|
+
"ws": "^8.18.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/ws": "^8.18.0",
|
|
40
|
+
"fast-check": "^4.8.0"
|
|
41
|
+
}
|
|
42
|
+
}
|