@celestea/tools 2.7.1
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/dist/args.d.ts +15 -0
- package/dist/args.js +55 -0
- package/dist/attachments/image-header.d.ts +28 -0
- package/dist/attachments/image-header.js +148 -0
- package/dist/attachments/store.d.ts +56 -0
- package/dist/attachments/store.js +148 -0
- package/dist/browser/cdp.d.ts +162 -0
- package/dist/browser/cdp.js +269 -0
- package/dist/browser/launch.d.ts +92 -0
- package/dist/browser/launch.js +232 -0
- package/dist/browser/memory-guard.d.ts +55 -0
- package/dist/browser/memory-guard.js +210 -0
- package/dist/browser/session.d.ts +146 -0
- package/dist/browser/session.js +371 -0
- package/dist/browser/snapshot.d.ts +69 -0
- package/dist/browser/snapshot.js +163 -0
- package/dist/browser/types.d.ts +51 -0
- package/dist/browser/types.js +8 -0
- package/dist/builtin.d.ts +54 -0
- package/dist/builtin.js +77 -0
- package/dist/desc.d.ts +20 -0
- package/dist/desc.js +22 -0
- package/dist/disclosure.d.ts +113 -0
- package/dist/disclosure.js +141 -0
- package/dist/env.d.ts +10 -0
- package/dist/env.js +33 -0
- package/dist/errors.d.ts +25 -0
- package/dist/errors.js +60 -0
- package/dist/exposure.d.ts +145 -0
- package/dist/exposure.js +244 -0
- package/dist/fn-tool.d.ts +14 -0
- package/dist/fn-tool.js +14 -0
- package/dist/fs/file-io.d.ts +78 -0
- package/dist/fs/file-io.js +239 -0
- package/dist/guard/path-guard.d.ts +144 -0
- package/dist/guard/path-guard.js +289 -0
- package/dist/guard/paths.d.ts +35 -0
- package/dist/guard/paths.js +100 -0
- package/dist/http/errors.d.ts +24 -0
- package/dist/http/errors.js +64 -0
- package/dist/http/headers.d.ts +19 -0
- package/dist/http/headers.js +62 -0
- package/dist/http/redirects.d.ts +31 -0
- package/dist/http/redirects.js +76 -0
- package/dist/http/ssrf.d.ts +105 -0
- package/dist/http/ssrf.js +272 -0
- package/dist/http/transport.d.ts +50 -0
- package/dist/http/transport.js +130 -0
- package/dist/index.d.ts +114 -0
- package/dist/index.js +129 -0
- package/dist/memory/log.d.ts +75 -0
- package/dist/memory/log.js +157 -0
- package/dist/memory/store.d.ts +47 -0
- package/dist/memory/store.js +61 -0
- package/dist/platform/exec.d.ts +79 -0
- package/dist/platform/exec.js +218 -0
- package/dist/platform/index.d.ts +12 -0
- package/dist/platform/index.js +12 -0
- package/dist/platform/paths.d.ts +51 -0
- package/dist/platform/paths.js +60 -0
- package/dist/platform/quote.d.ts +72 -0
- package/dist/platform/quote.js +102 -0
- package/dist/plugin.d.ts +96 -0
- package/dist/plugin.js +101 -0
- package/dist/process/buffers.d.ts +33 -0
- package/dist/process/buffers.js +86 -0
- package/dist/process/registry.d.ts +98 -0
- package/dist/process/registry.js +282 -0
- package/dist/registry.d.ts +52 -0
- package/dist/registry.js +161 -0
- package/dist/run-code/broker.d.ts +68 -0
- package/dist/run-code/broker.js +465 -0
- package/dist/run-code/limits.d.ts +69 -0
- package/dist/run-code/limits.js +88 -0
- package/dist/run-code/lines.d.ts +69 -0
- package/dist/run-code/lines.js +199 -0
- package/dist/run-code/sdk-ts.d.ts +34 -0
- package/dist/run-code/sdk-ts.js +276 -0
- package/dist/run-code/sdk.d.ts +39 -0
- package/dist/run-code/sdk.js +294 -0
- package/dist/sandbox/async.d.ts +10 -0
- package/dist/sandbox/async.js +26 -0
- package/dist/sandbox/bwrap-argv.d.ts +62 -0
- package/dist/sandbox/bwrap-argv.js +113 -0
- package/dist/sandbox/bwrap.d.ts +94 -0
- package/dist/sandbox/bwrap.js +159 -0
- package/dist/sandbox/child.d.ts +38 -0
- package/dist/sandbox/child.js +98 -0
- package/dist/sandbox/config.d.ts +89 -0
- package/dist/sandbox/config.js +149 -0
- package/dist/sandbox/fake-sandbox.d.ts +57 -0
- package/dist/sandbox/fake-sandbox.js +110 -0
- package/dist/sandbox/launch.d.ts +51 -0
- package/dist/sandbox/launch.js +134 -0
- package/dist/sandbox/limits.d.ts +63 -0
- package/dist/sandbox/limits.js +113 -0
- package/dist/sandbox/probe.d.ts +46 -0
- package/dist/sandbox/probe.js +102 -0
- package/dist/sandbox/provider.d.ts +83 -0
- package/dist/sandbox/provider.js +126 -0
- package/dist/sandbox/rlimit.d.ts +60 -0
- package/dist/sandbox/rlimit.js +76 -0
- package/dist/sandbox/seccomp.d.ts +48 -0
- package/dist/sandbox/seccomp.js +115 -0
- package/dist/sandbox/userspace.d.ts +65 -0
- package/dist/sandbox/userspace.js +107 -0
- package/dist/sandbox/workdir.d.ts +13 -0
- package/dist/sandbox/workdir.js +44 -0
- package/dist/schema.d.ts +20 -0
- package/dist/schema.js +135 -0
- package/dist/testing/platform-gates.d.ts +54 -0
- package/dist/testing/platform-gates.js +62 -0
- package/dist/tool-failure.d.ts +13 -0
- package/dist/tool-failure.js +19 -0
- package/dist/tools/ask-user.d.ts +32 -0
- package/dist/tools/ask-user.js +145 -0
- package/dist/tools/browser.d.ts +24 -0
- package/dist/tools/browser.js +132 -0
- package/dist/tools/http-request.d.ts +31 -0
- package/dist/tools/http-request.js +117 -0
- package/dist/tools/list-dir.d.ts +9 -0
- package/dist/tools/list-dir.js +45 -0
- package/dist/tools/load-skill.d.ts +37 -0
- package/dist/tools/load-skill.js +76 -0
- package/dist/tools/memory.d.ts +46 -0
- package/dist/tools/memory.js +131 -0
- package/dist/tools/process-control.d.ts +14 -0
- package/dist/tools/process-control.js +49 -0
- package/dist/tools/read-file.d.ts +11 -0
- package/dist/tools/read-file.js +81 -0
- package/dist/tools/read-image.d.ts +33 -0
- package/dist/tools/read-image.js +144 -0
- package/dist/tools/run-code.d.ts +48 -0
- package/dist/tools/run-code.js +115 -0
- package/dist/tools/run-shell.d.ts +22 -0
- package/dist/tools/run-shell.js +81 -0
- package/dist/tools/write-file.d.ts +8 -0
- package/dist/tools/write-file.js +31 -0
- package/package.json +28 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F4 step 2b: the memory backstop for an RLIMIT_AS-exempted browser.
|
|
3
|
+
*
|
|
4
|
+
* Exempting RLIMIT_AS (step 2a) removes the sandbox's only virtual-memory
|
|
5
|
+
* bound, so this module re-establishes a REAL one, in this order:
|
|
6
|
+
*
|
|
7
|
+
* 1. **cgroup v2 memory.max** — exact and kernel-enforced, but only when the
|
|
8
|
+
* service's cgroup is delegated (writable). Measured on the target host:
|
|
9
|
+
* /sys/fs/cgroup is read-only (mkdir -> EACCES), so this path is attempted
|
|
10
|
+
* and honestly reported as unavailable.
|
|
11
|
+
* 2. **bounded RSS watchdog** — sample the process tree's VmRSS on an interval
|
|
12
|
+
* and SIGKILL the tree when it exceeds the cap. This is BOUNDED but not
|
|
13
|
+
* instantaneous: a fast allocator can overshoot by one sampling window.
|
|
14
|
+
* 3. **none** — no /proc, no pid: reported as "none" with the reason. Never
|
|
15
|
+
* silently claimed as protected.
|
|
16
|
+
*
|
|
17
|
+
* The guard is deliberately injectable (readRssKb / killTree / cgroupRoot) so
|
|
18
|
+
* the watchdog logic is unit-tested without allocating real memory.
|
|
19
|
+
*/
|
|
20
|
+
import { mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
21
|
+
import { join } from "node:path";
|
|
22
|
+
/** Default cap: 1 GiB of RSS for one browser tree. */
|
|
23
|
+
export const DEFAULT_BROWSER_MEMORY_MB = 1024;
|
|
24
|
+
/** Default sampling window. */
|
|
25
|
+
export const DEFAULT_RSS_INTERVAL_MS = 500;
|
|
26
|
+
/** Arm the strongest available backstop; always returns a truthful status. */
|
|
27
|
+
export function armMemoryGuard(options) {
|
|
28
|
+
const pid = options.pid;
|
|
29
|
+
const limitMb = options.limitMb;
|
|
30
|
+
if (pid === null || pid === undefined)
|
|
31
|
+
return noneGuard("no pid: nothing to watch");
|
|
32
|
+
const cgroup = tryCgroupGuard(pid, limitMb, options);
|
|
33
|
+
if (cgroup !== null)
|
|
34
|
+
return cgroup;
|
|
35
|
+
return rssGuard(pid, limitMb, options);
|
|
36
|
+
}
|
|
37
|
+
/** Attempt cgroup v2 memory.max; null when the hierarchy is not writable. */
|
|
38
|
+
function tryCgroupGuard(pid, limitMb, options) {
|
|
39
|
+
const root = options.cgroupRoot ?? "/sys/fs/cgroup";
|
|
40
|
+
const path = options.cgroupPath === undefined ? readOwnCgroupPath() : options.cgroupPath;
|
|
41
|
+
if (path === null)
|
|
42
|
+
return null;
|
|
43
|
+
const dir = join(root, path, "celestea-browser-" + pid);
|
|
44
|
+
try {
|
|
45
|
+
mkdirSync(dir, { recursive: false });
|
|
46
|
+
writeFileSync(join(dir, "memory.max"), String(limitMb * 1024 * 1024));
|
|
47
|
+
writeFileSync(join(dir, "cgroup.procs"), String(pid));
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Not delegated / read-only / already exists: clean up and fall back.
|
|
51
|
+
try {
|
|
52
|
+
rmSync(dir, { recursive: true, force: true });
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
/* best effort */
|
|
56
|
+
}
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const status = {
|
|
60
|
+
kind: "cgroup-v2",
|
|
61
|
+
limit_mb: limitMb,
|
|
62
|
+
detail: "cgroup v2 memory.max=" + limitMb + "MiB at " + dir + " (kernel-enforced)",
|
|
63
|
+
killed: false,
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
status: () => ({ ...status }),
|
|
67
|
+
dispose: () => {
|
|
68
|
+
try {
|
|
69
|
+
rmSync(dir, { recursive: true, force: true });
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
/* the kernel keeps the cgroup until the last task leaves */
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Read this process's own cgroup v2 path from /proc/self/cgroup. */
|
|
78
|
+
export function readOwnCgroupPath(procRoot = "/proc") {
|
|
79
|
+
try {
|
|
80
|
+
const text = readFileSync(join(procRoot, "self", "cgroup"), "utf8");
|
|
81
|
+
for (const line of text.split("\n")) {
|
|
82
|
+
const parts = line.split(":");
|
|
83
|
+
if (parts.length >= 3 && parts[0] === "0")
|
|
84
|
+
return parts[2] ?? null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
/** Bounded RSS watchdog: sample, kill on overshoot, report the window. */
|
|
93
|
+
function rssGuard(pid, limitMb, options) {
|
|
94
|
+
const readRss = options.readRssKb ?? readTreeRssKb;
|
|
95
|
+
const killTree = options.killTree ?? defaultKillTree;
|
|
96
|
+
const intervalMs = options.intervalMs ?? DEFAULT_RSS_INTERVAL_MS;
|
|
97
|
+
let killed = false;
|
|
98
|
+
let lastKb = null;
|
|
99
|
+
const timer = setInterval(() => {
|
|
100
|
+
if (killed)
|
|
101
|
+
return;
|
|
102
|
+
const kb = readRss(pid);
|
|
103
|
+
lastKb = kb;
|
|
104
|
+
if (kb !== null && kb / 1024 > limitMb) {
|
|
105
|
+
killed = true;
|
|
106
|
+
killTree(pid);
|
|
107
|
+
clearInterval(timer);
|
|
108
|
+
}
|
|
109
|
+
}, intervalMs);
|
|
110
|
+
timer.unref();
|
|
111
|
+
return {
|
|
112
|
+
status: () => ({
|
|
113
|
+
kind: "rss-watchdog",
|
|
114
|
+
limit_mb: limitMb,
|
|
115
|
+
detail: "cgroup v2 memory.max unavailable (read-only hierarchy); sampling the tree's VmRSS every " +
|
|
116
|
+
intervalMs +
|
|
117
|
+
"ms against a " +
|
|
118
|
+
limitMb +
|
|
119
|
+
"MiB cap" +
|
|
120
|
+
(lastKb === null ? "" : " (last sample " + Math.round(lastKb / 1024) + "MiB)"),
|
|
121
|
+
killed,
|
|
122
|
+
}),
|
|
123
|
+
dispose: () => clearInterval(timer),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function noneGuard(detail) {
|
|
127
|
+
return {
|
|
128
|
+
status: () => ({ kind: "none", limit_mb: null, detail, killed: false }),
|
|
129
|
+
dispose: () => undefined,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** Sum VmRSS (KiB) over the pid and every descendant, bounded. */
|
|
133
|
+
export function readTreeRssKb(pid, procRoot = "/proc", maxPids = 2000) {
|
|
134
|
+
const seen = new Set();
|
|
135
|
+
const queue = [pid];
|
|
136
|
+
let total = 0;
|
|
137
|
+
let read = 0;
|
|
138
|
+
while (queue.length > 0 && seen.size < maxPids) {
|
|
139
|
+
const current = queue.shift();
|
|
140
|
+
if (seen.has(current))
|
|
141
|
+
continue;
|
|
142
|
+
seen.add(current);
|
|
143
|
+
const kb = readVmRssKb(current, procRoot);
|
|
144
|
+
if (kb !== null) {
|
|
145
|
+
total += kb;
|
|
146
|
+
read += 1;
|
|
147
|
+
}
|
|
148
|
+
for (const child of childPids(current, procRoot))
|
|
149
|
+
queue.push(child);
|
|
150
|
+
}
|
|
151
|
+
return read === 0 ? null : total;
|
|
152
|
+
}
|
|
153
|
+
function readVmRssKb(pid, procRoot) {
|
|
154
|
+
try {
|
|
155
|
+
const text = readFileSync(join(procRoot, String(pid), "status"), "utf8");
|
|
156
|
+
for (const line of text.split("\n")) {
|
|
157
|
+
if (!line.startsWith("VmRSS:"))
|
|
158
|
+
continue;
|
|
159
|
+
const value = Number(line.replace(/[^0-9]/g, ""));
|
|
160
|
+
return Number.isFinite(value) ? value : null;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
/** Direct children of a pid via /proc/<pid>/task/<tid>/children. */
|
|
169
|
+
function childPids(pid, procRoot) {
|
|
170
|
+
const out = [];
|
|
171
|
+
const taskDir = join(procRoot, String(pid), "task");
|
|
172
|
+
let tasks;
|
|
173
|
+
try {
|
|
174
|
+
tasks = readdirSync(taskDir);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return out;
|
|
178
|
+
}
|
|
179
|
+
for (const tid of tasks) {
|
|
180
|
+
try {
|
|
181
|
+
const text = readFileSync(join(taskDir, tid, "children"), "utf8").trim();
|
|
182
|
+
if (text === "")
|
|
183
|
+
continue;
|
|
184
|
+
for (const token of text.split(/\s+/)) {
|
|
185
|
+
const child = Number(token);
|
|
186
|
+
if (Number.isInteger(child) && child > 0)
|
|
187
|
+
out.push(child);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
/* the task vanished mid-scan */
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return out;
|
|
195
|
+
}
|
|
196
|
+
function defaultKillTree(pid) {
|
|
197
|
+
try {
|
|
198
|
+
process.kill(-pid, "SIGKILL");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
/* not a group leader */
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
process.kill(pid, "SIGKILL");
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
/* already gone */
|
|
209
|
+
}
|
|
210
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F4 step 2b: one SESSION's headless browser, launched THROUGH the sandbox.
|
|
3
|
+
*
|
|
4
|
+
* Why through the sandbox: the browser is the one workload that must run with
|
|
5
|
+
* `noAddressSpaceLimit: true` (step 2a) and, on the bwrap provider, with a
|
|
6
|
+
* SHARED network namespace (the DevTools ws:// endpoint lives on 127.0.0.1 and
|
|
7
|
+
* would be unreachable inside `--unshare-all`). Both facts are asserted here,
|
|
8
|
+
* never inferred: `spawned.sandbox.net_isolated === true` refuses the call with
|
|
9
|
+
* a structured `network_required` error instead of silently failing to connect.
|
|
10
|
+
*
|
|
11
|
+
* Lifecycle: the browser child is registered in the session ProcessRegistry, so
|
|
12
|
+
* the host's existing shutdown hook (`processes.dispose()`) reaps it; the
|
|
13
|
+
* manager ALSO exposes `dispose()` and removes the profile dir as soon as the
|
|
14
|
+
* child exits. No orphan is left behind.
|
|
15
|
+
*
|
|
16
|
+
* The result carries an explicit isolation block: the RLIMIT_AS exemption and
|
|
17
|
+
* the memory backstop are stated in the VALUE, so a caller can never mistake an
|
|
18
|
+
* exempted call for a sandboxed one.
|
|
19
|
+
*/
|
|
20
|
+
import type { ImageRef, Sandbox, SandboxChild, SandboxMeta } from "@celestea/core";
|
|
21
|
+
import type { AttachmentStore } from "../attachments/store.js";
|
|
22
|
+
import type { ProcessRegistry } from "../process/registry.js";
|
|
23
|
+
import { CdpClient } from "./cdp.js";
|
|
24
|
+
import { type MemoryGuardStatus } from "./memory-guard.js";
|
|
25
|
+
import type { BoundingBox } from "./types.js";
|
|
26
|
+
/** Default cap on rendered AX nodes / bytes (step 1's limits). */
|
|
27
|
+
export declare const DEFAULT_BROWSER_MAX_NODES = 200;
|
|
28
|
+
export declare const DEFAULT_BROWSER_MAX_BYTES: number;
|
|
29
|
+
/** Default wait for the DevTools endpoint. */
|
|
30
|
+
export declare const DEFAULT_BROWSER_STARTUP_MS = 20000;
|
|
31
|
+
/** Grace between terminate() and kill() when disposing. */
|
|
32
|
+
export declare const DEFAULT_BROWSER_DISPOSE_GRACE_MS = 3000;
|
|
33
|
+
/** How long to wait for document.readyState after navigate. */
|
|
34
|
+
export declare const DEFAULT_NAVIGATE_TIMEOUT_MS = 20000;
|
|
35
|
+
export interface BrowserViewport {
|
|
36
|
+
width: number;
|
|
37
|
+
height: number;
|
|
38
|
+
}
|
|
39
|
+
export interface BrowserActRequest {
|
|
40
|
+
action: "click" | "type" | "key" | "scroll";
|
|
41
|
+
ref?: string;
|
|
42
|
+
text?: string;
|
|
43
|
+
key?: string;
|
|
44
|
+
deltaX?: number;
|
|
45
|
+
deltaY?: number;
|
|
46
|
+
}
|
|
47
|
+
/** The isolation facts of the running browser (explicit, never inferred). */
|
|
48
|
+
export interface BrowserIsolation {
|
|
49
|
+
provider: string;
|
|
50
|
+
net_isolated: boolean;
|
|
51
|
+
tmp_private: boolean;
|
|
52
|
+
seccomp: boolean;
|
|
53
|
+
/** Always "exempted" for a browser: RLIMIT_AS is not applied. */
|
|
54
|
+
address_space_limit: "exempted";
|
|
55
|
+
/** The model-visible statement of that exemption. */
|
|
56
|
+
address_space_note: string;
|
|
57
|
+
memory_guard: MemoryGuardStatus;
|
|
58
|
+
}
|
|
59
|
+
export interface BrowserRef {
|
|
60
|
+
ref: string;
|
|
61
|
+
role: string;
|
|
62
|
+
name: string;
|
|
63
|
+
backend_dom_node_id: number | null;
|
|
64
|
+
box: BoundingBox | null;
|
|
65
|
+
}
|
|
66
|
+
export interface BrowserSnapshotValue {
|
|
67
|
+
text: string;
|
|
68
|
+
refs: BrowserRef[];
|
|
69
|
+
truncated: boolean;
|
|
70
|
+
truncation_reason: string | null;
|
|
71
|
+
total_nodes: number;
|
|
72
|
+
included_nodes: number;
|
|
73
|
+
}
|
|
74
|
+
export interface BrowserScreenshot {
|
|
75
|
+
attachment_id: string;
|
|
76
|
+
media_type: string;
|
|
77
|
+
width: number;
|
|
78
|
+
height: number;
|
|
79
|
+
bytes: number;
|
|
80
|
+
}
|
|
81
|
+
export interface BrowserResult {
|
|
82
|
+
ok: true;
|
|
83
|
+
url: string;
|
|
84
|
+
title: string;
|
|
85
|
+
snapshot: BrowserSnapshotValue;
|
|
86
|
+
screenshot: BrowserScreenshot | null;
|
|
87
|
+
attachments: ImageRef[];
|
|
88
|
+
isolation: BrowserIsolation;
|
|
89
|
+
notes: string[];
|
|
90
|
+
}
|
|
91
|
+
/** The model-visible sentence that must appear on every browser result. */
|
|
92
|
+
export declare const ADDRESS_SPACE_NOTE = "RLIMIT_AS is EXEMPTED for this browser process (noAddressSpaceLimit=true): its virtual address space is NOT bounded by the sandbox.";
|
|
93
|
+
export interface BrowserManagerOptions {
|
|
94
|
+
sandbox: Sandbox;
|
|
95
|
+
processes?: ProcessRegistry;
|
|
96
|
+
attachments?: AttachmentStore | null;
|
|
97
|
+
findExecutable?: () => string | null;
|
|
98
|
+
attach?: (endpoint: string) => Promise<CdpClient>;
|
|
99
|
+
/** Test seam: bypass the sandbox (the real path always passes the flag). */
|
|
100
|
+
spawn?: (command: string) => Promise<{
|
|
101
|
+
child: SandboxChild;
|
|
102
|
+
sandbox: SandboxMeta;
|
|
103
|
+
}>;
|
|
104
|
+
startupTimeoutMs?: number;
|
|
105
|
+
navigateTimeoutMs?: number;
|
|
106
|
+
disposeGraceMs?: number;
|
|
107
|
+
memoryLimitMb?: number;
|
|
108
|
+
maxNodes?: number;
|
|
109
|
+
maxBytes?: number;
|
|
110
|
+
}
|
|
111
|
+
/** Per-session browser owner. One instance is shared by both browser tools. */
|
|
112
|
+
export declare class BrowserManager {
|
|
113
|
+
private readonly options;
|
|
114
|
+
private session;
|
|
115
|
+
private disposed;
|
|
116
|
+
constructor(options: BrowserManagerOptions);
|
|
117
|
+
/** Open (or reuse) the page and return its snapshot + screenshot. */
|
|
118
|
+
open(url: string, viewport?: BrowserViewport): Promise<BrowserResult>;
|
|
119
|
+
/** Act on the page opened by [open]; returns the updated snapshot. */
|
|
120
|
+
act(request: BrowserActRequest): Promise<BrowserResult>;
|
|
121
|
+
/** Reclaim the browser: terminate the tree, wait, kill, remove the profile. */
|
|
122
|
+
dispose(): Promise<void>;
|
|
123
|
+
/** True while a live browser is attached (diagnostics / tests). */
|
|
124
|
+
get running(): boolean;
|
|
125
|
+
private ensure;
|
|
126
|
+
private spawnBrowser;
|
|
127
|
+
private browserCommand;
|
|
128
|
+
private readEndpoint;
|
|
129
|
+
private navigate;
|
|
130
|
+
private perform;
|
|
131
|
+
private click;
|
|
132
|
+
private typeText;
|
|
133
|
+
private key;
|
|
134
|
+
private scroll;
|
|
135
|
+
private boxOf;
|
|
136
|
+
private capture;
|
|
137
|
+
private screenshot;
|
|
138
|
+
private isolation;
|
|
139
|
+
private notes;
|
|
140
|
+
private get startupMs();
|
|
141
|
+
private get navigateMs();
|
|
142
|
+
private get graceMs();
|
|
143
|
+
private get memoryLimitMb();
|
|
144
|
+
private get maxNodes();
|
|
145
|
+
private get maxBytes();
|
|
146
|
+
}
|