@crouton-kit/capture 1.3.14 → 1.3.16
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/bin/capture +281 -168
- package/package.json +1 -1
- package/src/cdp/args.ts +9 -5
- package/src/cdp/commands/cdp.ts +13 -5
- package/src/cdp/commands/tab/close.ts +98 -0
- package/src/cdp/commands/tab/index.ts +7 -3
- package/src/cdp/commands/tab/reset.ts +35 -32
- package/src/cdp/connection.ts +12 -3
- package/src/cdp/types.ts +5 -0
- package/src/output/render.ts +1 -0
- package/src/session/commands.ts +5 -20
- package/src/session/coordinator.ts +18 -0
package/bin/capture
CHANGED
|
@@ -7797,6 +7797,7 @@ var init_render = __esm({
|
|
|
7797
7797
|
"screenshot",
|
|
7798
7798
|
"tabs",
|
|
7799
7799
|
"tab-opened",
|
|
7800
|
+
"tab-closed",
|
|
7800
7801
|
"tab-reset",
|
|
7801
7802
|
"network",
|
|
7802
7803
|
"cdp-result",
|
|
@@ -8715,7 +8716,7 @@ function validateKnownLeaf(command, positional) {
|
|
|
8715
8716
|
const branches = {
|
|
8716
8717
|
session: ["start", "stop", "list", "view", "har", "log"],
|
|
8717
8718
|
page: ["click", "type", "scroll", "navigate", "exec", "shot", "elements"],
|
|
8718
|
-
tab: ["list", "open", "reset", "network"],
|
|
8719
|
+
tab: ["list", "open", "close", "reset", "network"],
|
|
8719
8720
|
measure: ["snap", "check", "diff", "census", "explain", "sweep", "map"],
|
|
8720
8721
|
motion: ["rec", "mask", "timeline", "jank", "response"],
|
|
8721
8722
|
lib: ["list", "search", "show", "read"]
|
|
@@ -8831,9 +8832,9 @@ function validateCliInvocation(parsed) {
|
|
|
8831
8832
|
throw invalidInput("motion rec lifecycle flags cannot be combined with one-shot flags.");
|
|
8832
8833
|
}
|
|
8833
8834
|
} else {
|
|
8834
|
-
requireCount(values,
|
|
8835
|
+
requireCount(values, 0, 1, "motion rec");
|
|
8835
8836
|
if (!parsed.do) throw invalidInput("motion rec one-shot requires --do.");
|
|
8836
|
-
assertParseableUrl(values[0], "recording URL");
|
|
8837
|
+
if (values[0] !== void 0) assertParseableUrl(values[0], "recording URL");
|
|
8837
8838
|
parseDoAction(parsed.do);
|
|
8838
8839
|
}
|
|
8839
8840
|
if (parsed.viewport !== void 0) {
|
|
@@ -8862,6 +8863,7 @@ function parseCliSyntax(argv) {
|
|
|
8862
8863
|
if (VALUE_FLAGS.has(arg)) valueFor(arg, next);
|
|
8863
8864
|
if (arg === "--port") {
|
|
8864
8865
|
parsed.port = integer(valueFor(arg, next), "--port", 1, 65535);
|
|
8866
|
+
parsed.portSource = "flag";
|
|
8865
8867
|
i++;
|
|
8866
8868
|
} else if (arg === "--out") {
|
|
8867
8869
|
parsed.out = valueFor(arg, next);
|
|
@@ -9018,10 +9020,14 @@ function resolveCliContext(parsed) {
|
|
|
9018
9020
|
parsed.target = session.targetId;
|
|
9019
9021
|
parsed.targetSource = "session";
|
|
9020
9022
|
}
|
|
9021
|
-
if (parsed.port === void 0 && session.port !== void 0 && session.port !== null)
|
|
9023
|
+
if (parsed.port === void 0 && session.port !== void 0 && session.port !== null) {
|
|
9024
|
+
parsed.port = session.port;
|
|
9025
|
+
parsed.portSource = "session";
|
|
9026
|
+
}
|
|
9022
9027
|
}
|
|
9023
9028
|
if (parsed.port === void 0 && process.env.CDP_PORT !== void 0) {
|
|
9024
9029
|
parsed.port = integer(process.env.CDP_PORT, "CDP_PORT", 1, 65535);
|
|
9030
|
+
parsed.portSource = "env";
|
|
9025
9031
|
}
|
|
9026
9032
|
if (!session) getActiveSession();
|
|
9027
9033
|
if (!parsed.target && !parsed.url && process.env.CDP_TARGET) {
|
|
@@ -9099,6 +9105,20 @@ var init_gate_guard = __esm({
|
|
|
9099
9105
|
});
|
|
9100
9106
|
|
|
9101
9107
|
// src/session/coordinator.ts
|
|
9108
|
+
function scopeLifecycleLockPath() {
|
|
9109
|
+
return path5.join(CAPTURE_ROOT, `.session-lifecycle-${process.env.CRTR_NODE_ID ?? "default"}`);
|
|
9110
|
+
}
|
|
9111
|
+
async function withSessionScopeLifecycle(action) {
|
|
9112
|
+
const lock = await acquirePrivateLock(scopeLifecycleLockPath(), {
|
|
9113
|
+
acquireTimeoutMs: 12e4,
|
|
9114
|
+
leaseMs: 1e3
|
|
9115
|
+
});
|
|
9116
|
+
try {
|
|
9117
|
+
return await action();
|
|
9118
|
+
} finally {
|
|
9119
|
+
lock.release();
|
|
9120
|
+
}
|
|
9121
|
+
}
|
|
9102
9122
|
function statePath(sessionDir2) {
|
|
9103
9123
|
return path5.join(assertUnderCaptureRoot(sessionDir2), ".operations.json");
|
|
9104
9124
|
}
|
|
@@ -9822,7 +9842,7 @@ function validateHarAppendBatch(value, source) {
|
|
|
9822
9842
|
return { entries, incompleteLifecycles };
|
|
9823
9843
|
}
|
|
9824
9844
|
function captureVersion() {
|
|
9825
|
-
const version = "1.3.
|
|
9845
|
+
const version = "1.3.16";
|
|
9826
9846
|
return typeof version === "string" && version.length > 0 ? version : "development";
|
|
9827
9847
|
}
|
|
9828
9848
|
function token() {
|
|
@@ -11467,8 +11487,8 @@ function __domPathOf(el) {
|
|
|
11467
11487
|
const elements = [];
|
|
11468
11488
|
if (raw.length > 0) {
|
|
11469
11489
|
const resolved = await Promise.all(
|
|
11470
|
-
raw.map(async (
|
|
11471
|
-
const objectId = objectIds[
|
|
11490
|
+
raw.map(async (fact4) => {
|
|
11491
|
+
const objectId = objectIds[fact4.idx];
|
|
11472
11492
|
let backendNodeId2;
|
|
11473
11493
|
let quads = [];
|
|
11474
11494
|
let boxModel = null;
|
|
@@ -11495,33 +11515,33 @@ function __domPathOf(el) {
|
|
|
11495
11515
|
}
|
|
11496
11516
|
const geometryUnavailable = geometryUnavailableReason !== void 0;
|
|
11497
11517
|
const rect3 = quads.length > 0 ? unionRect(quads) : { x: 0, y: 0, width: 0, height: 0 };
|
|
11498
|
-
const zeroSize = quadsUnavailable ?
|
|
11499
|
-
const visible = quadsUnavailable ?
|
|
11518
|
+
const zeroSize = quadsUnavailable ? fact4.visibility.zeroSize : fact4.visibility.zeroSize || quads.length === 0;
|
|
11519
|
+
const visible = quadsUnavailable ? fact4.visibility.visible : fact4.visibility.visible && quads.length > 0;
|
|
11500
11520
|
return {
|
|
11501
|
-
id: `el-${
|
|
11502
|
-
tag: sanitizeString(
|
|
11503
|
-
selector:
|
|
11504
|
-
domPath: sanitizeString(
|
|
11521
|
+
id: `el-${fact4.idx}`,
|
|
11522
|
+
tag: sanitizeString(fact4.tag, { max: 64 }),
|
|
11523
|
+
selector: fact4.selector !== void 0 ? sanitizeString(fact4.selector, { max: 300 }) : void 0,
|
|
11524
|
+
domPath: sanitizeString(fact4.domPath, { max: 500 }),
|
|
11505
11525
|
...resolvedIdentity(backendNodeId2),
|
|
11506
|
-
text:
|
|
11507
|
-
frame:
|
|
11508
|
-
shadow:
|
|
11509
|
-
...
|
|
11510
|
-
hostSelector:
|
|
11526
|
+
text: fact4.text !== void 0 ? sanitizeString(fact4.text, { max: 200 }) : void 0,
|
|
11527
|
+
frame: fact4.frame,
|
|
11528
|
+
shadow: fact4.shadow ? {
|
|
11529
|
+
...fact4.shadow,
|
|
11530
|
+
hostSelector: fact4.shadow.hostSelector !== void 0 ? sanitizeString(fact4.shadow.hostSelector, { max: 300 }) : void 0
|
|
11511
11531
|
} : null,
|
|
11512
11532
|
rect: rect3,
|
|
11513
11533
|
quads,
|
|
11514
11534
|
boxModel,
|
|
11515
|
-
zIndex: sanitizeString(
|
|
11516
|
-
stackingContext:
|
|
11517
|
-
visibility: { ...
|
|
11518
|
-
clipping:
|
|
11519
|
-
clippedBy:
|
|
11520
|
-
clippedFraction:
|
|
11535
|
+
zIndex: sanitizeString(fact4.zIndex, { max: 20 }),
|
|
11536
|
+
stackingContext: fact4.stackingContext,
|
|
11537
|
+
visibility: { ...fact4.visibility, visible, zeroSize },
|
|
11538
|
+
clipping: fact4.clipping ? {
|
|
11539
|
+
clippedBy: fact4.clipping.clippedBy !== void 0 ? sanitizeString(fact4.clipping.clippedBy, { max: 300 }) : void 0,
|
|
11540
|
+
clippedFraction: fact4.clipping.clippedFraction
|
|
11521
11541
|
} : null,
|
|
11522
|
-
layout: capLayoutFact(
|
|
11542
|
+
layout: capLayoutFact(fact4.layout),
|
|
11523
11543
|
...geometryUnavailable ? { geometryUnavailable: true, geometryUnavailableReason } : {},
|
|
11524
|
-
...
|
|
11544
|
+
...fact4.iframeContentUnavailable ? { iframeContentUnavailable: true, iframeContentUnavailableReason: fact4.iframeContentUnavailableReason } : {}
|
|
11525
11545
|
};
|
|
11526
11546
|
})
|
|
11527
11547
|
);
|
|
@@ -11581,7 +11601,7 @@ function wallTime(value) {
|
|
|
11581
11601
|
}
|
|
11582
11602
|
}
|
|
11583
11603
|
function captureVersion2() {
|
|
11584
|
-
const version = "1.3.
|
|
11604
|
+
const version = "1.3.16";
|
|
11585
11605
|
return typeof version === "string" && version.length > 0 ? version : "development";
|
|
11586
11606
|
}
|
|
11587
11607
|
function deepFreeze(value) {
|
|
@@ -13759,20 +13779,6 @@ function readBundleManifest(bundlePath) {
|
|
|
13759
13779
|
function sessionDir(id) {
|
|
13760
13780
|
return path12.join(CAPTURE_ROOT, id);
|
|
13761
13781
|
}
|
|
13762
|
-
function lifecycleScopeLockPath() {
|
|
13763
|
-
return path12.join(CAPTURE_ROOT, `.session-lifecycle-${process.env.CRTR_NODE_ID ?? "default"}`);
|
|
13764
|
-
}
|
|
13765
|
-
async function withLifecycleCoordinator(action) {
|
|
13766
|
-
const handle = await acquirePrivateLock(lifecycleScopeLockPath(), {
|
|
13767
|
-
acquireTimeoutMs: 12e4,
|
|
13768
|
-
leaseMs: 1e3
|
|
13769
|
-
});
|
|
13770
|
-
try {
|
|
13771
|
-
return await action();
|
|
13772
|
-
} finally {
|
|
13773
|
-
handle.release();
|
|
13774
|
-
}
|
|
13775
|
-
}
|
|
13776
13782
|
function isSessionStopped(session) {
|
|
13777
13783
|
return Boolean(session.stoppedAt) || fs9.existsSync(path12.join(session.dir, "bundle.json"));
|
|
13778
13784
|
}
|
|
@@ -13896,7 +13902,7 @@ async function start(parsed) {
|
|
|
13896
13902
|
return;
|
|
13897
13903
|
}
|
|
13898
13904
|
if (rejectSurplusPositionals(parsed, "start", 0, "capture session start [--url <url>] [--hold]")) return;
|
|
13899
|
-
return
|
|
13905
|
+
return withSessionScopeLifecycle(async () => {
|
|
13900
13906
|
const active = getActiveSession();
|
|
13901
13907
|
if (active && !isSessionStopped(active)) {
|
|
13902
13908
|
emitResult({
|
|
@@ -14306,7 +14312,7 @@ async function stop(parsed) {
|
|
|
14306
14312
|
process.exitCode = 1;
|
|
14307
14313
|
return;
|
|
14308
14314
|
}
|
|
14309
|
-
return
|
|
14315
|
+
return withSessionScopeLifecycle(async () => {
|
|
14310
14316
|
let session;
|
|
14311
14317
|
try {
|
|
14312
14318
|
session = readSession(id);
|
|
@@ -14626,6 +14632,8 @@ input:
|
|
|
14626
14632
|
--hold Hold one CDP browser connection open for the session's
|
|
14627
14633
|
lifetime, so browser-level state (permission grants,
|
|
14628
14634
|
ServiceWorker enablement) survives across separate commands.
|
|
14635
|
+
With no --url, later --target <existing-id> commands adopt
|
|
14636
|
+
an already-open tab without creating a new one.
|
|
14629
14637
|
--port <n> CDP port to attach to; default is auto-detected across localhost.
|
|
14630
14638
|
|
|
14631
14639
|
Output:
|
|
@@ -14870,7 +14878,12 @@ async function connectForCommand(parsed) {
|
|
|
14870
14878
|
}
|
|
14871
14879
|
const port = resolved?.port ?? getPortFromWebSocketDebuggerUrl(tab.webSocketDebuggerUrl);
|
|
14872
14880
|
if (activeSession && !activeSession.targetId) {
|
|
14873
|
-
await seams.
|
|
14881
|
+
await seams.withSessionScopeLifecycle(async () => {
|
|
14882
|
+
const current = seams.getActiveSession();
|
|
14883
|
+
if (current?.sessionId === activeSession.sessionId && !current.targetId) {
|
|
14884
|
+
await seams.updateActiveSession({ targetId: tab.id, port: port ?? null });
|
|
14885
|
+
}
|
|
14886
|
+
});
|
|
14874
14887
|
}
|
|
14875
14888
|
console.error(
|
|
14876
14889
|
`Using target ${tab.id.slice(0, 8)}${port ? ` on port ${port}` : ""}${tab.url ? ` (${tab.url})` : ""}`
|
|
@@ -14988,12 +15001,14 @@ var init_connection = __esm({
|
|
|
14988
15001
|
init_har_recorder();
|
|
14989
15002
|
init_har_manager();
|
|
14990
15003
|
init_session_context();
|
|
15004
|
+
init_coordinator();
|
|
14991
15005
|
init_recorder_client();
|
|
14992
15006
|
init_recorder();
|
|
14993
15007
|
init_errors();
|
|
14994
15008
|
seams = {
|
|
14995
15009
|
getActiveSession: () => getActiveSession(),
|
|
14996
15010
|
updateActiveSession,
|
|
15011
|
+
withSessionScopeLifecycle,
|
|
14997
15012
|
resolveTab: defaultResolveTab,
|
|
14998
15013
|
createClient: (wsUrl) => new CDPClient(wsUrl),
|
|
14999
15014
|
appendHar: appendToHarRecording,
|
|
@@ -227405,6 +227420,94 @@ effects: opens (or reuses) a background browser tab and waits up to 10s for its
|
|
|
227405
227420
|
}
|
|
227406
227421
|
});
|
|
227407
227422
|
|
|
227423
|
+
// src/cdp/commands/tab/close.ts
|
|
227424
|
+
function buildTabClosedResult(tab, port) {
|
|
227425
|
+
return {
|
|
227426
|
+
tag: "tab-closed",
|
|
227427
|
+
attrs: { port, target: tab.id },
|
|
227428
|
+
summary: line(text`tab `, data(tab.id.slice(0, 8)), text` closed: `, data(tab.url, 300))
|
|
227429
|
+
};
|
|
227430
|
+
}
|
|
227431
|
+
async function cmdTabClose(parsed, _args) {
|
|
227432
|
+
if (parsed.help) {
|
|
227433
|
+
console.log(USAGE10);
|
|
227434
|
+
return;
|
|
227435
|
+
}
|
|
227436
|
+
const target = parsed.positional[0];
|
|
227437
|
+
if (!target) {
|
|
227438
|
+
throw invalidInput("received: no target; expected: capture tab close <target> [--port <port>].", "missing_argument");
|
|
227439
|
+
}
|
|
227440
|
+
if (target.length < 8) {
|
|
227441
|
+
throw invalidInput(`received: target ${target}; expected: a full target id or an unambiguous prefix of at least 8 characters.`, "target_prefix_too_short");
|
|
227442
|
+
}
|
|
227443
|
+
let port;
|
|
227444
|
+
try {
|
|
227445
|
+
port = parsed.port ?? await detectCdpPort();
|
|
227446
|
+
} catch {
|
|
227447
|
+
throw captureError(
|
|
227448
|
+
"world",
|
|
227449
|
+
"no_cdp_endpoint",
|
|
227450
|
+
"received: no --port, and no CDP endpoint was discovered on localhost; expected: a running CDP-enabled browser (or an explicit --port <port>). capture tab list probes every localhost CDP endpoint."
|
|
227451
|
+
);
|
|
227452
|
+
}
|
|
227453
|
+
const tab = await withSessionScopeLifecycle(async () => {
|
|
227454
|
+
let resolved;
|
|
227455
|
+
try {
|
|
227456
|
+
resolved = await findTabById(port, target);
|
|
227457
|
+
} catch (error) {
|
|
227458
|
+
throw captureError("precondition", "target_unavailable", `received: target ${target} on port ${port}; expected: one unambiguous page-tab target id. ${error instanceof Error ? error.message : String(error)}`, error);
|
|
227459
|
+
}
|
|
227460
|
+
if (!resolved || resolved.type !== "page") {
|
|
227461
|
+
throw captureError(
|
|
227462
|
+
"precondition",
|
|
227463
|
+
"target_unavailable",
|
|
227464
|
+
`received: target ${target} on port ${port}; expected: one existing page-tab target id (8-character prefix accepted). capture tab list shows available tabs.`
|
|
227465
|
+
);
|
|
227466
|
+
}
|
|
227467
|
+
const active = getActiveSession();
|
|
227468
|
+
if (active && !active.targetId) {
|
|
227469
|
+
throw captureError(
|
|
227470
|
+
"precondition",
|
|
227471
|
+
"active_session_target_unknown",
|
|
227472
|
+
`session ${active.sessionId} has not established its target yet, so capture tab close cannot prove ${resolved.id} is a background tab. Target the session with a page command first, or stop the session with capture session stop ${active.sessionId}.`
|
|
227473
|
+
);
|
|
227474
|
+
}
|
|
227475
|
+
if (active?.targetId === resolved.id) {
|
|
227476
|
+
throw captureError(
|
|
227477
|
+
"precondition",
|
|
227478
|
+
"active_session_target",
|
|
227479
|
+
`target ${resolved.id} is the active session ${active.sessionId}'s tab; capture tab close never leaves an active session pointing at a closed target. Use capture tab reset <url> to replace it or capture session stop ${active.sessionId} first.`
|
|
227480
|
+
);
|
|
227481
|
+
}
|
|
227482
|
+
try {
|
|
227483
|
+
await closeTarget(port, resolved.id);
|
|
227484
|
+
} catch (error) {
|
|
227485
|
+
throw captureError("world", "close_failed", `closing target ${resolved.id} on port ${port} failed: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
227486
|
+
}
|
|
227487
|
+
return resolved;
|
|
227488
|
+
});
|
|
227489
|
+
emitResult(buildTabClosedResult(tab, port), { json: parsed.json });
|
|
227490
|
+
}
|
|
227491
|
+
var USAGE10;
|
|
227492
|
+
var init_close = __esm({
|
|
227493
|
+
"src/cdp/commands/tab/close.ts"() {
|
|
227494
|
+
init_errors();
|
|
227495
|
+
init_detect();
|
|
227496
|
+
init_targets();
|
|
227497
|
+
init_session_context();
|
|
227498
|
+
init_coordinator();
|
|
227499
|
+
init_render();
|
|
227500
|
+
USAGE10 = `capture tab close \u2014 close one explicitly identified background browser tab.
|
|
227501
|
+
|
|
227502
|
+
input:
|
|
227503
|
+
<target> required \u2014 full tab target id or an unambiguous 8-character prefix
|
|
227504
|
+
--port <port> CDP endpoint (default: the auto-discovered preferred endpoint)
|
|
227505
|
+
|
|
227506
|
+
output: <tab-closed port=\u2026 target=\u2026> \u2014 the closed tab's full target id and last observed URL.
|
|
227507
|
+
effects: closes exactly one page tab. Refuses unless any active session's background-tab ownership is known, and never closes that session's tab; reset or stop the session first.`;
|
|
227508
|
+
}
|
|
227509
|
+
});
|
|
227510
|
+
|
|
227408
227511
|
// src/cdp/commands/tab/reset.ts
|
|
227409
227512
|
function buildTabResetResult(tab, port, sessionUpdated) {
|
|
227410
227513
|
return {
|
|
@@ -227445,46 +227548,48 @@ async function boundedLoadWait(tab) {
|
|
|
227445
227548
|
}
|
|
227446
227549
|
async function cmdTabReset(parsed, _args) {
|
|
227447
227550
|
if (parsed.help) {
|
|
227448
|
-
console.log(
|
|
227551
|
+
console.log(USAGE11);
|
|
227449
227552
|
return;
|
|
227450
227553
|
}
|
|
227451
227554
|
const url = parsed.positional[0];
|
|
227452
227555
|
if (!url) throw invalidInput("received: no URL; expected: capture tab reset <url> [--port <port>].", "missing_argument");
|
|
227453
|
-
|
|
227454
|
-
|
|
227455
|
-
|
|
227456
|
-
|
|
227457
|
-
|
|
227458
|
-
|
|
227459
|
-
|
|
227460
|
-
|
|
227461
|
-
|
|
227462
|
-
await boundedLoadWait(tab);
|
|
227463
|
-
emitResult(buildTabResetResult(tab, port, false), { json: parsed.json });
|
|
227464
|
-
return;
|
|
227465
|
-
}
|
|
227466
|
-
const op = await admitSessionOperation(session.dir);
|
|
227467
|
-
try {
|
|
227468
|
-
const result = await withSessionLifecycle(session.dir, async () => {
|
|
227469
|
-
const fresh = getActiveSession();
|
|
227470
|
-
if (!fresh || fresh.dir !== session.dir) throw captureError("precondition", "session_unavailable", "The active capture session is no longer available.");
|
|
227471
|
-
const scan = scanRecorderHandles(session.dir, deps5.lifecycle);
|
|
227472
|
-
if (scan.some((h) => h.classification === "unknown")) throw captureError("world", "recorder_liveness_unknown", "Cannot determine recorder liveness; refusing to reset.");
|
|
227473
|
-
if (scan.some((h) => h.classification === "malformed")) throw captureError("precondition", "recorder_unavailable", "A malformed recorder handle exists on this session; resolve it before resetting.");
|
|
227474
|
-
if (scan.some((h) => h.classification === "live")) throw captureError("precondition", "recorder_active", "A recording is active on this session; stop it first: `capture motion rec --stop`. Reset never rebinds a live recorder.");
|
|
227475
|
-
await clearDanglingRecorderPointer(session.dir, scan);
|
|
227476
|
-
const port = fresh.port ?? parsed.port ?? await deps5.detectCdpPort();
|
|
227556
|
+
return withSessionScopeLifecycle(async () => {
|
|
227557
|
+
const session = getActiveSession();
|
|
227558
|
+
if (!session) {
|
|
227559
|
+
let port;
|
|
227560
|
+
try {
|
|
227561
|
+
port = parsed.port ?? await deps5.detectCdpPort();
|
|
227562
|
+
} catch {
|
|
227563
|
+
throw captureError("world", "no_cdp_endpoint", "received: no --port, and no CDP endpoint was discovered on localhost; expected: a running CDP-enabled browser (or an explicit --port <port>).");
|
|
227564
|
+
}
|
|
227477
227565
|
const tab = await openTabOrThrow(port, url);
|
|
227478
227566
|
await boundedLoadWait(tab);
|
|
227479
|
-
|
|
227480
|
-
return
|
|
227481
|
-
}
|
|
227482
|
-
|
|
227483
|
-
|
|
227484
|
-
|
|
227485
|
-
|
|
227567
|
+
emitResult(buildTabResetResult(tab, port, false), { json: parsed.json });
|
|
227568
|
+
return;
|
|
227569
|
+
}
|
|
227570
|
+
const op = await admitSessionOperation(session.dir);
|
|
227571
|
+
try {
|
|
227572
|
+
const result = await withSessionLifecycle(session.dir, async () => {
|
|
227573
|
+
const fresh = getActiveSession();
|
|
227574
|
+
if (!fresh || fresh.dir !== session.dir) throw captureError("precondition", "session_unavailable", "The active capture session is no longer available.");
|
|
227575
|
+
const scan = scanRecorderHandles(session.dir, deps5.lifecycle);
|
|
227576
|
+
if (scan.some((h) => h.classification === "unknown")) throw captureError("world", "recorder_liveness_unknown", "Cannot determine recorder liveness; refusing to reset.");
|
|
227577
|
+
if (scan.some((h) => h.classification === "malformed")) throw captureError("precondition", "recorder_unavailable", "A malformed recorder handle exists on this session; resolve it before resetting.");
|
|
227578
|
+
if (scan.some((h) => h.classification === "live")) throw captureError("precondition", "recorder_active", "A recording is active on this session; stop it first: `capture motion rec --stop`. Reset never rebinds a live recorder.");
|
|
227579
|
+
await clearDanglingRecorderPointer(session.dir, scan);
|
|
227580
|
+
const port = fresh.port ?? parsed.port ?? await deps5.detectCdpPort();
|
|
227581
|
+
const tab = await openTabOrThrow(port, url);
|
|
227582
|
+
await boundedLoadWait(tab);
|
|
227583
|
+
await updateSessionState(session.dir, { targetId: tab.id, port });
|
|
227584
|
+
return buildTabResetResult(tab, port, true);
|
|
227585
|
+
}, deps5.lifecycle);
|
|
227586
|
+
emitResult(result, { json: parsed.json });
|
|
227587
|
+
} finally {
|
|
227588
|
+
await op.release();
|
|
227589
|
+
}
|
|
227590
|
+
});
|
|
227486
227591
|
}
|
|
227487
|
-
var
|
|
227592
|
+
var USAGE11, deps5;
|
|
227488
227593
|
var init_reset = __esm({
|
|
227489
227594
|
"src/cdp/commands/tab/reset.ts"() {
|
|
227490
227595
|
init_detect();
|
|
@@ -227494,7 +227599,7 @@ var init_reset = __esm({
|
|
|
227494
227599
|
init_coordinator();
|
|
227495
227600
|
init_errors();
|
|
227496
227601
|
init_render();
|
|
227497
|
-
|
|
227602
|
+
USAGE11 = `capture tab reset \u2014 abandon a stuck tab and open a fresh one at the URL.
|
|
227498
227603
|
|
|
227499
227604
|
input:
|
|
227500
227605
|
<url> required \u2014 the URL the fresh tab opens at
|
|
@@ -227566,7 +227671,7 @@ function buildNetworkResult(mode, target) {
|
|
|
227566
227671
|
}
|
|
227567
227672
|
async function cmdTabNetwork(parsed, _args) {
|
|
227568
227673
|
if (parsed.help) {
|
|
227569
|
-
console.log(
|
|
227674
|
+
console.log(USAGE12);
|
|
227570
227675
|
return;
|
|
227571
227676
|
}
|
|
227572
227677
|
const mode = parsed.positional[0];
|
|
@@ -227656,7 +227761,7 @@ async function cmdTabNetwork(parsed, _args) {
|
|
|
227656
227761
|
}
|
|
227657
227762
|
emitResult(buildNetworkResult(mode, targetId), { json: parsed.json });
|
|
227658
227763
|
}
|
|
227659
|
-
var fs15,
|
|
227764
|
+
var fs15, USAGE12;
|
|
227660
227765
|
var init_network = __esm({
|
|
227661
227766
|
"src/cdp/commands/tab/network.ts"() {
|
|
227662
227767
|
fs15 = __toESM(require("node:fs"));
|
|
@@ -227665,7 +227770,7 @@ var init_network = __esm({
|
|
|
227665
227770
|
init_coordinator();
|
|
227666
227771
|
init_client2();
|
|
227667
227772
|
init_render();
|
|
227668
|
-
|
|
227773
|
+
USAGE12 = `capture tab network \u2014 toggle connection-level network emulation for the active session's held tab.
|
|
227669
227774
|
|
|
227670
227775
|
input:
|
|
227671
227776
|
<offline|online> required \u2014 offline blocks HTTP requests and drops WebSocket connections; online restores connectivity
|
|
@@ -227687,6 +227792,8 @@ async function tabMain(parsed, args) {
|
|
|
227687
227792
|
return cmdTabList(rest, args);
|
|
227688
227793
|
case "open":
|
|
227689
227794
|
return cmdTabOpen(rest, args);
|
|
227795
|
+
case "close":
|
|
227796
|
+
return cmdTabClose(rest, args);
|
|
227690
227797
|
case "reset":
|
|
227691
227798
|
return cmdTabReset(rest, args);
|
|
227692
227799
|
case "network":
|
|
@@ -227704,12 +227811,13 @@ var init_tab = __esm({
|
|
|
227704
227811
|
init_errors();
|
|
227705
227812
|
init_list();
|
|
227706
227813
|
init_open();
|
|
227814
|
+
init_close();
|
|
227707
227815
|
init_reset();
|
|
227708
227816
|
init_network();
|
|
227709
227817
|
COMMAND_BLOCK3 = `<command name="tab">
|
|
227710
|
-
tab and connection plumbing \u2014 endpoint/tab discovery,
|
|
227711
|
-
use when finding a CDP endpoint or tab, opening/replacing a tab, or toggling connectivity; \`tab list\` is the probe for a running browser
|
|
227712
|
-
list \xB7 open \xB7 reset \xB7 network \u2014 \`capture tab -h\`
|
|
227818
|
+
tab and connection plumbing \u2014 endpoint/tab discovery, lifecycle, connection-level network emulation
|
|
227819
|
+
use when finding a CDP endpoint or tab, opening/closing/replacing a tab, or toggling connectivity; \`tab list\` is the probe for a running browser
|
|
227820
|
+
list \xB7 open \xB7 close \xB7 reset \xB7 network \u2014 \`capture tab -h\`
|
|
227713
227821
|
</command>`;
|
|
227714
227822
|
TAB_USAGE = `capture tab \u2014 tab and connection plumbing: discovery, lifecycle, network emulation.
|
|
227715
227823
|
|
|
@@ -227721,6 +227829,7 @@ the session's {target, port} pair together.
|
|
|
227721
227829
|
|
|
227722
227830
|
<subcommand name="list" args="[--port <port>]" whenToUse="discover CDP endpoints and the tabs open on them"/>
|
|
227723
227831
|
<subcommand name="open" args="<url> [--new] [--port <port>]" whenToUse="open a URL and get its tab id"/>
|
|
227832
|
+
<subcommand name="close" args="<target> [--port <port>]" whenToUse="close one explicitly identified background tab"/>
|
|
227724
227833
|
<subcommand name="reset" args="<url> [--port <port>]" whenToUse="abandon a stuck tab and open a fresh one (refuses while a recording is active; reaps dead recorder handles; updates the active session's {target, port} together)"/>
|
|
227725
227834
|
<subcommand name="network" args="<offline|online>" whenToUse="toggle connection-level network emulation for a tab"/>
|
|
227726
227835
|
|
|
@@ -228279,8 +228388,10 @@ function invocationLabel(method, waitEvent) {
|
|
|
228279
228388
|
async function runBrowserScope(method, params, parsed, timeoutMs, deps7 = DEFAULT_BROWSER_DEPS) {
|
|
228280
228389
|
const flagTarget = parsed.targetSource === "flag" ? parsed.target : void 0;
|
|
228281
228390
|
const session = getActiveSession();
|
|
228282
|
-
|
|
228283
|
-
|
|
228391
|
+
const bridgeSocket = session?.bridgeSocket;
|
|
228392
|
+
const heldBridgeActive = Boolean(bridgeSocket && fs17.existsSync(bridgeSocket));
|
|
228393
|
+
if (parsed.portSource !== "flag" && bridgeSocket && heldBridgeActive) {
|
|
228394
|
+
const resp = await deps7.sendBridgeRequest(bridgeSocket, {
|
|
228284
228395
|
method,
|
|
228285
228396
|
params,
|
|
228286
228397
|
targetId: flagTarget,
|
|
@@ -228304,8 +228415,9 @@ async function runBrowserScope(method, params, parsed, timeoutMs, deps7 = DEFAUL
|
|
|
228304
228415
|
});
|
|
228305
228416
|
return;
|
|
228306
228417
|
}
|
|
228418
|
+
const connectionReason = parsed.portSource === "flag" ? heldBridgeActive ? `Using explicitly selected CDP port ${parsed.port} instead of the active session bridge` : `Using explicitly selected CDP port ${parsed.port}` : "No held session bridge active";
|
|
228307
228419
|
console.error(
|
|
228308
|
-
|
|
228420
|
+
`${connectionReason} \u2014 this one-shot connection closes when the command exits, so any browser-level grant or target enablement made here reverts immediately after.`
|
|
228309
228421
|
);
|
|
228310
228422
|
const port = parsed.port ?? await deps7.detectCdpPort();
|
|
228311
228423
|
const { client } = await deps7.getBrowserClient(port);
|
|
@@ -228418,7 +228530,8 @@ Input:
|
|
|
228418
228530
|
--params <json> JSON-encoded params object for the method. Spec deviation: params stay inline JSON (no file indirection) \u2014 raw CDP params are small protocol-defined objects.
|
|
228419
228531
|
--wait-event <Domain.event> wait for (and return) the next occurrence of a protocol event; combinable with a method (the method is sent first) or usable alone.
|
|
228420
228532
|
--browser route through the held connection (session start --hold) instead of a one-shot page websocket. Connection-scoped state (permission grants, domain enables) reverts the instant its connection closes \u2014 it survives across commands only inside a held session.
|
|
228421
|
-
--
|
|
228533
|
+
--port <port> CDP endpoint. An explicit flag selects that endpoint even when an active session holds another browser connection.
|
|
228534
|
+
--target <id> with --browser: attach a flattened CDP session on the held connection to this target (for target-scoped domains), including an already-open tab adopted by \`session start --hold\` without --url; without --browser: the page target to run against. 8-char id prefix accepted.
|
|
228422
228535
|
--timeout <ms> event-wait timeout (default ${DEFAULT_TIMEOUT_MS}ms).
|
|
228423
228536
|
|
|
228424
228537
|
Output:
|
|
@@ -230035,9 +230148,9 @@ async function collectStylesInner(ctx, styleSheetUrls, styleSheetHeaders) {
|
|
|
230035
230148
|
}
|
|
230036
230149
|
const sourceCache = /* @__PURE__ */ new Map();
|
|
230037
230150
|
const elements = await Promise.all(
|
|
230038
|
-
facts.map(async (
|
|
230151
|
+
facts.map(async (fact4, index) => {
|
|
230039
230152
|
const ref = resolved[index];
|
|
230040
|
-
const computed2 = normalizeComputed(
|
|
230153
|
+
const computed2 = normalizeComputed(fact4.computed);
|
|
230041
230154
|
let winningDeclarations;
|
|
230042
230155
|
let provenanceUnavailable;
|
|
230043
230156
|
if (ref?.nodeId !== void 0) {
|
|
@@ -230063,7 +230176,7 @@ async function collectStylesInner(ctx, styleSheetUrls, styleSheetHeaders) {
|
|
|
230063
230176
|
}
|
|
230064
230177
|
return {
|
|
230065
230178
|
id: `s-${index}`,
|
|
230066
|
-
selector: sanitizeString(
|
|
230179
|
+
selector: sanitizeString(fact4.cssPath),
|
|
230067
230180
|
...resolvedIdentity3(ref?.backendNodeId),
|
|
230068
230181
|
computed: computed2,
|
|
230069
230182
|
winningDeclarations,
|
|
@@ -231015,11 +231128,11 @@ var init_text = __esm({
|
|
|
231015
231128
|
} else {
|
|
231016
231129
|
rawPlatformFontFamilies = fontsResult.fonts.map((font) => font.familyName ?? "");
|
|
231017
231130
|
platformFonts = fontsResult.fonts.map((font) => {
|
|
231018
|
-
const
|
|
231131
|
+
const fact4 = {
|
|
231019
231132
|
familyName: sanitizeString(font.familyName),
|
|
231020
231133
|
isCustomFont: !!font.isCustomFont
|
|
231021
231134
|
};
|
|
231022
|
-
return typeof font.glyphCount === "number" ? { ...
|
|
231135
|
+
return typeof font.glyphCount === "number" ? { ...fact4, glyphCount: font.glyphCount } : fact4;
|
|
231023
231136
|
});
|
|
231024
231137
|
platformFontsAvailable = true;
|
|
231025
231138
|
platformFontsUnavailableReason = void 0;
|
|
@@ -234869,36 +234982,36 @@ document.querySelectorAll('img, video, canvas, svg, iframe').length;`;
|
|
|
234869
234982
|
resolved = facts.map(() => void 0);
|
|
234870
234983
|
}
|
|
234871
234984
|
}
|
|
234872
|
-
const elements = facts.map((
|
|
234873
|
-
const natural =
|
|
234985
|
+
const elements = facts.map((fact4, index) => {
|
|
234986
|
+
const natural = fact4.naturalWidth !== null && fact4.naturalHeight !== null ? { w: fact4.naturalWidth, h: fact4.naturalHeight } : null;
|
|
234874
234987
|
const intrinsicAspectRatio = natural && natural.w > 0 && natural.h > 0 ? natural.w / natural.h : null;
|
|
234875
|
-
const crop =
|
|
234988
|
+
const crop = fact4.styleUnavailable ? null : computeObjectFitCrop(natural, { w: fact4.rect.width, h: fact4.rect.height }, fact4.objectFit, fact4.objectPosition);
|
|
234876
234989
|
return {
|
|
234877
234990
|
id: `m-${index}`,
|
|
234878
|
-
selector:
|
|
234991
|
+
selector: fact4.cssPath ? sanitizeString(fact4.cssPath) : "",
|
|
234879
234992
|
...resolvedIdentity8(resolved[index]?.backendNodeId),
|
|
234880
|
-
tag:
|
|
234881
|
-
rect:
|
|
234882
|
-
visible:
|
|
234883
|
-
naturalWidth:
|
|
234884
|
-
naturalHeight:
|
|
234885
|
-
renderedWidth:
|
|
234886
|
-
renderedHeight:
|
|
234887
|
-
devicePixelRatio:
|
|
234888
|
-
currentSrc: sanitizeOptional2(
|
|
234889
|
-
decodeState:
|
|
234993
|
+
tag: fact4.tag,
|
|
234994
|
+
rect: fact4.rect,
|
|
234995
|
+
visible: fact4.visible,
|
|
234996
|
+
naturalWidth: fact4.naturalWidth,
|
|
234997
|
+
naturalHeight: fact4.naturalHeight,
|
|
234998
|
+
renderedWidth: fact4.rect.width,
|
|
234999
|
+
renderedHeight: fact4.rect.height,
|
|
235000
|
+
devicePixelRatio: fact4.dpr,
|
|
235001
|
+
currentSrc: sanitizeOptional2(fact4.currentSrc),
|
|
235002
|
+
decodeState: fact4.decodeState,
|
|
234890
235003
|
intrinsicAspectRatio,
|
|
234891
|
-
objectFit: sanitizeOptional2(
|
|
234892
|
-
objectPosition: sanitizeOptional2(
|
|
235004
|
+
objectFit: sanitizeOptional2(fact4.objectFit),
|
|
235005
|
+
objectPosition: sanitizeOptional2(fact4.objectPosition),
|
|
234893
235006
|
crop,
|
|
234894
|
-
styleUnavailable:
|
|
234895
|
-
intrinsicDimsUnavailable:
|
|
234896
|
-
contextType:
|
|
234897
|
-
backingWidth:
|
|
234898
|
-
backingHeight:
|
|
234899
|
-
poster:
|
|
234900
|
-
src:
|
|
234901
|
-
crossOrigin:
|
|
235007
|
+
styleUnavailable: fact4.styleUnavailable || void 0,
|
|
235008
|
+
intrinsicDimsUnavailable: fact4.intrinsicDimsUnavailable || void 0,
|
|
235009
|
+
contextType: fact4.contextType,
|
|
235010
|
+
backingWidth: fact4.backingWidth,
|
|
235011
|
+
backingHeight: fact4.backingHeight,
|
|
235012
|
+
poster: fact4.tag === "video" ? sanitizeOptional2(fact4.poster) : void 0,
|
|
235013
|
+
src: fact4.tag === "iframe" ? sanitizeOptional2(fact4.src) : void 0,
|
|
235014
|
+
crossOrigin: fact4.tag === "iframe" ? fact4.crossOrigin : void 0
|
|
234902
235015
|
};
|
|
234903
235016
|
});
|
|
234904
235017
|
ctx.write.json("media.json", {
|
|
@@ -235381,16 +235494,16 @@ function rectsOverlap(a, b) {
|
|
|
235381
235494
|
return a.x < b.x + b.w && a.x + a.w > b.x && a.y < b.y + b.h && a.y + a.h > b.y;
|
|
235382
235495
|
}
|
|
235383
235496
|
function annotateUnstableFacts(facts, regions) {
|
|
235384
|
-
return facts.map((
|
|
235497
|
+
return facts.map((fact4) => {
|
|
235385
235498
|
const caveats = [];
|
|
235386
235499
|
for (const region of regions) {
|
|
235387
|
-
const byElement =
|
|
235388
|
-
const byRect =
|
|
235500
|
+
const byElement = fact4.elementId !== void 0 && (region.elementIds?.includes(fact4.elementId) ?? false);
|
|
235501
|
+
const byRect = fact4.rect !== void 0 && region.rect !== void 0 && rectsOverlap(fact4.rect, region.rect);
|
|
235389
235502
|
if (byElement || byRect) {
|
|
235390
235503
|
caveats.push({ regionId: region.id, selector: region.selector, reason: region.reason });
|
|
235391
235504
|
}
|
|
235392
235505
|
}
|
|
235393
|
-
return { fact:
|
|
235506
|
+
return { fact: fact4, caveats };
|
|
235394
235507
|
});
|
|
235395
235508
|
}
|
|
235396
235509
|
var fs18, path20, ArtifactResolutionError, SNAP_CONFIG, REC_CONFIG, CREATING_COMMAND_BY_FILE;
|
|
@@ -235675,7 +235788,7 @@ function errorSections(details) {
|
|
|
235675
235788
|
}
|
|
235676
235789
|
async function cmdMeasureSnap(parsed, _args) {
|
|
235677
235790
|
if (parsed.help) {
|
|
235678
|
-
console.log(
|
|
235791
|
+
console.log(USAGE13);
|
|
235679
235792
|
return;
|
|
235680
235793
|
}
|
|
235681
235794
|
const captures = [];
|
|
@@ -235725,7 +235838,7 @@ async function cmdMeasureSnap(parsed, _args) {
|
|
|
235725
235838
|
process.exitCode = 1;
|
|
235726
235839
|
}
|
|
235727
235840
|
}
|
|
235728
|
-
var fs19, path21, import_crypto2,
|
|
235841
|
+
var fs19, path21, import_crypto2, USAGE13;
|
|
235729
235842
|
var init_snap = __esm({
|
|
235730
235843
|
"src/cdp/commands/measure/snap.ts"() {
|
|
235731
235844
|
fs19 = __toESM(require("fs"));
|
|
@@ -235743,7 +235856,7 @@ var init_snap = __esm({
|
|
|
235743
235856
|
init_artifact();
|
|
235744
235857
|
init_errors();
|
|
235745
235858
|
init_render();
|
|
235746
|
-
|
|
235859
|
+
USAGE13 = `capture measure snap [url|snap] \u2014 drive the page and write one settled snapshot substrate directory
|
|
235747
235860
|
|
|
235748
235861
|
input:
|
|
235749
235862
|
[url|snap] a URL drives the page fresh; a snap id or absolute path re-captures states over that base snapshot. Outside a session a URL writes under a private one-shot session; with an active session, snapshots are written under it and later resolve by snap id
|
|
@@ -235986,7 +236099,7 @@ function checkSnapshot(ref, requested) {
|
|
|
235986
236099
|
}
|
|
235987
236100
|
const regions = unstableRegionsFor(ref);
|
|
235988
236101
|
const annotated = annotateUnstableFacts(findings.map((f) => ({ ...f, elementId: f.elementId, rect: f.rect })), regions);
|
|
235989
|
-
return { findings: annotated.map(({ fact:
|
|
236102
|
+
return { findings: annotated.map(({ fact: fact4, caveats }) => ({ ...fact4, caveats })), elementCount: elements.length, settled: meta.settled, viewport: vp };
|
|
235990
236103
|
}
|
|
235991
236104
|
function writeFindingCrop(ref, finding2, index) {
|
|
235992
236105
|
if (!finding2.rect || !artifactExists(ref, "screenshot.png")) return void 0;
|
|
@@ -236047,7 +236160,7 @@ function caveatLine(caveats) {
|
|
|
236047
236160
|
}
|
|
236048
236161
|
async function cmdMeasureCheck(parsed, _args) {
|
|
236049
236162
|
if (parsed.help) {
|
|
236050
|
-
console.log(
|
|
236163
|
+
console.log(USAGE14);
|
|
236051
236164
|
return;
|
|
236052
236165
|
}
|
|
236053
236166
|
if (parsed.positional.length > 1) {
|
|
@@ -236104,14 +236217,14 @@ async function cmdMeasureCheck(parsed, _args) {
|
|
|
236104
236217
|
process.exitCode = 1;
|
|
236105
236218
|
}
|
|
236106
236219
|
}
|
|
236107
|
-
var
|
|
236220
|
+
var USAGE14, DEFAULT_FINDING_LIMIT;
|
|
236108
236221
|
var init_check2 = __esm({
|
|
236109
236222
|
"src/cdp/commands/measure/check.ts"() {
|
|
236110
236223
|
init_artifact();
|
|
236111
236224
|
init_render();
|
|
236112
236225
|
init_snap();
|
|
236113
236226
|
init_check();
|
|
236114
|
-
|
|
236227
|
+
USAGE14 = `capture measure check [url|snap] \u2014 read threshold/fact measurements from a settled snapshot
|
|
236115
236228
|
|
|
236116
236229
|
input:
|
|
236117
236230
|
[url|snap] a URL creates one one-shot snapshot first; a snap id or absolute path is read without re-driving the browser
|
|
@@ -236695,7 +236808,7 @@ function provenanceLines(records) {
|
|
|
236695
236808
|
}
|
|
236696
236809
|
async function cmdMeasureDiff(parsed, _args) {
|
|
236697
236810
|
if (parsed.help) {
|
|
236698
|
-
console.log(
|
|
236811
|
+
console.log(USAGE15);
|
|
236699
236812
|
return;
|
|
236700
236813
|
}
|
|
236701
236814
|
if (parsed.positional.length > 0 || !parsed.before || !parsed.after) {
|
|
@@ -236760,13 +236873,13 @@ async function cmdMeasureDiff(parsed, _args) {
|
|
|
236760
236873
|
process.exitCode = 1;
|
|
236761
236874
|
}
|
|
236762
236875
|
}
|
|
236763
|
-
var
|
|
236876
|
+
var USAGE15;
|
|
236764
236877
|
var init_diff3 = __esm({
|
|
236765
236878
|
"src/cdp/commands/measure/diff.ts"() {
|
|
236766
236879
|
init_artifact();
|
|
236767
236880
|
init_diff2();
|
|
236768
236881
|
init_render();
|
|
236769
|
-
|
|
236882
|
+
USAGE15 = `capture measure diff \u2014 structured before/after diff over two settled snapshots
|
|
236770
236883
|
|
|
236771
236884
|
input:
|
|
236772
236885
|
--before <snap> earlier snapshot id or absolute path (required; no positional target \u2014 both snapshots must already exist)
|
|
@@ -236969,7 +237082,7 @@ function errorResult(message, status) {
|
|
|
236969
237082
|
}
|
|
236970
237083
|
async function cmdMeasureCensus(parsed, _args) {
|
|
236971
237084
|
if (parsed.help) {
|
|
236972
|
-
console.log(
|
|
237085
|
+
console.log(USAGE16);
|
|
236973
237086
|
return;
|
|
236974
237087
|
}
|
|
236975
237088
|
if (parsed.positional.length) {
|
|
@@ -237000,7 +237113,7 @@ async function cmdMeasureCensus(parsed, _args) {
|
|
|
237000
237113
|
process.exitCode = 1;
|
|
237001
237114
|
}
|
|
237002
237115
|
}
|
|
237003
|
-
var fs23,
|
|
237116
|
+
var fs23, USAGE16;
|
|
237004
237117
|
var init_census2 = __esm({
|
|
237005
237118
|
"src/cdp/commands/measure/census.ts"() {
|
|
237006
237119
|
fs23 = __toESM(require("fs"));
|
|
@@ -237008,7 +237121,7 @@ var init_census2 = __esm({
|
|
|
237008
237121
|
init_artifact();
|
|
237009
237122
|
init_render();
|
|
237010
237123
|
init_census();
|
|
237011
|
-
|
|
237124
|
+
USAGE16 = `capture measure census --axis <axis> \u2014 value distributions and token-audit facts across one or more settled snapshots
|
|
237012
237125
|
|
|
237013
237126
|
input:
|
|
237014
237127
|
--axis <axis> color|font|spacing|radius|shadow|animation|geometry|media|queries (required)
|
|
@@ -237414,7 +237527,7 @@ function invalidInput2(message) {
|
|
|
237414
237527
|
}
|
|
237415
237528
|
async function cmdMeasureExplain(parsed, _args) {
|
|
237416
237529
|
if (parsed.help) {
|
|
237417
|
-
console.log(
|
|
237530
|
+
console.log(USAGE17);
|
|
237418
237531
|
return;
|
|
237419
237532
|
}
|
|
237420
237533
|
if (parsed.positional.length !== 1) {
|
|
@@ -237474,13 +237587,13 @@ async function cmdMeasureExplain(parsed, _args) {
|
|
|
237474
237587
|
process.exitCode = 1;
|
|
237475
237588
|
}
|
|
237476
237589
|
}
|
|
237477
|
-
var
|
|
237590
|
+
var USAGE17;
|
|
237478
237591
|
var init_explain2 = __esm({
|
|
237479
237592
|
"src/cdp/commands/measure/explain.ts"() {
|
|
237480
237593
|
init_explain();
|
|
237481
237594
|
init_artifact();
|
|
237482
237595
|
init_render();
|
|
237483
|
-
|
|
237596
|
+
USAGE17 = `capture measure explain <snap> --selector <sel> \u2014 per-element cascade/stacking/clipping explanation over one snapshot
|
|
237484
237597
|
|
|
237485
237598
|
input:
|
|
237486
237599
|
<snap> snapshot id in the active session or absolute artifact path (required)
|
|
@@ -237744,7 +237857,7 @@ async function cmdMeasureSweep(parsed, args) {
|
|
|
237744
237857
|
async function runMeasureSweep(parsed, _args, overrides = {}) {
|
|
237745
237858
|
const dependencies = { ...defaultDependencies, ...overrides };
|
|
237746
237859
|
if (parsed.help) {
|
|
237747
|
-
console.log(
|
|
237860
|
+
console.log(USAGE18);
|
|
237748
237861
|
return;
|
|
237749
237862
|
}
|
|
237750
237863
|
if (parsed.positional.length > 1) {
|
|
@@ -237855,7 +237968,7 @@ async function runMeasureSweep(parsed, _args, overrides = {}) {
|
|
|
237855
237968
|
process.exitCode = 1;
|
|
237856
237969
|
}
|
|
237857
237970
|
}
|
|
237858
|
-
var fs25, path26, import_crypto3,
|
|
237971
|
+
var fs25, path26, import_crypto3, USAGE18, SAMPLE_LIMIT, defaultDependencies, parsePositive;
|
|
237859
237972
|
var init_sweep2 = __esm({
|
|
237860
237973
|
"src/cdp/commands/measure/sweep.ts"() {
|
|
237861
237974
|
fs25 = __toESM(require("fs"));
|
|
@@ -237868,7 +237981,7 @@ var init_sweep2 = __esm({
|
|
|
237868
237981
|
init_render();
|
|
237869
237982
|
init_leaf_grammar();
|
|
237870
237983
|
init_sweep();
|
|
237871
|
-
|
|
237984
|
+
USAGE18 = `capture measure sweep [url] --axis <axis> \u2014 responsive/environment sampling with recursive bracketing of observed state changes
|
|
237872
237985
|
|
|
237873
237986
|
input:
|
|
237874
237987
|
[url] page to sweep; outside a session, snapshots and sweep.json are written under one private one-shot measure directory
|
|
@@ -238008,7 +238121,7 @@ function recoveryResult(err) {
|
|
|
238008
238121
|
}
|
|
238009
238122
|
async function cmdMeasureMapFocus(parsed, _args) {
|
|
238010
238123
|
if (parsed.help) {
|
|
238011
|
-
console.log(
|
|
238124
|
+
console.log(USAGE19);
|
|
238012
238125
|
return;
|
|
238013
238126
|
}
|
|
238014
238127
|
if (parsed.positional.length !== 1) {
|
|
@@ -238032,14 +238145,14 @@ async function cmdMeasureMapFocus(parsed, _args) {
|
|
|
238032
238145
|
process.exitCode = 1;
|
|
238033
238146
|
}
|
|
238034
238147
|
}
|
|
238035
|
-
var
|
|
238148
|
+
var USAGE19;
|
|
238036
238149
|
var init_map_focus2 = __esm({
|
|
238037
238150
|
"src/cdp/commands/measure/map-focus.ts"() {
|
|
238038
238151
|
init_snap();
|
|
238039
238152
|
init_map_focus();
|
|
238040
238153
|
init_artifact();
|
|
238041
238154
|
init_render();
|
|
238042
|
-
|
|
238155
|
+
USAGE19 = `capture measure map focus [url|snap] \u2014 keyboard traversal facts recorded in a snapshot's focus.json
|
|
238043
238156
|
|
|
238044
238157
|
input:
|
|
238045
238158
|
[url|snap] required target: a URL creates a settled snapshot first; a snapshot id or absolute path is read without re-driving the browser
|
|
@@ -238255,7 +238368,7 @@ async function runMeasureMapScroll(parsed, deps7 = {}) {
|
|
|
238255
238368
|
const captureSnap = deps7.captureSnap ?? captureMeasureSnap;
|
|
238256
238369
|
const emit = deps7.emit ?? emitResult;
|
|
238257
238370
|
if (parsed.help) {
|
|
238258
|
-
console.log(
|
|
238371
|
+
console.log(USAGE20);
|
|
238259
238372
|
return;
|
|
238260
238373
|
}
|
|
238261
238374
|
if (parsed.positional.length > 1) {
|
|
@@ -238309,14 +238422,14 @@ async function runMeasureMapScroll(parsed, deps7 = {}) {
|
|
|
238309
238422
|
async function cmdMeasureMapScroll(parsed, _args) {
|
|
238310
238423
|
await runMeasureMapScroll(parsed);
|
|
238311
238424
|
}
|
|
238312
|
-
var
|
|
238425
|
+
var USAGE20;
|
|
238313
238426
|
var init_map_scroll2 = __esm({
|
|
238314
238427
|
"src/cdp/commands/measure/map-scroll.ts"() {
|
|
238315
238428
|
init_snap();
|
|
238316
238429
|
init_artifact();
|
|
238317
238430
|
init_render();
|
|
238318
238431
|
init_map_scroll();
|
|
238319
|
-
|
|
238432
|
+
USAGE20 = `capture measure map scroll [url|snap] \u2014 scroll-container topology recorded in a snapshot's scroll.json
|
|
238320
238433
|
|
|
238321
238434
|
input:
|
|
238322
238435
|
[url|snap] required target: a URL creates a settled snapshot first; a snapshot id from the active session or an absolute snapshot artifact path is read without re-driving the browser
|
|
@@ -238483,7 +238596,7 @@ function errorResult2(err) {
|
|
|
238483
238596
|
}
|
|
238484
238597
|
async function cmdMeasureMapLayers(parsed, _args) {
|
|
238485
238598
|
if (parsed.help) {
|
|
238486
|
-
console.log(
|
|
238599
|
+
console.log(USAGE21);
|
|
238487
238600
|
return;
|
|
238488
238601
|
}
|
|
238489
238602
|
if (parsed.positional.length > 1) {
|
|
@@ -238516,14 +238629,14 @@ async function cmdMeasureMapLayers(parsed, _args) {
|
|
|
238516
238629
|
process.exitCode = 1;
|
|
238517
238630
|
}
|
|
238518
238631
|
}
|
|
238519
|
-
var
|
|
238632
|
+
var USAGE21;
|
|
238520
238633
|
var init_map_layers2 = __esm({
|
|
238521
238634
|
"src/cdp/commands/measure/map-layers.ts"() {
|
|
238522
238635
|
init_snap();
|
|
238523
238636
|
init_map_layers();
|
|
238524
238637
|
init_artifact();
|
|
238525
238638
|
init_render();
|
|
238526
|
-
|
|
238639
|
+
USAGE21 = `capture measure map layers [url|snap] \u2014 paint/compositor facts recorded in a snapshot's layers.json
|
|
238527
238640
|
|
|
238528
238641
|
input:
|
|
238529
238642
|
[url|snap] required target: a URL creates a settled snapshot first; a snapshot id or absolute path is read without re-driving the browser
|
|
@@ -239007,7 +239120,7 @@ function recoveryResult2(err) {
|
|
|
239007
239120
|
}
|
|
239008
239121
|
async function cmdMeasureMapAx(parsed, _args) {
|
|
239009
239122
|
if (parsed.help) {
|
|
239010
|
-
console.log(
|
|
239123
|
+
console.log(USAGE22);
|
|
239011
239124
|
return;
|
|
239012
239125
|
}
|
|
239013
239126
|
if (parsed.positional.length !== 1) {
|
|
@@ -239031,14 +239144,14 @@ async function cmdMeasureMapAx(parsed, _args) {
|
|
|
239031
239144
|
process.exitCode = 1;
|
|
239032
239145
|
}
|
|
239033
239146
|
}
|
|
239034
|
-
var
|
|
239147
|
+
var USAGE22;
|
|
239035
239148
|
var init_map_ax2 = __esm({
|
|
239036
239149
|
"src/cdp/commands/measure/map-ax.ts"() {
|
|
239037
239150
|
init_snap();
|
|
239038
239151
|
init_map_ax();
|
|
239039
239152
|
init_artifact();
|
|
239040
239153
|
init_render();
|
|
239041
|
-
|
|
239154
|
+
USAGE22 = `capture measure map ax [url|snap] \u2014 accessibility-tree facts recorded in a snapshot's ax.json joined against geometry.json
|
|
239042
239155
|
|
|
239043
239156
|
input:
|
|
239044
239157
|
[url|snap] required target: a URL creates a settled snapshot first; a snapshot id or absolute path is read without re-driving the browser
|
|
@@ -239145,7 +239258,7 @@ capture measure map <leaf> -h Per-leaf usage`;
|
|
|
239145
239258
|
// src/cdp/commands/motion/rec.ts
|
|
239146
239259
|
async function cmdMotionRec(parsed, _args) {
|
|
239147
239260
|
if (parsed.help) {
|
|
239148
|
-
console.log(
|
|
239261
|
+
console.log(USAGE23);
|
|
239149
239262
|
return;
|
|
239150
239263
|
}
|
|
239151
239264
|
const lifecycleError = validateLifecycleInputs(parsed);
|
|
@@ -239509,7 +239622,7 @@ function listRecordingArtifacts(recDir) {
|
|
|
239509
239622
|
}
|
|
239510
239623
|
return names.sort().map((name) => ({ name }));
|
|
239511
239624
|
}
|
|
239512
|
-
var fs26, path27, crypto9, import_child_process3, deps6,
|
|
239625
|
+
var fs26, path27, crypto9, import_child_process3, deps6, USAGE23, DoActionError;
|
|
239513
239626
|
var init_rec = __esm({
|
|
239514
239627
|
"src/cdp/commands/motion/rec.ts"() {
|
|
239515
239628
|
fs26 = __toESM(require("fs"));
|
|
@@ -239541,7 +239654,7 @@ var init_rec = __esm({
|
|
|
239541
239654
|
stopComposedRecorder,
|
|
239542
239655
|
encodeVideo: encodeVideoIfAvailable
|
|
239543
239656
|
};
|
|
239544
|
-
|
|
239657
|
+
USAGE23 = `capture motion rec \u2014 record the page over time: composed (whatever the active session does between --start and --stop) or one-shot (one scripted action on a URL or the active session tab).
|
|
239545
239658
|
|
|
239546
239659
|
input:
|
|
239547
239660
|
[url] --do <action> one-shot: open <url> (or record the active session tab when <url> is omitted), record one action, finalize
|
|
@@ -239854,7 +239967,7 @@ var init_mask = __esm({
|
|
|
239854
239967
|
// src/cdp/commands/motion/mask.ts
|
|
239855
239968
|
async function cmdMotionMask(parsed, _args) {
|
|
239856
239969
|
if (parsed.help) {
|
|
239857
|
-
console.log(
|
|
239970
|
+
console.log(USAGE24);
|
|
239858
239971
|
return;
|
|
239859
239972
|
}
|
|
239860
239973
|
if (parsed.positional.length !== 1) {
|
|
@@ -239916,14 +240029,14 @@ function emitCommandError2(parsed, status, message) {
|
|
|
239916
240029
|
}, { json: parsed.json });
|
|
239917
240030
|
process.exitCode = 1;
|
|
239918
240031
|
}
|
|
239919
|
-
var DEFAULT_REGION_LIMIT,
|
|
240032
|
+
var DEFAULT_REGION_LIMIT, USAGE24;
|
|
239920
240033
|
var init_mask2 = __esm({
|
|
239921
240034
|
"src/cdp/commands/motion/mask.ts"() {
|
|
239922
240035
|
init_mask();
|
|
239923
240036
|
init_artifact();
|
|
239924
240037
|
init_render();
|
|
239925
240038
|
DEFAULT_REGION_LIMIT = 20;
|
|
239926
|
-
|
|
240039
|
+
USAGE24 = `capture motion mask <rec> \u2014 motion-diff composite image plus per-region facts over a finalized recording
|
|
239927
240040
|
|
|
239928
240041
|
input:
|
|
239929
240042
|
<rec> recording id in the active session or an absolute recording path (required; the recording must be finalized)
|
|
@@ -240061,7 +240174,7 @@ var init_timeline = __esm({
|
|
|
240061
240174
|
// src/cdp/commands/motion/timeline.ts
|
|
240062
240175
|
async function cmdMotionTimeline(parsed, _args) {
|
|
240063
240176
|
if (parsed.help) {
|
|
240064
|
-
console.log(
|
|
240177
|
+
console.log(USAGE25);
|
|
240065
240178
|
return;
|
|
240066
240179
|
}
|
|
240067
240180
|
const recArg = parsed.positional[0];
|
|
@@ -240159,13 +240272,13 @@ function emitCommandError3(parsed, status, message, recovery, ref, state) {
|
|
|
240159
240272
|
emitResult(result, { json: parsed.json });
|
|
240160
240273
|
process.exitCode = 1;
|
|
240161
240274
|
}
|
|
240162
|
-
var
|
|
240275
|
+
var USAGE25;
|
|
240163
240276
|
var init_timeline2 = __esm({
|
|
240164
240277
|
"src/cdp/commands/motion/timeline.ts"() {
|
|
240165
240278
|
init_artifact();
|
|
240166
240279
|
init_timeline();
|
|
240167
240280
|
init_render();
|
|
240168
|
-
|
|
240281
|
+
USAGE25 = `capture motion timeline <rec> --element <sel> \u2014 per-frame geometry/scroll/property timeline for one element across a finalized recording
|
|
240169
240282
|
|
|
240170
240283
|
input:
|
|
240171
240284
|
<rec> recording id in the active session or an absolute recording path (required; the recording must be finalized)
|
|
@@ -240457,7 +240570,7 @@ var init_jank = __esm({
|
|
|
240457
240570
|
// src/cdp/commands/motion/jank.ts
|
|
240458
240571
|
async function cmdMotionJank(parsed, _args) {
|
|
240459
240572
|
if (parsed.help) {
|
|
240460
|
-
console.log(
|
|
240573
|
+
console.log(USAGE26);
|
|
240461
240574
|
return;
|
|
240462
240575
|
}
|
|
240463
240576
|
if (parsed.positional.length !== 1 || !parsed.positional[0]) {
|
|
@@ -240550,13 +240663,13 @@ function emitCommandError4(parsed, status, message, recovery) {
|
|
|
240550
240663
|
emitResult(result, { json: parsed.json });
|
|
240551
240664
|
process.exitCode = 1;
|
|
240552
240665
|
}
|
|
240553
|
-
var
|
|
240666
|
+
var USAGE26;
|
|
240554
240667
|
var init_jank2 = __esm({
|
|
240555
240668
|
"src/cdp/commands/motion/jank.ts"() {
|
|
240556
240669
|
init_artifact();
|
|
240557
240670
|
init_render();
|
|
240558
240671
|
init_jank();
|
|
240559
|
-
|
|
240672
|
+
USAGE26 = `capture motion jank <rec> \u2014 dropped-frame, long-task-record, and layout-shift facts over a finalized recording
|
|
240560
240673
|
|
|
240561
240674
|
input:
|
|
240562
240675
|
<rec> recording id in the active session or an absolute recording path (required; the recording must be finalized)
|
|
@@ -240811,7 +240924,7 @@ function emitError(parsed, status, message, sections) {
|
|
|
240811
240924
|
}
|
|
240812
240925
|
async function cmdMotionResponse(parsed, _args) {
|
|
240813
240926
|
if (parsed.help) {
|
|
240814
|
-
console.log(
|
|
240927
|
+
console.log(USAGE27);
|
|
240815
240928
|
return;
|
|
240816
240929
|
}
|
|
240817
240930
|
if (parsed.positional.length !== 1) {
|
|
@@ -240852,13 +240965,13 @@ async function cmdMotionResponse(parsed, _args) {
|
|
|
240852
240965
|
return emitError(parsed, "response_unavailable", err instanceof Error ? err.message : String(err));
|
|
240853
240966
|
}
|
|
240854
240967
|
}
|
|
240855
|
-
var
|
|
240968
|
+
var USAGE27;
|
|
240856
240969
|
var init_response2 = __esm({
|
|
240857
240970
|
"src/cdp/commands/motion/response.ts"() {
|
|
240858
240971
|
init_render();
|
|
240859
240972
|
init_artifact();
|
|
240860
240973
|
init_response();
|
|
240861
|
-
|
|
240974
|
+
USAGE27 = `capture motion response <rec> \u2014 input-to-settled response timeline over a finalized recording
|
|
240862
240975
|
|
|
240863
240976
|
input:
|
|
240864
240977
|
<rec> recording id in the active session or an absolute recording path (required; the recording must be finalized)
|
|
@@ -241059,7 +241172,7 @@ CDP_PORT / CDP_TARGET pin the browser + tab for orchestrators \u2014 precedence:
|
|
|
241059
241172
|
explicit flag > active session > env.`;
|
|
241060
241173
|
}
|
|
241061
241174
|
function printVersion() {
|
|
241062
|
-
const declared = "1.3.
|
|
241175
|
+
const declared = "1.3.16";
|
|
241063
241176
|
if (declared) {
|
|
241064
241177
|
console.log(declared);
|
|
241065
241178
|
return;
|