harnery 0.31.6 → 0.32.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/commander.d.ts.map +1 -1
- package/dist/commander.js +2 -0
- package/dist/commands/agents.d.ts +0 -9
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +70 -95
- package/dist/commands/browse-session.d.ts +21 -0
- package/dist/commands/browse-session.d.ts.map +1 -0
- package/dist/commands/browse-session.js +157 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +205 -37
- package/dist/commands/checkpoint.js +1 -1
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +4 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +40 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +100 -17
- package/dist/commands/init.d.ts +1 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +16 -5
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +2 -3
- package/dist/core/agents/canonical-emit.d.ts +1 -2
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +1 -2
- package/dist/core/agents/cli.js +123 -88
- package/dist/core/agents/coord-client.d.ts +7 -3
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +5 -4
- package/dist/core/agents/finalization.d.ts +68 -0
- package/dist/core/agents/finalization.d.ts.map +1 -0
- package/dist/core/agents/finalization.js +443 -0
- package/dist/core/agents/git-hook.d.ts +51 -0
- package/dist/core/agents/git-hook.d.ts.map +1 -0
- package/dist/core/agents/git-hook.js +118 -0
- package/dist/core/agents/render/prompt-context.d.ts +6 -5
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +26 -13
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +15 -2
- package/dist/core/agents/rules/claim-conflict.js +3 -3
- package/dist/core/agents/rules/commit-conflict.d.ts +15 -6
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +21 -5
- package/dist/core/agents/rules/stop-hook.d.ts +3 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +59 -23
- package/dist/core/agents/session-events.d.ts +8 -16
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +12 -26
- package/dist/core/agents/state/heartbeat-projector.d.ts +3 -0
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-projector.js +44 -1
- package/dist/core/agents/state/heartbeat-writer.d.ts +32 -5
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +54 -17
- package/dist/core/agents/state/names.d.ts +22 -1
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +40 -2
- package/dist/core/config.d.ts +30 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +74 -11
- package/dist/core/governor/planning.d.ts.map +1 -1
- package/dist/core/governor/planning.js +12 -13
- package/dist/core/hooks/adapter/detect.d.ts +2 -4
- package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
- package/dist/core/hooks/adapter/detect.js +4 -14
- package/dist/core/hooks/adapter/output.d.ts +1 -1
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +5 -4
- package/dist/core/hooks/adapter/wiring.d.ts +23 -0
- package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
- package/dist/core/hooks/adapter/wiring.js +32 -0
- package/dist/core/hooks/cli.d.ts +1 -2
- package/dist/core/hooks/cli.d.ts.map +1 -1
- package/dist/core/hooks/cli.js +169 -27
- package/dist/core/hooks/codex-wsl-bridge.d.ts +46 -0
- package/dist/core/hooks/codex-wsl-bridge.d.ts.map +1 -0
- package/dist/core/hooks/codex-wsl-bridge.js +137 -0
- package/dist/core/hooks/effects/index.d.ts +1 -1
- package/dist/core/hooks/effects/index.js +3 -3
- package/dist/core/hooks/events/schema.d.ts +27 -0
- package/dist/core/hooks/events/schema.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.d.ts +7 -1
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +15 -0
- package/dist/core/hooks/resolve/transcript.d.ts +44 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +176 -1
- package/dist/core/hooks/session-name-presence.d.ts +30 -0
- package/dist/core/hooks/session-name-presence.d.ts.map +1 -0
- package/dist/core/hooks/session-name-presence.js +43 -0
- package/dist/core/hooks/unsafe-cross-shell.d.ts +13 -0
- package/dist/core/hooks/unsafe-cross-shell.d.ts.map +1 -0
- package/dist/core/hooks/unsafe-cross-shell.js +151 -0
- package/dist/core/work/state.d.ts +4 -5
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +5 -8
- package/dist/core/workflow/index.d.ts +1 -1
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/proof.d.ts +2 -2
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +2 -2
- package/dist/core/workflow/run-state.d.ts +2 -2
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +2 -2
- package/dist/core/workflow/types.d.ts +3 -3
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/execution.d.ts +2 -2
- package/dist/core/workflow/workspaces/execution.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/execution.js +5 -0
- package/dist/core/workflow/workspaces/index.d.ts +1 -1
- package/dist/core/workflow/workspaces/index.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/local-git.js +1 -2
- package/dist/core/workflow/workspaces/paths.d.ts +2 -2
- package/dist/core/workflow/workspaces/types.d.ts +0 -6
- package/dist/core/workflow/workspaces/types.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/validate.d.ts +0 -2
- package/dist/core/workflow/workspaces/validate.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/validate.js +0 -2
- package/dist/lib/browser/client.d.ts +118 -1
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +435 -6
- package/dist/lib/browser/geometry.d.ts.map +1 -1
- package/dist/lib/browser/geometry.js +180 -37
- package/dist/lib/browser/index.d.ts +5 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +5 -1
- package/dist/lib/browser/netscape-cookies.d.ts +6 -0
- package/dist/lib/browser/netscape-cookies.d.ts.map +1 -0
- package/dist/lib/browser/netscape-cookies.js +31 -0
- package/dist/lib/browser/proxy.d.ts +24 -0
- package/dist/lib/browser/proxy.d.ts.map +1 -0
- package/dist/lib/browser/proxy.js +84 -0
- package/dist/lib/browser/runts.d.ts +6 -0
- package/dist/lib/browser/runts.d.ts.map +1 -1
- package/dist/lib/browser/runts.js +21 -4
- package/dist/lib/browser/session-control.d.ts +112 -0
- package/dist/lib/browser/session-control.d.ts.map +1 -0
- package/dist/lib/browser/session-control.js +670 -0
- package/dist/lib/docs-links.d.ts +108 -0
- package/dist/lib/docs-links.d.ts.map +1 -0
- package/dist/lib/docs-links.js +555 -0
- package/dist/lib/exec.d.ts +1 -1
- package/dist/lib/exec.js +1 -1
- package/dist/lib/identities/assume.d.ts +4 -2
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +15 -2
- package/dist/lib/instructions/git-hooks.d.ts +75 -0
- package/dist/lib/instructions/git-hooks.d.ts.map +1 -0
- package/dist/lib/instructions/git-hooks.js +238 -0
- package/dist/lib/instructions/splice.d.ts +10 -4
- package/dist/lib/instructions/splice.d.ts.map +1 -1
- package/dist/lib/instructions/splice.js +19 -11
- package/package.json +1 -1
- package/schemas/config.schema.json +32 -0
- package/src/commander.ts +2 -0
- package/src/commands/agents.ts +96 -115
- package/src/commands/browse-session.ts +245 -0
- package/src/commands/browse.ts +287 -44
- package/src/commands/checkpoint.ts +1 -1
- package/src/commands/deinit.ts +7 -1
- package/src/commands/docs.ts +56 -0
- package/src/commands/doctor.ts +100 -18
- package/src/commands/init.ts +17 -9
- package/src/commands/tunnel.ts +2 -5
- package/src/core/agents/canonical-emit.ts +1 -2
- package/src/core/agents/cli.ts +137 -88
- package/src/core/agents/coord-client.ts +10 -5
- package/src/core/agents/finalization.ts +595 -0
- package/src/core/agents/git-hook.ts +126 -0
- package/src/core/agents/render/prompt-context.ts +28 -13
- package/src/core/agents/render/session-context.ts +15 -2
- package/src/core/agents/rules/claim-conflict.ts +3 -3
- package/src/core/agents/rules/commit-conflict.ts +35 -8
- package/src/core/agents/rules/stop-hook.ts +71 -23
- package/src/core/agents/session-events.ts +14 -41
- package/src/core/agents/state/heartbeat-projector.ts +45 -1
- package/src/core/agents/state/heartbeat-writer.ts +78 -16
- package/src/core/agents/state/names.ts +54 -2
- package/src/core/config.ts +92 -12
- package/src/core/governor/planning.ts +17 -12
- package/src/core/hooks/adapter/detect.ts +4 -13
- package/src/core/hooks/adapter/output.ts +9 -4
- package/src/core/hooks/adapter/wiring.ts +43 -0
- package/src/core/hooks/cli.ts +201 -23
- package/src/core/hooks/codex-wsl-bridge.ts +188 -0
- package/src/core/hooks/effects/index.ts +5 -5
- package/src/core/hooks/events/schema.ts +27 -0
- package/src/core/hooks/resolve/owner.ts +22 -1
- package/src/core/hooks/resolve/transcript.ts +164 -1
- package/src/core/hooks/session-name-presence.ts +52 -0
- package/src/core/hooks/unsafe-cross-shell.ts +160 -0
- package/src/core/work/state.ts +8 -12
- package/src/core/workflow/engine.ts +2 -2
- package/src/core/workflow/index.ts +0 -1
- package/src/core/workflow/proof.ts +4 -4
- package/src/core/workflow/run-state.ts +5 -5
- package/src/core/workflow/types.ts +3 -3
- package/src/core/workflow/workspaces/execution.ts +11 -4
- package/src/core/workflow/workspaces/index.ts +0 -3
- package/src/core/workflow/workspaces/local-git.ts +1 -2
- package/src/core/workflow/workspaces/paths.ts +2 -2
- package/src/core/workflow/workspaces/types.ts +0 -9
- package/src/core/workflow/workspaces/validate.ts +1 -5
- package/src/lib/browser/client.ts +528 -6
- package/src/lib/browser/geometry.ts +197 -37
- package/src/lib/browser/index.ts +39 -0
- package/src/lib/browser/netscape-cookies.ts +39 -0
- package/src/lib/browser/proxy.ts +105 -0
- package/src/lib/browser/runts.ts +27 -3
- package/src/lib/browser/session-control.ts +892 -0
- package/src/lib/docs-links.ts +674 -0
- package/src/lib/exec.ts +1 -1
- package/src/lib/identities/assume.ts +22 -1
- package/src/lib/instructions/git-hooks.ts +259 -0
- package/src/lib/instructions/splice.ts +41 -11
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { mkdirSync } from "node:fs";
|
|
1
|
+
import { chmodSync, mkdirSync, statSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { resolve } from "node:path";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
4
|
import axe from "axe-core";
|
|
5
5
|
import { chromium, } from "playwright";
|
|
6
6
|
import { buildAssertCheck } from "./asserts.js";
|
|
@@ -10,6 +10,14 @@ import { buildClearLayoutAnnotationsScript, buildLayoutAnnotateScript, buildOver
|
|
|
10
10
|
import { buildClearRuntsAnnotationsScript, buildRuntsAnnotateScript, buildRuntsCheck, } from "./runts.js";
|
|
11
11
|
import { buildClearTargetSizeAnnotationsScript, buildTargetSizeAnnotateScript, buildTargetSizeCheck, } from "./target-size.js";
|
|
12
12
|
import { buildAnnotateScript, buildClearAnnotationsScript, buildVisibilityCheck, } from "./visibility.js";
|
|
13
|
+
export class BrowserSessionActionError extends Error {
|
|
14
|
+
code;
|
|
15
|
+
constructor(code, message) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.code = code;
|
|
18
|
+
this.name = "BrowserSessionActionError";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
13
21
|
const DEFAULT_PROFILE = resolve(homedir(), ".cache", "harnery", "browser-profile");
|
|
14
22
|
// Bound how many Chromium processes SPAWN at the same moment. When many Browser
|
|
15
23
|
// instances open at once — a full test suite, a fan-out of browse calls — the
|
|
@@ -17,8 +25,10 @@ const DEFAULT_PROFILE = resolve(homedir(), ".cache", "harnery", "browser-profile
|
|
|
17
25
|
// resources and Chromium launch dies with an unhandled ENOENT that a per-call
|
|
18
26
|
// retry can't catch. Serializing only the brief launch phase (never the
|
|
19
27
|
// browser's lifetime, so N browsers still run concurrently) removes the burst
|
|
20
|
-
// that causes it.
|
|
21
|
-
|
|
28
|
+
// that causes it. The default stays at one because even a three-process burst
|
|
29
|
+
// can exhaust Bun/Playwright's IPC sockets under a full suite; callers with
|
|
30
|
+
// more headroom can opt into a higher value via HARNERY_MAX_BROWSER_LAUNCHES.
|
|
31
|
+
const MAX_CONCURRENT_LAUNCHES = Math.max(1, Number.parseInt(process.env.HARNERY_MAX_BROWSER_LAUNCHES ?? "1", 10) || 1);
|
|
22
32
|
let activeLaunches = 0;
|
|
23
33
|
const launchWaiters = [];
|
|
24
34
|
async function acquireLaunchSlot() {
|
|
@@ -42,6 +52,12 @@ export class Browser {
|
|
|
42
52
|
opts;
|
|
43
53
|
context = null;
|
|
44
54
|
page = null;
|
|
55
|
+
pageIndexes = new Map();
|
|
56
|
+
pageRecency = new Map();
|
|
57
|
+
pageNavigations = new Map();
|
|
58
|
+
nextPageIndex = 0;
|
|
59
|
+
recencyClock = 0;
|
|
60
|
+
sessionRevision = 0;
|
|
45
61
|
profileDir;
|
|
46
62
|
consoleEvents = [];
|
|
47
63
|
pageErrors = [];
|
|
@@ -52,6 +68,8 @@ export class Browser {
|
|
|
52
68
|
}
|
|
53
69
|
/** Lazy: caller-side helper to find the active page if mid-flow. */
|
|
54
70
|
get currentPage() {
|
|
71
|
+
if (!this.page || this.page.isClosed())
|
|
72
|
+
this.selectMostRecentPage();
|
|
55
73
|
if (!this.page) {
|
|
56
74
|
throw new Error("Browser not opened. Call open() first.");
|
|
57
75
|
}
|
|
@@ -72,6 +90,7 @@ export class Browser {
|
|
|
72
90
|
...(this.opts.launchArgs && this.opts.launchArgs.length > 0
|
|
73
91
|
? { args: this.opts.launchArgs }
|
|
74
92
|
: {}),
|
|
93
|
+
...(this.opts.proxy ? { proxy: this.opts.proxy } : {}),
|
|
75
94
|
...(this.opts.recordHarPath
|
|
76
95
|
? { recordHar: { path: this.opts.recordHarPath, mode: "full" } }
|
|
77
96
|
: {}),
|
|
@@ -101,8 +120,10 @@ export class Browser {
|
|
|
101
120
|
});
|
|
102
121
|
}
|
|
103
122
|
const pages = this.context.pages();
|
|
104
|
-
|
|
105
|
-
this.
|
|
123
|
+
const firstPage = pages[0] ?? (await this.context.newPage());
|
|
124
|
+
for (const page of this.context.pages())
|
|
125
|
+
this.trackPage(page, page === firstPage);
|
|
126
|
+
this.context.on("page", (page) => this.trackPage(page, true));
|
|
106
127
|
}
|
|
107
128
|
/**
|
|
108
129
|
* Open the browser, retrying a few times on a transient startup failure.
|
|
@@ -141,6 +162,10 @@ export class Browser {
|
|
|
141
162
|
}
|
|
142
163
|
this.context = null;
|
|
143
164
|
this.page = null;
|
|
165
|
+
this.pageIndexes.clear();
|
|
166
|
+
this.pageRecency.clear();
|
|
167
|
+
this.nextPageIndex = 0;
|
|
168
|
+
this.recencyClock = 0;
|
|
144
169
|
this.consoleEvents = [];
|
|
145
170
|
this.pageErrors = [];
|
|
146
171
|
this.failedRequests = [];
|
|
@@ -197,6 +222,78 @@ export class Browser {
|
|
|
197
222
|
});
|
|
198
223
|
});
|
|
199
224
|
}
|
|
225
|
+
trackPage(page, makeActive) {
|
|
226
|
+
if (!this.pageIndexes.has(page)) {
|
|
227
|
+
this.pageIndexes.set(page, this.nextPageIndex++);
|
|
228
|
+
this.pageNavigations.set(page, {
|
|
229
|
+
sequence: 0,
|
|
230
|
+
occurred_at: null,
|
|
231
|
+
url: page.url(),
|
|
232
|
+
type: "unknown",
|
|
233
|
+
});
|
|
234
|
+
this.attachDiagnosticListeners(page);
|
|
235
|
+
page.on("domcontentloaded", () => this.recordDocumentNavigation(page));
|
|
236
|
+
page.once("close", () => {
|
|
237
|
+
this.pageRecency.delete(page);
|
|
238
|
+
this.pageNavigations.delete(page);
|
|
239
|
+
if (this.page === page)
|
|
240
|
+
this.selectMostRecentPage();
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
if (makeActive)
|
|
244
|
+
this.setActivePage(page);
|
|
245
|
+
}
|
|
246
|
+
setActivePage(page) {
|
|
247
|
+
if (page.isClosed())
|
|
248
|
+
return;
|
|
249
|
+
this.page = page;
|
|
250
|
+
this.pageRecency.set(page, ++this.recencyClock);
|
|
251
|
+
}
|
|
252
|
+
recordDocumentNavigation(page) {
|
|
253
|
+
if (page.isClosed())
|
|
254
|
+
return;
|
|
255
|
+
const previous = this.pageNavigations.get(page);
|
|
256
|
+
this.pageNavigations.set(page, {
|
|
257
|
+
sequence: (previous?.sequence ?? 0) + 1,
|
|
258
|
+
occurred_at: new Date().toISOString(),
|
|
259
|
+
url: page.url(),
|
|
260
|
+
type: "unknown",
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
async describeNavigation(page) {
|
|
264
|
+
const current = this.pageNavigations.get(page) ?? {
|
|
265
|
+
sequence: 0,
|
|
266
|
+
occurred_at: null,
|
|
267
|
+
url: page.url(),
|
|
268
|
+
type: "unknown",
|
|
269
|
+
};
|
|
270
|
+
const type = await page
|
|
271
|
+
.evaluate(() => {
|
|
272
|
+
const entry = performance.getEntriesByType("navigation")[0];
|
|
273
|
+
const observed = entry?.type;
|
|
274
|
+
return observed === "navigate" ||
|
|
275
|
+
observed === "reload" ||
|
|
276
|
+
observed === "back_forward" ||
|
|
277
|
+
observed === "prerender"
|
|
278
|
+
? observed
|
|
279
|
+
: "unknown";
|
|
280
|
+
})
|
|
281
|
+
.catch(() => current.type);
|
|
282
|
+
const latest = this.pageNavigations.get(page);
|
|
283
|
+
if (latest?.sequence === current.sequence) {
|
|
284
|
+
const updated = { ...latest, type };
|
|
285
|
+
this.pageNavigations.set(page, updated);
|
|
286
|
+
return updated;
|
|
287
|
+
}
|
|
288
|
+
return latest ?? current;
|
|
289
|
+
}
|
|
290
|
+
selectMostRecentPage() {
|
|
291
|
+
const surviving = [...this.pageIndexes.keys()].filter((page) => !page.isClosed());
|
|
292
|
+
surviving.sort((a, b) => (this.pageRecency.get(b) ?? 0) - (this.pageRecency.get(a) ?? 0));
|
|
293
|
+
this.page = surviving[0] ?? null;
|
|
294
|
+
if (this.page)
|
|
295
|
+
this.pageRecency.set(this.page, ++this.recencyClock);
|
|
296
|
+
}
|
|
200
297
|
/**
|
|
201
298
|
* Snapshot of every event captured since `open()`. Returned objects are
|
|
202
299
|
* copies, so callers can safely store them after `close()`.
|
|
@@ -456,6 +553,317 @@ export class Browser {
|
|
|
456
553
|
}
|
|
457
554
|
});
|
|
458
555
|
}
|
|
556
|
+
async sessionStatus() {
|
|
557
|
+
const tabs = await this.sessionTabs();
|
|
558
|
+
const active = tabs.find((tab) => tab.active);
|
|
559
|
+
if (!active)
|
|
560
|
+
throw new BrowserSessionActionError("no_active_tab", "No active browser tab.");
|
|
561
|
+
return {
|
|
562
|
+
phase: "ready",
|
|
563
|
+
active_tab: active.index,
|
|
564
|
+
tab_count: tabs.length,
|
|
565
|
+
revision: this.sessionRevision,
|
|
566
|
+
navigation: active.navigation,
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
async sessionTabs() {
|
|
570
|
+
this.selectMostRecentPageIfNeeded();
|
|
571
|
+
const pages = [...this.pageIndexes.entries()]
|
|
572
|
+
.filter(([page]) => !page.isClosed())
|
|
573
|
+
.sort((a, b) => a[1] - b[1]);
|
|
574
|
+
return await Promise.all(pages.map(async ([page, index]) => ({
|
|
575
|
+
index,
|
|
576
|
+
title: await page.title().catch(() => ""),
|
|
577
|
+
url: page.url(),
|
|
578
|
+
active: page === this.page,
|
|
579
|
+
revision: this.sessionRevision,
|
|
580
|
+
navigation: await this.describeNavigation(page),
|
|
581
|
+
})));
|
|
582
|
+
}
|
|
583
|
+
async sessionSelectTab(index) {
|
|
584
|
+
const page = this.pageForIndex(index);
|
|
585
|
+
await page.bringToFront();
|
|
586
|
+
this.setActivePage(page);
|
|
587
|
+
this.sessionRevision++;
|
|
588
|
+
return this.describeTab(page);
|
|
589
|
+
}
|
|
590
|
+
async sessionOpenTab(url) {
|
|
591
|
+
if (!this.context)
|
|
592
|
+
throw new BrowserSessionActionError("not_ready", "Browser is not open.");
|
|
593
|
+
const previous = this.page;
|
|
594
|
+
const page = await this.context.newPage();
|
|
595
|
+
this.trackPage(page, true);
|
|
596
|
+
try {
|
|
597
|
+
await page.goto(url, { waitUntil: this.opts.waitUntil ?? "load" });
|
|
598
|
+
this.sessionRevision++;
|
|
599
|
+
return await this.describeTab(page);
|
|
600
|
+
}
|
|
601
|
+
catch (error) {
|
|
602
|
+
await page.close().catch(() => { });
|
|
603
|
+
if (previous && !previous.isClosed())
|
|
604
|
+
this.setActivePage(previous);
|
|
605
|
+
throw error;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
async sessionCloseTab(index) {
|
|
609
|
+
const surviving = [...this.pageIndexes.keys()].filter((page) => !page.isClosed());
|
|
610
|
+
if (surviving.length <= 1) {
|
|
611
|
+
throw new BrowserSessionActionError("final_tab", "The final browser tab cannot be closed.");
|
|
612
|
+
}
|
|
613
|
+
const page = this.pageForIndex(index);
|
|
614
|
+
await page.close();
|
|
615
|
+
this.selectMostRecentPageIfNeeded();
|
|
616
|
+
this.sessionRevision++;
|
|
617
|
+
return this.describeTab(this.currentPage);
|
|
618
|
+
}
|
|
619
|
+
async sessionGoto(url) {
|
|
620
|
+
const page = this.currentPage;
|
|
621
|
+
await page.goto(url, { waitUntil: this.opts.waitUntil ?? "load" });
|
|
622
|
+
this.sessionRevision++;
|
|
623
|
+
return this.describeTab(page);
|
|
624
|
+
}
|
|
625
|
+
async sessionReload() {
|
|
626
|
+
const page = this.currentPage;
|
|
627
|
+
await page.reload({ waitUntil: this.opts.waitUntil ?? "load" });
|
|
628
|
+
this.sessionRevision++;
|
|
629
|
+
return this.describeTab(page);
|
|
630
|
+
}
|
|
631
|
+
async sessionClick(locator) {
|
|
632
|
+
const target = await this.strictSessionLocator(locator);
|
|
633
|
+
await target.click();
|
|
634
|
+
this.sessionRevision++;
|
|
635
|
+
return { revision: this.sessionRevision };
|
|
636
|
+
}
|
|
637
|
+
async sessionFill(locator, value) {
|
|
638
|
+
const target = await this.strictSessionLocator(locator);
|
|
639
|
+
await target.fill(value);
|
|
640
|
+
this.sessionRevision++;
|
|
641
|
+
return { revision: this.sessionRevision };
|
|
642
|
+
}
|
|
643
|
+
async sessionPress(key) {
|
|
644
|
+
await this.currentPage.keyboard.press(key);
|
|
645
|
+
this.sessionRevision++;
|
|
646
|
+
return { revision: this.sessionRevision };
|
|
647
|
+
}
|
|
648
|
+
async sessionWait(locator) {
|
|
649
|
+
const target = this.sessionLocator(locator);
|
|
650
|
+
await target.first().waitFor({ state: "visible" });
|
|
651
|
+
await this.requireStrictLocator(target);
|
|
652
|
+
this.sessionRevision++;
|
|
653
|
+
return { revision: this.sessionRevision };
|
|
654
|
+
}
|
|
655
|
+
async sessionInspect(locator) {
|
|
656
|
+
const page = this.currentPage;
|
|
657
|
+
const tabIndex = this.pageIndexes.get(page);
|
|
658
|
+
if (tabIndex === undefined) {
|
|
659
|
+
throw new BrowserSessionActionError("no_active_tab", "No active browser tab.");
|
|
660
|
+
}
|
|
661
|
+
const rawText = locator
|
|
662
|
+
? await (await this.strictSessionLocator(locator)).innerText()
|
|
663
|
+
: await page.locator("body").innerText();
|
|
664
|
+
const textResult = truncateUtf8(rawText, 256 * 1024);
|
|
665
|
+
const observed = await page.evaluate(() => {
|
|
666
|
+
const visible = (element) => {
|
|
667
|
+
const style = getComputedStyle(element);
|
|
668
|
+
const rect = element.getBoundingClientRect();
|
|
669
|
+
return (style.display !== "none" &&
|
|
670
|
+
style.visibility !== "hidden" &&
|
|
671
|
+
Number(style.opacity) > 0 &&
|
|
672
|
+
rect.width > 0 &&
|
|
673
|
+
rect.height > 0);
|
|
674
|
+
};
|
|
675
|
+
const named = (element) => {
|
|
676
|
+
const aria = element.getAttribute("aria-label")?.trim();
|
|
677
|
+
if (aria)
|
|
678
|
+
return aria;
|
|
679
|
+
const labelledBy = element.getAttribute("aria-labelledby");
|
|
680
|
+
if (labelledBy) {
|
|
681
|
+
const text = labelledBy
|
|
682
|
+
.split(/\s+/)
|
|
683
|
+
.map((id) => document.getElementById(id)?.textContent?.trim() ?? "")
|
|
684
|
+
.filter(Boolean)
|
|
685
|
+
.join(" ");
|
|
686
|
+
if (text)
|
|
687
|
+
return text;
|
|
688
|
+
}
|
|
689
|
+
if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
|
|
690
|
+
const label = element.labels?.[0]?.textContent?.trim();
|
|
691
|
+
if (label)
|
|
692
|
+
return label;
|
|
693
|
+
return element.placeholder?.trim() ?? "";
|
|
694
|
+
}
|
|
695
|
+
if (element instanceof HTMLSelectElement) {
|
|
696
|
+
return element.labels?.[0]?.textContent?.trim() ?? "";
|
|
697
|
+
}
|
|
698
|
+
return element.textContent?.replace(/\s+/g, " ").trim().slice(0, 200) ?? "";
|
|
699
|
+
};
|
|
700
|
+
const describe = (element) => {
|
|
701
|
+
const tag = element.tagName.toLowerCase();
|
|
702
|
+
const role = element.getAttribute("role")?.trim();
|
|
703
|
+
let kind = role || tag;
|
|
704
|
+
if (element instanceof HTMLAnchorElement)
|
|
705
|
+
kind = "link";
|
|
706
|
+
if (element instanceof HTMLButtonElement)
|
|
707
|
+
kind = "button";
|
|
708
|
+
const attributes = {};
|
|
709
|
+
const type = element.getAttribute("type")?.trim();
|
|
710
|
+
if (type)
|
|
711
|
+
attributes.type = type;
|
|
712
|
+
const name = element.getAttribute("name")?.trim();
|
|
713
|
+
if (name)
|
|
714
|
+
attributes.name = name;
|
|
715
|
+
const autocomplete = element.getAttribute("autocomplete")?.trim();
|
|
716
|
+
if (autocomplete)
|
|
717
|
+
attributes.autocomplete = autocomplete;
|
|
718
|
+
if (element instanceof HTMLAnchorElement && element.href) {
|
|
719
|
+
try {
|
|
720
|
+
const href = new URL(element.href);
|
|
721
|
+
href.username = "";
|
|
722
|
+
href.password = "";
|
|
723
|
+
href.search = "";
|
|
724
|
+
href.hash = "";
|
|
725
|
+
attributes.href = href.toString();
|
|
726
|
+
}
|
|
727
|
+
catch {
|
|
728
|
+
// Ignore malformed link targets.
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if ("disabled" in element && element.disabled) {
|
|
732
|
+
attributes.disabled = true;
|
|
733
|
+
}
|
|
734
|
+
if ((element instanceof HTMLInputElement && element.type !== "hidden") ||
|
|
735
|
+
element instanceof HTMLTextAreaElement ||
|
|
736
|
+
element instanceof HTMLSelectElement) {
|
|
737
|
+
return {
|
|
738
|
+
kind,
|
|
739
|
+
name: named(element),
|
|
740
|
+
attributes,
|
|
741
|
+
has_value: element.value.length > 0,
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
return { kind, name: named(element), attributes };
|
|
745
|
+
};
|
|
746
|
+
const selector = [
|
|
747
|
+
"a[href]",
|
|
748
|
+
"button",
|
|
749
|
+
"input:not([type=hidden])",
|
|
750
|
+
"select",
|
|
751
|
+
"textarea",
|
|
752
|
+
'[role="button"]',
|
|
753
|
+
'[role="link"]',
|
|
754
|
+
'[role="checkbox"]',
|
|
755
|
+
'[role="radio"]',
|
|
756
|
+
'[role="textbox"]',
|
|
757
|
+
'[role="combobox"]',
|
|
758
|
+
].join(",");
|
|
759
|
+
const controls = Array.from(document.querySelectorAll(selector))
|
|
760
|
+
.filter(visible)
|
|
761
|
+
.slice(0, 500)
|
|
762
|
+
.map(describe);
|
|
763
|
+
const focus = document.activeElement;
|
|
764
|
+
return {
|
|
765
|
+
controls,
|
|
766
|
+
focus: focus && focus !== document.body && visible(focus) ? describe(focus) : null,
|
|
767
|
+
};
|
|
768
|
+
});
|
|
769
|
+
return {
|
|
770
|
+
active_tab: tabIndex,
|
|
771
|
+
url: page.url(),
|
|
772
|
+
title: await page.title(),
|
|
773
|
+
text: textResult.text,
|
|
774
|
+
controls: observed.controls,
|
|
775
|
+
focus: observed.focus,
|
|
776
|
+
revision: this.sessionRevision,
|
|
777
|
+
navigation: await this.describeNavigation(page),
|
|
778
|
+
truncated: textResult.truncated,
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
async sessionScreenshot(outInput) {
|
|
782
|
+
const out = resolve(outInput);
|
|
783
|
+
let parent;
|
|
784
|
+
try {
|
|
785
|
+
parent = statSync(dirname(out));
|
|
786
|
+
}
|
|
787
|
+
catch {
|
|
788
|
+
throw new BrowserSessionActionError("screenshot_parent_missing", "Screenshot parent directory must already exist.");
|
|
789
|
+
}
|
|
790
|
+
if (!parent.isDirectory()) {
|
|
791
|
+
throw new BrowserSessionActionError("screenshot_parent_invalid", "Screenshot parent is not a directory.");
|
|
792
|
+
}
|
|
793
|
+
const buffer = await this.currentPage.screenshot({ type: "png", fullPage: true });
|
|
794
|
+
if (buffer.length < 24 || buffer.toString("ascii", 1, 4) !== "PNG") {
|
|
795
|
+
throw new BrowserSessionActionError("screenshot_invalid", "Browser returned an invalid PNG.");
|
|
796
|
+
}
|
|
797
|
+
try {
|
|
798
|
+
writeFileSync(out, buffer, { flag: "wx", mode: 0o600 });
|
|
799
|
+
chmodSync(out, 0o600);
|
|
800
|
+
}
|
|
801
|
+
catch (error) {
|
|
802
|
+
if (error.code === "EEXIST") {
|
|
803
|
+
throw new BrowserSessionActionError("screenshot_exists", "Screenshot output already exists.");
|
|
804
|
+
}
|
|
805
|
+
throw error;
|
|
806
|
+
}
|
|
807
|
+
this.sessionRevision++;
|
|
808
|
+
return {
|
|
809
|
+
path: out,
|
|
810
|
+
width: buffer.readUInt32BE(16),
|
|
811
|
+
height: buffer.readUInt32BE(20),
|
|
812
|
+
revision: this.sessionRevision,
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
sessionLocator(locator) {
|
|
816
|
+
const page = this.currentPage;
|
|
817
|
+
switch (locator.kind) {
|
|
818
|
+
case "selector":
|
|
819
|
+
return page.locator(locator.value);
|
|
820
|
+
case "role":
|
|
821
|
+
return page.getByRole(locator.value, {
|
|
822
|
+
...(locator.name === undefined ? {} : { name: locator.name, exact: !locator.partial }),
|
|
823
|
+
});
|
|
824
|
+
case "label":
|
|
825
|
+
return page.getByLabel(locator.value, { exact: !locator.partial });
|
|
826
|
+
case "text":
|
|
827
|
+
return page.getByText(locator.value, { exact: !locator.partial });
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
async strictSessionLocator(locator) {
|
|
831
|
+
return this.requireStrictLocator(this.sessionLocator(locator));
|
|
832
|
+
}
|
|
833
|
+
async requireStrictLocator(locator) {
|
|
834
|
+
const count = await locator.count();
|
|
835
|
+
if (count === 0) {
|
|
836
|
+
throw new BrowserSessionActionError("locator_not_found", "Locator matched no elements.");
|
|
837
|
+
}
|
|
838
|
+
if (count !== 1) {
|
|
839
|
+
throw new BrowserSessionActionError("locator_ambiguous", `Locator matched ${count} elements; refine it before acting.`);
|
|
840
|
+
}
|
|
841
|
+
return locator;
|
|
842
|
+
}
|
|
843
|
+
pageForIndex(index) {
|
|
844
|
+
const entry = [...this.pageIndexes.entries()].find(([page, pageIndex]) => pageIndex === index && !page.isClosed());
|
|
845
|
+
if (!entry)
|
|
846
|
+
throw new BrowserSessionActionError("tab_not_found", "Browser tab was not found.");
|
|
847
|
+
return entry[0];
|
|
848
|
+
}
|
|
849
|
+
async describeTab(page) {
|
|
850
|
+
const index = this.pageIndexes.get(page);
|
|
851
|
+
if (index === undefined || page.isClosed()) {
|
|
852
|
+
throw new BrowserSessionActionError("tab_not_found", "Browser tab was not found.");
|
|
853
|
+
}
|
|
854
|
+
return {
|
|
855
|
+
index,
|
|
856
|
+
title: await page.title().catch(() => ""),
|
|
857
|
+
url: page.url(),
|
|
858
|
+
active: page === this.page,
|
|
859
|
+
revision: this.sessionRevision,
|
|
860
|
+
navigation: await this.describeNavigation(page),
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
selectMostRecentPageIfNeeded() {
|
|
864
|
+
if (!this.page || this.page.isClosed())
|
|
865
|
+
this.selectMostRecentPage();
|
|
866
|
+
}
|
|
459
867
|
/**
|
|
460
868
|
* Run occlusion checks on one or more selectors. For each, samples a grid
|
|
461
869
|
* of points inside the element's bounding rect and uses
|
|
@@ -589,6 +997,12 @@ export class Browser {
|
|
|
589
997
|
throw new Error("Browser not opened. Call open() first.");
|
|
590
998
|
await this.context.addInitScript(script);
|
|
591
999
|
}
|
|
1000
|
+
/** Snapshot all cookies in the live persistent context. */
|
|
1001
|
+
async cookies() {
|
|
1002
|
+
if (!this.context)
|
|
1003
|
+
throw new Error("Browser not opened. Call open() first.");
|
|
1004
|
+
return this.context.cookies();
|
|
1005
|
+
}
|
|
592
1006
|
/**
|
|
593
1007
|
* Sync cookies from the live context back into the jar (if one was provided),
|
|
594
1008
|
* then tear everything down. Safe to call multiple times.
|
|
@@ -610,6 +1024,12 @@ export class Browser {
|
|
|
610
1024
|
await this.context.close().catch(() => { });
|
|
611
1025
|
this.context = null;
|
|
612
1026
|
this.page = null;
|
|
1027
|
+
this.pageIndexes.clear();
|
|
1028
|
+
this.pageRecency.clear();
|
|
1029
|
+
this.pageNavigations.clear();
|
|
1030
|
+
this.nextPageIndex = 0;
|
|
1031
|
+
this.recencyClock = 0;
|
|
1032
|
+
this.sessionRevision = 0;
|
|
613
1033
|
}
|
|
614
1034
|
}
|
|
615
1035
|
// ---------------------------------------------------------------------------
|
|
@@ -655,3 +1075,12 @@ function normalizeSameSite(s) {
|
|
|
655
1075
|
return "None";
|
|
656
1076
|
return undefined;
|
|
657
1077
|
}
|
|
1078
|
+
function truncateUtf8(value, maxBytes) {
|
|
1079
|
+
const buffer = Buffer.from(value, "utf8");
|
|
1080
|
+
if (buffer.length <= maxBytes)
|
|
1081
|
+
return { text: value, truncated: false };
|
|
1082
|
+
let end = maxBytes;
|
|
1083
|
+
while (end > 0 && (buffer[end] & 0xc0) === 0x80)
|
|
1084
|
+
end--;
|
|
1085
|
+
return { text: buffer.subarray(0, end).toString("utf8"), truncated: true };
|
|
1086
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/geometry.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/geometry.ts"],"names":[],"mappings":"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"}
|