@achamm/veilbrowser 0.3.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/dist/page.d.ts ADDED
@@ -0,0 +1,194 @@
1
+ /**
2
+ * The agent-facing page API.
3
+ *
4
+ * Design goal: an LLM agent should never write a CSS/XPath selector. Selectors
5
+ * are the #1 source of automation breakage. Instead, `snapshot()` returns the
6
+ * page as a flat, numbered list of meaningful elements pulled from Chrome's
7
+ * accessibility tree — the same semantic layer a screen reader sees. The agent
8
+ * acts on a stable integer `ref`; we resolve the geometry and drive real input.
9
+ */
10
+ import type { CDP } from "./cdp.js";
11
+ import { type Point } from "./human.js";
12
+ export interface Element {
13
+ ref: number;
14
+ role: string;
15
+ name: string;
16
+ value?: string;
17
+ center: Point;
18
+ }
19
+ export interface Snapshot {
20
+ url: string;
21
+ title: string;
22
+ /** Human/agent-readable index, e.g. `[3] button "Sign in"`. */
23
+ text: string;
24
+ elements: Element[];
25
+ }
26
+ /** One account offered in a FedCM account chooser. */
27
+ export interface FedCmAccount {
28
+ accountId: string;
29
+ email?: string;
30
+ name?: string;
31
+ givenName?: string;
32
+ idpConfigUrl?: string;
33
+ }
34
+ /** A FedCM dialog Chrome would normally render as native browser UI. */
35
+ export interface FedCmDialog {
36
+ dialogId: string;
37
+ /** "AccountChooser" | "AutoReauthn" | "ConfirmIdpLogin" | "SelectAccount" ... */
38
+ type: string;
39
+ title?: string;
40
+ subtitle?: string;
41
+ accounts: FedCmAccount[];
42
+ }
43
+ /**
44
+ * True if `url` targets a loopback / private-network host. Fingerprinters
45
+ * (iphey, pixelscan, …) port-scan these from page JS to profile the machine's
46
+ * OTHER software — VNC on :5900, a local automation API on :3001, etc. — which
47
+ * also leaks your LAN to every site you visit. Exotic IP encodings (decimal,
48
+ * hex) are a known gap; real-world scanners use the canonical forms below.
49
+ */
50
+ export declare function isPrivateHost(url: string): boolean;
51
+ export declare class Page {
52
+ private cdp;
53
+ readonly sessionId: string;
54
+ private targetId?;
55
+ private rng;
56
+ private mouse;
57
+ private refs;
58
+ private closed;
59
+ private fedcmOff?;
60
+ private fedcmQueue;
61
+ private fedcmWaiters;
62
+ private lastFedcmDialogId?;
63
+ private blockPrivateOff?;
64
+ private mainFrameId?;
65
+ private topPrivate;
66
+ constructor(cdp: CDP, sessionId: string, targetId?: string | undefined);
67
+ /** Enable the domains we use and arm stealth injection on every document. */
68
+ init(opts?: {
69
+ maskWebgl?: boolean;
70
+ blockPrivateNetwork?: boolean;
71
+ }): Promise<void>;
72
+ /**
73
+ * Inject cookies before navigating — e.g. a logged-in session transferred
74
+ * from another browser. Each cookie is a CDP CookieParam ({name, value,
75
+ * domain, path, secure, httpOnly, expires?, sameSite?}). Lets the browser
76
+ * ride an existing session instead of re-doing a bot-walled login.
77
+ */
78
+ setCookies(cookies: Array<Record<string, any>>): Promise<void>;
79
+ /**
80
+ * Scrub the "HeadlessChrome" token from the UA and the matching client-hint
81
+ * brands. headless=new leaks it in both navigator.userAgent AND the Sec-CH-UA
82
+ * request headers; setUserAgentOverride with metadata fixes both at once. A
83
+ * no-op for headful Chrome, whose UA is already clean.
84
+ */
85
+ private normalizeUserAgent;
86
+ private send;
87
+ /** Navigate and wait for the load event. */
88
+ goto(url: string, opts?: {
89
+ timeout?: number;
90
+ }): Promise<void>;
91
+ /** Evaluate JS in the page WITHOUT Runtime.enable (avoids the CDP tell). */
92
+ evaluate<T = any>(expression: string): Promise<T>;
93
+ url(): Promise<string>;
94
+ /** Build the numbered element index from the accessibility tree. */
95
+ snapshot(): Promise<Snapshot>;
96
+ private boxCenter;
97
+ /** Move the cursor along a human curve to a target point. */
98
+ private moveTo;
99
+ /** Click an element by its snapshot ref. */
100
+ click(ref: number): Promise<void>;
101
+ /** Bring this page's target to the foreground — CDP Input only routes to the active target. */
102
+ bringToFront(): Promise<void>;
103
+ /** Trusted click at absolute viewport coords (when you can't resolve a snapshot ref). */
104
+ clickAt(x: number, y: number): Promise<void>;
105
+ /** Type text into the focused element with human cadence. */
106
+ type(text: string): Promise<void>;
107
+ /** Click a field then type into it. */
108
+ fill(ref: number, text: string): Promise<void>;
109
+ /** Capture a PNG screenshot (Buffer) — feed to a vision model. */
110
+ screenshot(opts?: {
111
+ fullPage?: boolean;
112
+ }): Promise<Buffer>;
113
+ /** Poll an expression until truthy (replaces flaky fixed sleeps). */
114
+ waitFor(expression: string, opts?: {
115
+ timeout?: number;
116
+ poll?: number;
117
+ }): Promise<void>;
118
+ /**
119
+ * Attach local files to a file `<input>` — even a hidden one — without an OS
120
+ * file picker. Uses CDP DOM.setFileInputFiles (the same primitive Playwright
121
+ * uses under the hood), which sets `input.files` and fires `change` directly.
122
+ * `selector` defaults to the first file input; pass a more specific one if the
123
+ * page has several. Paths must be absolute.
124
+ */
125
+ uploadFile(paths: string[], selector?: string): Promise<void>;
126
+ /**
127
+ * Attach files through a control that opens a file picker (e.g. an "Upload
128
+ * files" menu item) WITHOUT an OS dialog. Intercepts the chooser via CDP,
129
+ * clicks the trigger, then feeds the paths to the input it opened for. This is
130
+ * the path for SPAs (like Gemini) that create the `<input>` lazily on click.
131
+ * Paths must be absolute.
132
+ */
133
+ uploadViaPicker(triggerRef: number, paths: string[], opts?: {
134
+ timeout?: number;
135
+ }): Promise<void>;
136
+ /** Read the page's visible text (for scraping a model response, etc.). */
137
+ innerText(): Promise<string>;
138
+ /** Press a single named key on the focused element (Enter, Tab, Escape, arrows...). */
139
+ press(key: string): Promise<void>;
140
+ /**
141
+ * Start intercepting FedCM on this page. Call it ON DEMAND, right before the
142
+ * sign-in you're driving — never as blanket startup setup. Any page that
143
+ * silently probes FedCM at load (GoHighLevel, many SaaS logins) will HANG if
144
+ * interception is on and nothing resolves the probe, so keep it off until you
145
+ * need it and disableFedCm() afterwards.
146
+ *
147
+ * With {autoSelectFirst:true} (default) veil selects account 0 on every dialog
148
+ * automatically — the one-liner for "just sign me in". Pass false to inspect
149
+ * accounts via waitForFedCmDialog() and choose with selectFedCmAccount().
150
+ */
151
+ enableFedCm(opts?: {
152
+ autoSelectFirst?: boolean;
153
+ }): Promise<void>;
154
+ /** Resolve with the next FedCM dialog (or one already queued since enable). */
155
+ waitForFedCmDialog(opts?: {
156
+ timeout?: number;
157
+ }): Promise<FedCmDialog>;
158
+ /** Pick an account in the current FedCM dialog (index into dialog.accounts). */
159
+ selectFedCmAccount(accountIndex?: number, dialogId?: string | undefined): Promise<void>;
160
+ /** Dismiss the current FedCM dialog (decline the sign-in). */
161
+ dismissFedCm(dialogId?: string | undefined): Promise<void>;
162
+ /** Stop intercepting FedCM. Call after a sign-in so a later navigation that
163
+ * probes FedCM isn't left hanging on us. */
164
+ disableFedCm(): Promise<void>;
165
+ /**
166
+ * One call to complete an active federated sign-in: enables FedCM, clicks the
167
+ * "Sign in with Google" button (a snapshot ref), waits for the account
168
+ * chooser, selects an account, and returns it. For passive/one-tap flows that
169
+ * fire on page load, enableFedCm() BEFORE navigating, then
170
+ * waitForFedCmDialog() — the default autoSelectFirst signs you straight in.
171
+ */
172
+ signInWithFedCm(opts?: {
173
+ triggerRef?: number;
174
+ accountIndex?: number;
175
+ timeout?: number;
176
+ }): Promise<FedCmAccount>;
177
+ /**
178
+ * Stop the page — and any site it loads — from reaching loopback / private
179
+ * hosts. Detectors port-scan 127.0.0.1 from JS to fingerprint the machine's
180
+ * other software (and it leaks your LAN to every site). With this on, each
181
+ * such request is failed UNIFORMLY (same instant error, open port or closed),
182
+ * so the scan can't tell them apart and comes back empty. Only private-host
183
+ * requests are intercepted, so normal browsing keeps its exact timing.
184
+ *
185
+ * Still allowed: the agent's own top-level navigation to a private host
186
+ * (page.goto("http://localhost:3000")), and a localhost page loading its own
187
+ * localhost resources — only a PUBLIC page reaching a private host is blocked.
188
+ */
189
+ blockPrivateNetwork(): Promise<void>;
190
+ /** Lift the private-network block (re-allows localhost/LAN requests). */
191
+ unblockPrivateNetwork(): Promise<void>;
192
+ /** Close this page and detach its target from the browser. Idempotent. */
193
+ close(): Promise<void>;
194
+ }