pi-agent-browser-native 0.6.12 → 0.6.14
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/CHANGELOG.md +27 -0
- package/README.md +24 -20
- package/dist/extensions/agent-browser/index.js +24 -10
- package/dist/extensions/agent-browser/lib/argv-grammar.js +1 -0
- package/dist/extensions/agent-browser/lib/command-taxonomy.js +4 -0
- package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +32 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +14 -3
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +1 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +21 -5
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +15 -4
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +3 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +20 -6
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +14 -3
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +5 -2
- package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +4 -2
- package/dist/extensions/agent-browser/lib/orchestration/native-session-defaults.js +100 -9
- package/dist/extensions/agent-browser/lib/playbook.js +5 -4
- package/dist/extensions/agent-browser/lib/process.js +18 -5
- package/dist/extensions/agent-browser/lib/recording-reservations.js +8 -1
- package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +15 -1
- package/dist/extensions/agent-browser/lib/results/presentation/batch.js +18 -9
- package/dist/extensions/agent-browser/lib/results/presentation/common.js +3 -0
- package/dist/extensions/agent-browser/lib/results/presentation/registry.js +1 -1
- package/dist/extensions/agent-browser/lib/results/presentation.js +7 -3
- package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +14 -2
- package/dist/extensions/agent-browser/lib/results/snapshot.js +12 -5
- package/dist/extensions/agent-browser/lib/runtime.js +3 -1
- package/dist/extensions/agent-browser/lib/session-page-state.js +7 -3
- package/dist/extensions/agent-browser/lib/webmcp-observation.js +28 -0
- package/dist/scripts/agent-browser-target.mjs +1 -1
- package/docs/ARCHITECTURE.md +16 -5
- package/docs/COMMAND_REFERENCE.md +71 -15
- package/docs/ELECTRON.md +1 -1
- package/docs/RELEASE.md +7 -6
- package/docs/SUPPORT_MATRIX.md +15 -9
- package/docs/TOOL_CONTRACT.md +19 -5
- package/docs/platform-smoke.md +3 -3
- package/package.json +1 -1
- package/scripts/agent-browser-capability-baseline.mjs +34 -3
- package/scripts/agent-browser-target.mjs +1 -1
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { isRecord } from "../parsing.js";
|
|
2
2
|
import { getEditableRefEvidence } from "./editable-ref-evidence.js";
|
|
3
3
|
import { compareRefIds, normalizeWhitespace } from "./text.js";
|
|
4
|
+
/** Project native delta full responses onto the ordinary snapshot shape for local readers. */
|
|
5
|
+
export function getFullSnapshotData(data) {
|
|
6
|
+
if (!isRecord(data))
|
|
7
|
+
return undefined;
|
|
8
|
+
if (!isRecord(data.snapshot))
|
|
9
|
+
return data;
|
|
10
|
+
return data.snapshot.kind === "full"
|
|
11
|
+
? { ...data, snapshot: data.snapshot.tree, refs: data.snapshot.refs }
|
|
12
|
+
: undefined;
|
|
13
|
+
}
|
|
4
14
|
export function getSnapshotRefRecord(data) {
|
|
5
|
-
|
|
15
|
+
const full = getFullSnapshotData(data);
|
|
16
|
+
return full && isRecord(full.refs) ? full.refs : undefined;
|
|
6
17
|
}
|
|
7
18
|
export function getSnapshotLineTextByRef(data) {
|
|
8
|
-
const
|
|
19
|
+
const full = getFullSnapshotData(data);
|
|
20
|
+
const snapshot = typeof full?.snapshot === "string" ? full.snapshot : "";
|
|
9
21
|
const lineByRef = new Map();
|
|
10
22
|
for (const line of snapshot.split("\n")) {
|
|
11
23
|
const ref = line.match(/\bref=([^,\]\s]+)/)?.[1];
|
|
@@ -2,7 +2,7 @@ import { isRecord } from "../parsing.js";
|
|
|
2
2
|
import { isHighValueControlEntry, selectHighValueControlEntries } from "./snapshot-high-value-controls.js";
|
|
3
3
|
import { buildFallbackSnapshotOutline, buildRefLineOrderMap, buildSegmentPreview, buildSnapshotSegments, canUseStructuredSnapshotPreview, chooseAdditionalSegments, choosePrimarySegment, getMeaningfulSegmentLines, getSnapshotRolePriority, isChromeSectionName, isNoiseName, parseSnapshotLines, } from "./snapshot-segments.js";
|
|
4
4
|
import { applySnapshotArtifactManifest, writeSnapshotSpillFile } from "./snapshot-spill.js";
|
|
5
|
-
import { enrichSnapshotRefEntries, getSnapshotRefEntries, } from "./snapshot-refs.js";
|
|
5
|
+
import { enrichSnapshotRefEntries, getFullSnapshotData, getSnapshotRefEntries, } from "./snapshot-refs.js";
|
|
6
6
|
import { compareRefIds, countLines, truncateText } from "./text.js";
|
|
7
7
|
const SNAPSHOT_INLINE_MAX_CHARS = 6_000;
|
|
8
8
|
const SNAPSHOT_INLINE_MAX_LINES = 80;
|
|
@@ -15,7 +15,8 @@ const SNAPSHOT_HIGH_VALUE_REF_MAX_LINES = 10;
|
|
|
15
15
|
const SNAPSHOT_ROLE_COUNT_MAX_ENTRIES = 4;
|
|
16
16
|
const SNAPSHOT_NAME_MAX_CHARS = 96;
|
|
17
17
|
function getSnapshotText(data) {
|
|
18
|
-
|
|
18
|
+
const full = getFullSnapshotData(data);
|
|
19
|
+
return typeof full?.snapshot === "string" ? full.snapshot : isRecord(data.snapshot) ? JSON.stringify(data.snapshot) : undefined;
|
|
19
20
|
}
|
|
20
21
|
function getSnapshotOrigin(data) {
|
|
21
22
|
return typeof data.origin === "string" ? data.origin : "(unknown origin)";
|
|
@@ -76,13 +77,17 @@ function shouldCompactSnapshot(rawText, data) {
|
|
|
76
77
|
}
|
|
77
78
|
export function formatSnapshotSummary(data) {
|
|
78
79
|
const origin = typeof data.origin === "string" ? data.origin : "page";
|
|
79
|
-
|
|
80
|
+
if (isRecord(data.snapshot) && data.snapshot.kind !== "full")
|
|
81
|
+
return `Snapshot ${data.snapshot.kind}: revision ${data.snapshot.revision} on ${origin}`;
|
|
82
|
+
const refs = getSnapshotRefEntries(data).length;
|
|
80
83
|
return `Snapshot: ${refs} refs on ${origin}`;
|
|
81
84
|
}
|
|
82
85
|
export function formatRawSnapshotText(data) {
|
|
83
86
|
const origin = getSnapshotOrigin(data);
|
|
84
|
-
const refs =
|
|
87
|
+
const refs = getSnapshotRefEntries(data).length;
|
|
85
88
|
const snapshot = getSnapshotText(data);
|
|
89
|
+
if (isRecord(data.snapshot) && data.snapshot.kind !== "full")
|
|
90
|
+
return `Origin: ${origin}\n${formatSnapshotSummary(data)}\n\n${snapshot}`;
|
|
86
91
|
if (!snapshot) {
|
|
87
92
|
return `Origin: ${origin}\nRefs: ${refs}\n\n(no interactive elements)`;
|
|
88
93
|
}
|
|
@@ -91,7 +96,9 @@ export function formatRawSnapshotText(data) {
|
|
|
91
96
|
export async function buildSnapshotPresentation(data, persistentArtifactStore = undefined, artifactManifest = undefined) {
|
|
92
97
|
const summary = formatSnapshotSummary(data);
|
|
93
98
|
const rawText = formatRawSnapshotText(data);
|
|
94
|
-
|
|
99
|
+
// Native partials are already compact patches, not accessibility trees.
|
|
100
|
+
// The ordinary large-output presenter handles truly oversized patches.
|
|
101
|
+
if ((isRecord(data.snapshot) && data.snapshot.kind !== "full") || !shouldCompactSnapshot(rawText, data)) {
|
|
95
102
|
return {
|
|
96
103
|
content: [{ type: "text", text: rawText }],
|
|
97
104
|
data,
|
|
@@ -17,7 +17,9 @@ const AGENT_BROWSER_IDLE_TIMEOUT_ENV = "AGENT_BROWSER_IDLE_TIMEOUT_MS";
|
|
|
17
17
|
const IMPLICIT_SESSION_IDLE_TIMEOUT_ENV = "PI_AGENT_BROWSER_IMPLICIT_SESSION_IDLE_TIMEOUT_MS";
|
|
18
18
|
const IMPLICIT_SESSION_CLOSE_TIMEOUT_ENV = "PI_AGENT_BROWSER_IMPLICIT_SESSION_CLOSE_TIMEOUT_MS";
|
|
19
19
|
const DEFAULT_IMPLICIT_SESSION_IDLE_TIMEOUT_MS = 15 * 60 * 1000;
|
|
20
|
-
|
|
20
|
+
// Native close includes a five-second Chrome exit grace after protocol shutdown.
|
|
21
|
+
// Use the normal CLI watchdog budget rather than interrupting that grace.
|
|
22
|
+
const DEFAULT_IMPLICIT_SESSION_CLOSE_TIMEOUT_MS = 35_000;
|
|
21
23
|
const INSPECTION_FLAGS = new Set(["--help", "-h", "--version", "-V"]);
|
|
22
24
|
const SENSITIVE_VALUE_FLAGS = new Set(["--body", "--headers", "--password", "--proxy"]);
|
|
23
25
|
const SENSITIVE_QUERY_PARAM_PATTERN = /^(?:access(?:_|-)?token|api(?:_|-)?key|auth|authorization|authorization(?:_|-)?session(?:_|-)?id|bearer|client(?:_|-)?secret|code|cookie|id(?:_|-)?token|key|pass(?:word)?|refresh(?:_|-)?token|relay(?:_|-)?state|saml(?:_|-)?request|saml(?:_|-)?response|secret|sentry(?:_|-)?key|session(?:_|-)?id|sig(?:nature)?|token|write(?:_|-)?key)$/i;
|
|
@@ -5,7 +5,7 @@ import { isCloseAllCommand, isCloseCommand, isReadOnlyDiagnosticSessionTargetCom
|
|
|
5
5
|
import { isRecord } from "./parsing.js";
|
|
6
6
|
import { findReadConfirmation as findPendingReadConfirmation, parseReadConfirmation } from "./read-confirmation.js";
|
|
7
7
|
import { getEditableRefEvidence } from "./results/editable-ref-evidence.js";
|
|
8
|
-
import { enrichSnapshotRefEntries, getSnapshotRefEntries } from "./results/snapshot-refs.js";
|
|
8
|
+
import { enrichSnapshotRefEntries, getFullSnapshotData, getSnapshotRefEntries } from "./results/snapshot-refs.js";
|
|
9
9
|
import { parseSnapshotLines } from "./results/snapshot-segments.js";
|
|
10
10
|
export function normalizeComparableUrl(url) {
|
|
11
11
|
const normalizedUrl = url?.trim();
|
|
@@ -188,8 +188,9 @@ function extractRefSnapshotRefs(data) {
|
|
|
188
188
|
}));
|
|
189
189
|
return Object.keys(refs).length > 0 ? refs : undefined;
|
|
190
190
|
}
|
|
191
|
-
export function extractRefSnapshotFromData(
|
|
192
|
-
|
|
191
|
+
export function extractRefSnapshotFromData(value) {
|
|
192
|
+
const data = getFullSnapshotData(value);
|
|
193
|
+
if (!data)
|
|
193
194
|
return undefined;
|
|
194
195
|
const refs = extractRefSnapshotRefs(data);
|
|
195
196
|
return {
|
|
@@ -260,6 +261,9 @@ export function extractLatestRefSnapshotStateFromBatchResults(data) {
|
|
|
260
261
|
if (snapshot) {
|
|
261
262
|
latestState = { snapshot };
|
|
262
263
|
}
|
|
264
|
+
else if (isRecord(item.result) && isRecord(item.result.snapshot)) {
|
|
265
|
+
latestState = { refreshArgs: commandTokens.filter((token) => token !== "--delta" && token !== "--full") };
|
|
266
|
+
}
|
|
263
267
|
}
|
|
264
268
|
return latestState;
|
|
265
269
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
import { isRecord } from "./parsing.js";
|
|
3
|
+
const observation = new AsyncLocalStorage();
|
|
4
|
+
export function getNativeWebMcpCatalog(data) {
|
|
5
|
+
if (Array.isArray(data)) {
|
|
6
|
+
for (let index = data.length - 1; index >= 0; index -= 1) {
|
|
7
|
+
const catalog = getNativeWebMcpCatalog(isRecord(data[index]) ? data[index].result : undefined);
|
|
8
|
+
if (catalog)
|
|
9
|
+
return catalog;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
if (!isRecord(data) || !isRecord(data.webmcp))
|
|
13
|
+
return undefined;
|
|
14
|
+
return Array.isArray(data.webmcp.tools) || data.webmcp.status === "unavailable" ? data.webmcp : undefined;
|
|
15
|
+
}
|
|
16
|
+
export function observeNativeWebMcp(data) {
|
|
17
|
+
const current = observation.getStore();
|
|
18
|
+
if (!current)
|
|
19
|
+
return;
|
|
20
|
+
const catalog = getNativeWebMcpCatalog(data);
|
|
21
|
+
if (catalog)
|
|
22
|
+
current.catalog = catalog;
|
|
23
|
+
}
|
|
24
|
+
/** Native discovery is edge-triggered; helper reads must not swallow its updates. */
|
|
25
|
+
export async function collectNativeWebMcp(run) {
|
|
26
|
+
const current = {};
|
|
27
|
+
return observation.run(current, async () => ({ result: await run(), catalog: current.catalog }));
|
|
28
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const TARGET_AGENT_BROWSER_SOURCE = "scripts/agent-browser-target.mjs";
|
|
2
|
-
export const TARGET_AGENT_BROWSER_VERSION = "0.
|
|
2
|
+
export const TARGET_AGENT_BROWSER_VERSION = "0.38.1";
|
|
3
3
|
export const TARGET_AGENT_BROWSER_VERSION_LABEL = `agent-browser ${TARGET_AGENT_BROWSER_VERSION}`;
|
|
4
4
|
export const MINIMUM_AGENT_BROWSER_VERSION = "0.35.0";
|
|
5
5
|
export const MINIMUM_AGENT_BROWSER_VERSION_LABEL = `agent-browser ${MINIMUM_AGENT_BROWSER_VERSION}`;
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -141,9 +141,9 @@ The default extension factory optionally accepts `{ beforeExecute }`. `index.ts`
|
|
|
141
141
|
|
|
142
142
|
### Default
|
|
143
143
|
|
|
144
|
-
An explicit native `session` default (user/project JSON or `AGENT_BROWSER_SESSION`) selects a caller-owned browser across Pi sessions. Per-call session/namespace flags win. `lib/orchestration/native-session-defaults.ts` reads
|
|
144
|
+
An explicit native `session` default (user/project JSON or `AGENT_BROWSER_SESSION`) selects a caller-owned browser across Pi sessions. Per-call session/namespace flags win. `lib/orchestration/native-session-defaults.ts` reads session/namespace and contributing launch defaults from native config paths and uses sessionless native `--config <path> --json session` to validate each contributing file and resolve its session. Native config continues to own launch/profile/storage settings; the adapter does not duplicate its schema. Explicit config and per-call idle settings are scoped to helpers through `lib/process-environment.ts`. No startup probe, persistent config cache, or new lifecycle service is added.
|
|
145
145
|
|
|
146
|
-
When no native session
|
|
146
|
+
When no native session, attachment, or explicit fresh launch is selected, `sessionMode: "auto"` uses `pi-root-<sha256(root Pi ID)[0:24]>` through the existing caller-owned named-session path. Descendants receive `PI_SUBAGENT_ROOT_SESSION_ID` from pi-subagents; root processes use `ctx.sessionManager.getSessionId()`. No cwd, human fork ancestry, run registry, or process-global assignment participates. The same name is the default native restore key. Existing native daemon inspection runs inside the existing identity queue: inactive roots receive bootstrap defaults, while active roots retain native launch settings and their current restore key. Scoped subprocess environment keeps helper settings consistent; no launch-settings journal is added. Root-name explicit follow-ups retain those defaults; unrelated explicit names do not. Global/override package `browser.defaultProfile` with `policy: "always"` supplies native Chrome profile names only, plus the configured executable. Paths and project-only profile settings stay advisory. Native config/environment and explicit launch settings win. The communal source is copied by native Chrome launch, never by the wrapper, and each root's restore writes remain separate. Native JSON restore omits IndexedDB, service workers, and page-memory credentials; application-level restart verification is required. Parent and child quit leave the root browser alive; existing per-session queues remain process-local, with no global broker. An active older/fresh managed session keeps its existing lifecycle. A configured session has the same precedence over `fresh` as a literal `--session`; script and Electron launch keep their separate wrapper-owned lifecycles. Electron launch suppresses the native session environment default only while allocating its generated session; ordinary browser follow-ups still honor the configured native default, so use the returned Electron session explicitly.
|
|
147
147
|
|
|
148
148
|
Why:
|
|
149
149
|
- works out of the box
|
|
@@ -158,6 +158,12 @@ An explicit native `session info` call is the preflight: daemon activity/PID is
|
|
|
158
158
|
|
|
159
159
|
`lib/read-confirmation.ts` recognizes only native structured control responses for actual explicit URL reads. Ordered pending/cleared `readConfirmation` markers live in the existing `SessionPageState` and tool-result transcript, including resume/branch replay. They preserve actual session/default routing even for legacy prompts. Only native `capabilities.readRequiresConfirmation: true`, which promises exact ID validation, allows matching confirm/deny to skip page helpers and managed replacement. Explicit caller identities win, DOM/unknown-origin confirmations keep their prior checks, and response content cannot manufacture provenance. There is no separate confirmation store or wrapper authorization system.
|
|
160
160
|
|
|
161
|
+
### Native observation state
|
|
162
|
+
|
|
163
|
+
Native `snapshot --delta` owns its revision baseline. Nested full responses are projected onto the existing tree/ref readers; partial responses stay native in presentation and trigger one ordinary full snapshot read for the existing `SessionPageState` ref guard. This does not advance the native delta baseline or add a second tree/revision cache. Failed ref refreshes invalidate refs. Batch folding selects the last reached snapshot unless a later transition invalidates it; transcript replay persists the resulting complete refs as before. Wrapper-only filters request full trees.
|
|
164
|
+
|
|
165
|
+
Conditional screenshots keep upstream `changed: false` pathless: no destination repair, artifact, or old image attachment. Recording cursor/contact-sheet flags are skipped by the shared path/URL reader; native contact-sheet paths use existing image metadata, verification, and attachment handling, with the companion path on the existing video reservation and transcript entry. Preflight derives only the documented native filename for alias checks; artifact reporting uses the actual native path. `--input-mode` is a value-taking global, not launch-scoped. Native WebMCP catalog updates remain untrusted page data in ordinary presentations. A call-scoped `AsyncLocalStorage` collects the latest native update across helper and main responses: native discovery emits updates once, so preflight reads must not consume them silently. The final tool boundary exposes `details.webMcpCatalog` and any helper-only prose, without mutating native result data or storing a cross-call catalog.
|
|
166
|
+
|
|
161
167
|
### Explicit upstream sessions and fresh launches
|
|
162
168
|
|
|
163
169
|
If the caller provides `--session`, `--profile`, `--cdp`, or similar upstream flags, the extension should respect them with minimal interference.
|
|
@@ -166,8 +172,9 @@ The tool should also expose a first-class `sessionMode: "fresh"` escape hatch so
|
|
|
166
172
|
|
|
167
173
|
### Ownership
|
|
168
174
|
|
|
169
|
-
|
|
170
|
-
-
|
|
175
|
+
Ownership rule:
|
|
176
|
+
- automatic root sessions use native caller-owned lifecycle; group members coordinate and close them explicitly
|
|
177
|
+
- older implicit auto-generated sessions are extension-managed convenience sessions
|
|
171
178
|
- unnamed `sessionMode: "fresh"` launches rotate that extension-managed session to a new upstream browser
|
|
172
179
|
- explicit/user-managed sessions are not auto-managed by default
|
|
173
180
|
- extension-managed sessions should be reusable during an active `pi` session and across `/reload`, exact-session relaunch, `/resume`, and Pi branch-tree transitions, while still being cleaned up predictably
|
|
@@ -181,7 +188,7 @@ Practical policy:
|
|
|
181
188
|
- redact snapshot spill payloads before writing them, clean up process-private temp spill artifacts on shutdown, and keep persisted-session spill files in a private session-scoped artifact directory for `details.fullOutputPath` after reload/resume, with a 32 MiB per-session budget by default; `PI_AGENT_BROWSER_SESSION_ARTIFACT_MAX_BYTES=0` skips persistent-spill enumeration and eviction without changing temporary spill cleanup
|
|
182
189
|
- keep explicit screenshots, downloads, PDFs, traces, HAR captures, and recordings written to caller-chosen paths on disk after a successful upstream close command (`close`, `quit`, or `exit`); before artifact-producing commands run, create missing parent directories for requested host paths, and for simple loopback HTML anchor downloads with resolvable HTTP(S) hrefs the wrapper may save directly to the requested path before upstream fallback. When the bounded `details.artifactManifest` has entries, successful close commands also surface `details.artifactCleanup` and a compact `Artifact lifecycle` note pointing to structured explicit paths so operators remove files with normal host tools—the native tool does not delete arbitrary user paths (`extensions/agent-browser/lib/orchestration/browser-run/diagnostics.ts`, `getArtifactCleanupGuidance`); contract in [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details), checklist `RQ-0079` in [`SUPPORT_MATRIX.md`](SUPPORT_MATRIX.md)
|
|
183
190
|
- reconstruct the current branch-visible extension-managed session, every transcript-proven still-active wrapper-owned managed identity, page-scoped refs, newest-revision aggregate artifact manifest, unbounded active-recording reservation events, and Electron launch records from the active transcript branch on `session_start` and `session_tree` so later default and explicit off-current calls keep following owned browsers after resume/reload or branch switching; restore also honors successful explicit `--session <wrapper-owned> close` rows, terminal nested-batch close outcomes even when aggregate artifact verification failed, and `electron.cleanup` managed-session steps so closed wrapper-owned sessions are not resurrected; a nested close invalidates the pre-close page target so a lifecycle-proven relaunch at `about:blank` is not treated as stale focus drift; explicit lifecycle evidence that a later diagnostic did not launch a browser preserves the terminal close, while any later row—including a failed row—whose lifecycle reports a browser launch keeps active/attached provenance; failed-step presentation persists only that bounded launch boolean so transcript replay reaches the same decision, missing lifecycle evidence remains conservatively active even on the first managed call, successful closes clear wrapper trace/profiler ownership before ordered later successful rows can rebuild it, namespace-scoped `close --all` clears all matching managed/attached/page/ref/route/trace/recording ownership, and recording starts after close are rejected before spawn
|
|
184
|
-
- keep active recording destination reservations separate from the bounded metadata-only artifact manifest. The same journal retains native recording IDs and start windows; native receipts, including failures, flow through existing artifact metadata and verification. A stop timeout/no-recording result gets one two-second native `session info` query matching namespace/session, ID/path or effective batch start window. Recovery needs terminal native encoder success plus a matching verified file; filesystem presence alone is insufficient, old same-path receipts cannot verify a new take, and freshness starts at capture rather than status-query time. Original attempts and unrelated batch failures remain visible. No second ledger, recorder, sidecar or runtime ffprobe is added. The process-wide map is keyed by canonical namespace/session identity, rebuilt from append-only branch events, and retained for still-live process-owned recordings across branch switches. Shutdown/reload appends both terminal tombstones and still-live reservations onto the current branch so restart cannot resurrect a cross-branch close or lose a live-daemon reservation. One artifact lifecycle/output queue makes global destination preflight and reservation updates atomic across otherwise-concurrent caller-owned session queues. Every successful direct, ordered nested-batch, managed replacement, script, Electron, or shutdown close retires its exact identity at that lifecycle point; only the newest pending recording path remains authoritative across current transition replay (including same-timestamp restart rows), and recording starts after a nested close are rejected because upstream can falsely report success. Existing and dangling symlink ancestry, hardlink inode identity, full Unicode/platform case folding, and same-call `outputPath` comparison prevent alias reuse. One shared command-token projection mirrors upstream's full-argv global cleanup before artifact, recording, and presentation parsing; wait-download detection removes only the first timeout pair, follows upstream long/short mode precedence, and accepts both `--download` and `-d` wherever download mode wins; screenshot destinations use upstream's exact-flag, selector-prefix, case-sensitive extension, slash-path, and second-positional rules, while retaining the wrapper's intentional slash-bearing hidden-workspace path normalization. Recording path/URL consumers share a command-local reader that skips complete numeric `--fps` pairs without rewriting argv or treating them as outer globals; native owns rate, format and extra-argument validation. Current recording transitions are replayed directly; artifact manifests are not treated as reservation events
|
|
191
|
+
- keep active recording destination reservations separate from the bounded metadata-only artifact manifest. The same journal retains native recording IDs and start windows; native receipts, including failures, flow through existing artifact metadata and verification. A stop timeout/no-recording result gets one two-second native `session info` query matching namespace/session, ID/path or effective batch start window. Recovery needs terminal native encoder success plus a matching verified file; filesystem presence alone is insufficient, old same-path receipts cannot verify a new take, and freshness starts at capture rather than status-query time. Original attempts and unrelated batch failures remain visible. No second ledger, recorder, sidecar or runtime ffprobe is added. The process-wide map is keyed by canonical namespace/session identity, rebuilt from append-only branch events, and retained for still-live process-owned recordings across branch switches. Shutdown/reload appends both terminal tombstones and still-live reservations onto the current branch so restart cannot resurrect a cross-branch close or lose a live-daemon reservation. One artifact lifecycle/output queue makes global destination preflight and reservation updates atomic across otherwise-concurrent caller-owned session queues. Every successful direct, ordered nested-batch, managed replacement, script, Electron, or shutdown close retires its exact identity at that lifecycle point; only the newest pending recording path remains authoritative across current transition replay (including same-timestamp restart rows), and recording starts after a nested close are rejected because upstream can falsely report success. Existing and dangling symlink ancestry, hardlink inode identity, full Unicode/platform case folding, and same-call `outputPath` comparison prevent alias reuse. One shared command-token projection mirrors upstream's full-argv global cleanup before artifact, recording, and presentation parsing; wait-download detection removes only the first timeout pair, follows upstream long/short mode precedence, and accepts both `--download` and `-d` wherever download mode wins; screenshot destinations use upstream's exact-flag, selector-prefix, case-sensitive extension, slash-path, and second-positional rules, while retaining the wrapper's intentional slash-bearing hidden-workspace path normalization. Recording path/URL consumers share a command-local reader that skips complete numeric `--fps` pairs, cursor/contact-sheet switches, and contact-sheet threshold values without rewriting argv or treating them as outer globals; native owns rate, format and extra-argument validation. Current recording transitions are replayed directly; artifact manifests are not treated as reservation events
|
|
185
192
|
- keep process-owned cleanup registries for extension-managed sessions and wrapper-launched Electron records separate from the current branch-visible view; `session_tree` restore and wrapper-owned browser commands are serialized with managed-session work, while caller-owned explicit-session commands are serialized by process-local queues keyed to effective canonical namespace/session across prepare helpers (explicit namespace argv overrides inherited `AGENT_BROWSER_NAMESPACE`, including an explicit empty default) and main execution. macOS and Windows additionally normalize and case-fold namespace and session components to match case-insensitive daemon identity. Different caller-owned identities remain concurrent, except namespace-scoped `close --all` drains and exclusively barriers managed plus matching caller-owned work before clearing global namespace state; nested helpers never re-enter the outer queue, policy/route/artifact deltas merge across unrelated managed-state commits, and a separate branch-restore generation guard prevents stale completions from overwriting newer branch-visible state; aggregate artifact results use monotonic revisions so transcript replay cannot lose a concurrently completed entry. Branch switches still must not drop resources the current Pi process owns and must keep fresh-session allocation monotonic
|
|
186
193
|
- record successful `connect`, `--cdp`, enabled `--auto-connect`, environment-configured CDP/auto-connect, and wrapper Electron attachment identities in branch-visible state. First-use and later content-bearing calls live-check `get url` because attached targets can drift outside Pi. Caller config, file access, launch arguments, and environment pass through unchanged; only wrapper-injected compatibility launch arguments are omitted on active attachments. A terminal successful close removes the marker; a close followed by a later step whose lifecycle reports a browser launch preserves it, while a non-launching diagnostic such as `stream status` leaves the close terminal
|
|
187
194
|
- when a successful close targets the current extension-managed session, including an explicit `--session <current> close` or an `electron.cleanup` managed-session step, clear page/ref state, mark that session inactive, untrack cleanup ownership, and rotate the next default auto call to a fresh wrapper-generated session name rather than reusing the closed name
|
|
@@ -208,6 +215,10 @@ This is primarily about ownership clarity and avoiding surprise, not adding a he
|
|
|
208
215
|
|
|
209
216
|
### Launch flags
|
|
210
217
|
|
|
218
|
+
`native-session-defaults.ts` reads launch-argument/engine fields through its existing native-validated config discovery. Local Chrome composes `--no-startup-window` with the highest-priority caller arguments. Root bootstrap retains its existing helper scope; owned/fresh preparation reuses daemon-policy inspection, while explicit local callers use the same session-info probe. `process.ts` applies the scoped arguments after managed restore-policy checks, composing the existing compatibility user agent without overriding caller Chrome arguments. Configured environment/file arguments remain consistent across helpers; ordinary active calls do not receive a new launch configuration. This adds no browser launcher, profile mutation, tab cleanup, binary distribution, or persistent launch-settings state. Older custom-argument browsers can undergo native's normal hash-change restart on first use of the new default.
|
|
219
|
+
|
|
220
|
+
Input resolution replaces URL-less `open` with native `get url` before planning, retaining requested argv separately. Effective raw/stdin batch rows use the existing native argument parser and raw-over-stdin precedence; only changed rows are rewritten. Native URL reads provide lazy launch and real lifecycle/URL output without navigating an existing page. Explicit navigation and help/version input are unchanged.
|
|
221
|
+
|
|
211
222
|
`agent-browser` startup flags are sticky once a session is already running.
|
|
212
223
|
The extension should surface that clearly and avoid hidden restart behavior in v1.
|
|
213
224
|
|
|
@@ -22,15 +22,36 @@ SDK hosts can supply an awaited [`beforeExecute` callback](TOOL_CONTRACT.md#host
|
|
|
22
22
|
|
|
23
23
|
<!-- agent-browser-capability-baseline:start upstream-baseline -->
|
|
24
24
|
<!-- Generated from scripts/agent-browser-capability-baseline.mjs. Run `npm run docs -- command-reference write` to update. Do not edit manually. -->
|
|
25
|
-
This reference is baselined to the locally installed `agent-browser 0.
|
|
25
|
+
This reference is baselined to the locally installed `agent-browser 0.38.1` command/help surface, audited against vercel-labs/agent-browser@aff6125c023b810ea3f2e5deec5379e9a4270bdc. Upstream `agent-browser` remains the source of truth for command semantics; this file is the local fallback for Pi agent sessions where direct binary help is blocked or discouraged.
|
|
26
26
|
|
|
27
27
|
The lightweight drift check is `npm run verify -- command-reference`. Run it whenever the installed upstream `agent-browser` version changes or this reference is edited.
|
|
28
28
|
|
|
29
29
|
<!-- agent-browser-capability-baseline:end upstream-baseline -->
|
|
30
30
|
|
|
31
|
+
### Upstream 0.38.1 rebaseline
|
|
32
|
+
|
|
33
|
+
The recommended release keeps the stable 0.35.0 floor. New options require an upstream release that provides them; the wrapper adds no version-specific emulation.
|
|
34
|
+
|
|
35
|
+
- `snapshot --delta` returns a nested `snapshot` object: `kind: full` includes `tree`, `refs`, and `revision`; `unchanged` includes `baseRevision` and `revision`; `delta` also includes ref `changes` and an exact `treeChange` line splice. `snapshot --delta --full` resets the native baseline. The wrapper preserves this payload and shows revisions rather than reporting an empty page. Partial results trigger a full native snapshot read for wrapper ref checks without advancing the delta baseline; there is no wrapper revision cache. Wrapper-only search/filter/viewport/diff options use a full tree instead of native delta output.
|
|
36
|
+
- Surviving DOM elements retain refs across same-document snapshots. Navigation and replaced page/iframe documents invalidate them. Keep refreshing after page changes; persistent refs do not remove page-target checks or same-batch mutation boundaries.
|
|
37
|
+
- `screenshot --if-changed` suppresses unchanged captures. `screenshot --threshold <0-1>` implies it and tolerates that changed-pixel ratio (default 0). Native `changed: false` omits the path: no new file or inline image is reported, even with an explicit destination. Use an ordinary screenshot when every call must save evidence.
|
|
38
|
+
- `--input-mode <mode>` sets sticky session pointer behavior (`instant`, `smooth`, or `human`) and can change on a live session. `click <sel> --human` and `drag <src> <dst> --human` override an action. `mouse move <x> <y> --duration <ms> --steps <n> --human --seed <n>` controls timed, reproducible paths (1–240 movement events); browser response time can extend the requested duration.
|
|
39
|
+
- `record start` / `record restart` accept `--cursor`, `--contact-sheet`, and `--contact-sheet-threshold <n>` (0–1, default 0.05, implies contact sheet). These options are not path/URL operands. Contact sheets use `<video-stem>.contact-sheet.png`, contain timestamped visual changes, and remain pending until stop; reported sheets join `details.artifacts` as images and are attached after verification. The sheet's destination is reserved alongside its video until stop/close, including transcript replay and same-batch/output-path alias checks. After direct restart, the previous take's known sheet is shown with disk evidence but remains unverified because native restart omits its terminal receipt; use stop then start when both completed artifacts must be verified. The 0.38.1 cursor overlay stays synchronized with drags and timed mouse movement. Screenshots during recording include the overlay; snapshots do not.
|
|
40
|
+
- `auth login <name> --no-navigate` uses the prepared top-level login page, checks its origin against the effective credential URL, and permits submit-triggered navigation. Saved and plugin credentials support the same username/password/submit selector overrides; use native auth rather than implementing a second login flow.
|
|
41
|
+
- Native WebMCP discovery emits bounded catalog updates on discovery/change, including names, descriptions, origin, and frame IDs. The wrapper surfaces these as untrusted page data and keeps `data.webmcp`; `details.webMcpCatalog` also preserves updates consumed by helper reads during that call. It never reuses a prior call's catalog. Request full schemas with `webmcp list [tool] [--frame <frame-id>]`; for one relevant tool, use `webmcp list set_message --frame <frame-id>`. Upstream owns CDP recovery, normalized dropdown labels, recording frame pacing, and 0.37.1 Windows headless desktop isolation.
|
|
42
|
+
|
|
43
|
+
Examples through `agent_browser`:
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{ "args": ["snapshot", "-i", "--delta"] }
|
|
47
|
+
{ "args": ["screenshot", "--if-changed", "--threshold", "0.01", "shots/current.png"] }
|
|
48
|
+
{ "args": ["--input-mode", "human", "click", "@e4"] }
|
|
49
|
+
{ "args": ["record", "start", "demo.webm", "--cursor", "--contact-sheet"] }
|
|
50
|
+
```
|
|
51
|
+
|
|
31
52
|
### Upstream 0.37.0 rebaseline
|
|
32
53
|
|
|
33
|
-
|
|
54
|
+
This release keeps the stable 0.35.0 floor and no upper version cap.
|
|
34
55
|
|
|
35
56
|
- `record start` / `record restart` accept command-local `--fps <n>` before, between or after path/URL operands (1–60, default 30). WebM uses VP8/libvpx; MP4 uses H.264/libx264. Other extensions are handed to ffmpeg; extensionless paths are rejected. Native startup validates the path, rate and ffmpeg availability.
|
|
36
57
|
- Recording uses the current active page without replacing its DOM/JavaScript state unless a URL is supplied. The wrapper still conservatively requires a fresh snapshot after dispatched starts and URL-bearing restarts to protect older supported natives; this is not evidence that a page changed. FPS alone neither chooses another tab nor makes a restart invalidate refs.
|
|
@@ -218,6 +239,7 @@ Tool parameters (use exactly one of `script`, `args`, `semanticAction`, `job`, `
|
|
|
218
239
|
- `outputPath`: optional wrapper-owned local file sink for successful results and recording receipts, including failed, pending, timed-out or recovered stops. Recording exports preserve an envelope with original attempt status and native receipt/verification (`details.outputFile.source: "recording-receipt"`); unrelated failed extractions remain unwritten. Use it for durable `eval`, `get`, `snapshot`, or diagnostic outputs, not as the destination for screenshots, downloads, recordings, or other browser artifacts; if the paths resolve to the same file, the browser artifact is preserved and the result-data write fails validation. If presentation compacted a large direct result, a result row, or the whole `batch`, the writer copies each full command-redacted pre-compaction value only from its matching live wrapper-manifest spill; if any required spill is unavailable or untrusted, it fails without writing compact metadata. `details.outputFile` reports the saved path and byte count. If caller argv includes upstream `--json`, the visible JSON content stays parseable and the save notice is only in `details.outputFile`.
|
|
219
240
|
- `timeoutMs`: optional per-call wrapper subprocess watchdog override in milliseconds for the requested browser CLI process. Managed-session policy inspection can independently consume up to 35 seconds before that process; this preflight is intentionally not shortened by `timeoutMs` because a busy but valid daemon must remain distinguishable from an unverifiable one.
|
|
220
241
|
- `sessionMode`:
|
|
242
|
+
- Unconfigured ordinary calls select a root-Pi named browser with native restore; descendants share it, unrelated roots do not wait on each other, and Pi quit leaves it running. Existing managed sessions and explicit fresh launches retain their lifecycle.
|
|
221
243
|
- Native configured `session` / `AGENT_BROWSER_SESSION` defaults select a caller-owned shared browser for ordinary calls, just like explicit `--session`, without requiring repeated flags. Such a selection wins over both modes and is not closed on Pi quit. See [shared browser defaults](../README.md#shared-browser-defaults).
|
|
222
244
|
- `"auto"` reuses the extension-managed session when no native session is selected.
|
|
223
245
|
- `"fresh"` rotates that managed session to a fresh upstream launch so launch-scoped flags (`--allowed-domains`, `--auto-connect`, `--args`, `--ca-cert`, `--no-ca-cert`, `--cdp`, `--enable`, `--executable-path`, `--webgpu`, `--init-script`, `--idle-timeout`, `--user-agent`, `--headed`, `--device`, `--namespace`, `--profile`, `--provider`, `-p`, `--restore`, `--restore-save`, `--restore-check-url`, `--restore-check-text`, `--restore-check-fn`, `--session-name`, `--state`) apply.
|
|
@@ -475,7 +497,7 @@ Typical lifecycle:
|
|
|
475
497
|
{ "electron": { "action": "cleanup", "launchId": "electron-…" } }
|
|
476
498
|
```
|
|
477
499
|
|
|
478
|
-
`electron.status` and `electron.cleanup` take either `launchId`, **`all: true`** (literal boolean) to walk every active wrapper-tracked launch (including dead, failed, or partial records, but excluding cleaned records), or neither when exactly one active launch exists—never both `launchId` and `all`. They can target the current branch-visible launch plus still-owned off-branch launch records by `launchId`; default no-arg calls are intentionally ambiguous when more than one active launch is owned. `/reload` preserves the current branch-visible active Electron launch and its isolated temp `userDataDir` for continuity, and cleans off-branch owned Electron launches. First reuse after reload/resume checks the live app's saved debug endpoint and the exact named upstream connection with `get cdp-url`, without reconnecting or resetting page refs; if cleanup is partial and skips or fails profile removal, the generic temp sweep preserves that `userDataDir` across reload, quit, later temp cleanup, process exit, and stale temp-root pruning after restart. `electron.list` has no configurable timeout and rejects both top-level and nested `timeoutMs`. For `electron.launch`, nested `timeoutMs` sets host CDP readiness polling to a **15s** default and **120s** cap after target discovery; upstream attach and handoff use separate subprocess budgets. Optional `timeoutMs` on **`status`** applies to each managed-session `get url` / `get title` read and any `get cdp-url` read needed to verify a restored connection (localhost CDP probes stay on a short fixed fetch budget). On **`cleanup`**, it is applied separately to upstream `close` and the initial host process-exit wait, not to the entire teardown; debug-port checks have fixed fetch budgets and profile removal has no configurable deadline; when omitted it follows the implicit session close default (**
|
|
500
|
+
`electron.status` and `electron.cleanup` take either `launchId`, **`all: true`** (literal boolean) to walk every active wrapper-tracked launch (including dead, failed, or partial records, but excluding cleaned records), or neither when exactly one active launch exists—never both `launchId` and `all`. They can target the current branch-visible launch plus still-owned off-branch launch records by `launchId`; default no-arg calls are intentionally ambiguous when more than one active launch is owned. `/reload` preserves the current branch-visible active Electron launch and its isolated temp `userDataDir` for continuity, and cleans off-branch owned Electron launches. First reuse after reload/resume checks the live app's saved debug endpoint and the exact named upstream connection with `get cdp-url`, without reconnecting or resetting page refs; if cleanup is partial and skips or fails profile removal, the generic temp sweep preserves that `userDataDir` across reload, quit, later temp cleanup, process exit, and stale temp-root pruning after restart. `electron.list` has no configurable timeout and rejects both top-level and nested `timeoutMs`. For `electron.launch`, nested `timeoutMs` sets host CDP readiness polling to a **15s** default and **120s** cap after target discovery; upstream attach and handoff use separate subprocess budgets. Optional `timeoutMs` on **`status`** applies to each managed-session `get url` / `get title` read and any `get cdp-url` read needed to verify a restored connection (localhost CDP probes stay on a short fixed fetch budget). On **`cleanup`**, it is applied separately to upstream `close` and the initial host process-exit wait, not to the entire teardown; debug-port checks have fixed fetch budgets and profile removal has no configurable deadline; when omitted it follows the implicit session close default (**35s** unless `PI_AGENT_BROWSER_IMPLICIT_SESSION_CLOSE_TIMEOUT_MS` overrides). A successful managed-session close step retires that wrapper-managed session even when host process/profile cleanup remains partial. On **`probe`**, it bounds each underlying upstream read subprocess—omit it to use the normal tool subprocess default, or raise it on slow desktops.
|
|
479
501
|
|
|
480
502
|
Explicit-ID `electron.status` labels a cleaned record as historical while measuring PID/port liveness independently. `details.electron.statuses[].userDataDirState` freshly reports the tracked profile path as `present`, `absent` (only ENOENT), or `unknown` (other native `lstat` errors); dangling symlinks are present. This is not an audit of all app residue and does not change stored launch records or cleanup ownership.
|
|
481
503
|
|
|
@@ -721,7 +743,7 @@ Skill-source debugging note: upstream honors `AGENT_BROWSER_SKILLS_DIR` as an ov
|
|
|
721
743
|
| `screenshot [selector] [path]` | Take a full-page or element-scoped screenshot; a single selector-like argument scopes, while a path-like argument saves to that path. |
|
|
722
744
|
| `screenshot [path]` | Take a screenshot and optionally save it to a path. |
|
|
723
745
|
| `pdf <path>` | Save the page as a PDF. |
|
|
724
|
-
| `snapshot` | Print an accessibility tree with refs for AI interaction. Common options include `snapshot --interactive`, `snapshot --urls`, `snapshot --compact`, `snapshot --depth <n>`, `snapshot --selector <sel>`, and `snapshot --
|
|
746
|
+
| `snapshot` | Print an accessibility tree with refs for AI interaction. Common options include `snapshot --interactive`, `snapshot --urls`, `snapshot --compact`, `snapshot --depth <n>`, `snapshot --selector <sel>`, and native `snapshot --delta` / `snapshot --delta --full`. Cursor-interactive elements are included by default; `snapshot --cursor` / `snapshot -C` are deprecated no-ops. |
|
|
725
747
|
| `eval <js>` | Run JavaScript. Use `eval --stdin` through this wrapper for larger snippets, or `eval -b <base64>` for shell-escaping-safe one-liners. |
|
|
726
748
|
| `connect <port|url>` | Connect to a browser through CDP. |
|
|
727
749
|
| `close [--all]` | Close the current browser or all sessions; `quit` and `exit` are upstream close aliases. |
|
|
@@ -834,10 +856,11 @@ With `--pin-tab`, a closed bound tab fails as `tab_gone` (`data.targetId`, optio
|
|
|
834
856
|
| `snapshot -i` / `snapshot --interactive` | Include only interactive elements. |
|
|
835
857
|
| `snapshot -i --urls` | Include only interactive elements and link hrefs. |
|
|
836
858
|
| `snapshot -u` / `snapshot --urls` | Include href URLs for link elements. |
|
|
837
|
-
| `snapshot -C` / `snapshot --cursor` |
|
|
859
|
+
| `snapshot -C` / `snapshot --cursor` | Deprecated no-ops; cursor-interactive elements are included by default. |
|
|
838
860
|
| `snapshot -c` / `snapshot --compact` | Remove empty structural elements. |
|
|
839
861
|
| `snapshot -d <n>` / `snapshot --depth <n>` | Limit tree depth. |
|
|
840
862
|
| `snapshot -s <sel>` / `snapshot --selector <sel>` | Scope to a CSS selector. |
|
|
863
|
+
| `snapshot --delta` / `snapshot --delta --full` | Native revision-relative observation or a forced full baseline; see [0.38.1](#upstream-0381-rebaseline). |
|
|
841
864
|
|
|
842
865
|
When a snapshot is too large for inline output, the Pi wrapper renders a compact view before spilling the full redacted snapshot to `details.fullOutputPath`. Compact snapshots are main-content-first, but dense pages and desktop host screens can still hide actionable controls in omitted content; scan `Omitted high-value controls` before opening the spill file. That bounded section favors editable/searchbox/textbox/combobox controls, named tab/surface controls, primary action buttons, and named action links such as row/navigation links and repository-style result links, then includes other useful controls such as checkboxes, radios, options, and menuitems that were not already listed under key refs or other refs. When that section appears, `details.data.highValueControlRefIds` repeats the same visible ref ids for programmatic follow-up alongside fields such as `previewMode`, `previewSections`, and counts on `details.data` (see [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details)).
|
|
843
866
|
|
|
@@ -902,7 +925,7 @@ Long-running or lifecycle commands should be explicitly paired with cleanup call
|
|
|
902
925
|
| --- | --- |
|
|
903
926
|
| `batch [--bail] ["cmd" ...]` | Execute multiple commands sequentially from args or stdin. |
|
|
904
927
|
| `auth save <name> [opts]` | Save an auth profile. Full credential form: `auth save <name> --url <url> --username <user> --password <pass>`; selector override form: `auth save <name> --username-selector <s> --password-selector <s> --submit-selector <s>`. Prefer `auth save <name> --password-stdin` with the tool `stdin` field; avoid putting passwords in `args`. |
|
|
905
|
-
| `auth login <name>` | Login using saved credentials. |
|
|
928
|
+
| `auth login <name>` | Login using saved credentials; add `--no-navigate` for a prepared, same-origin login page. |
|
|
906
929
|
| `auth list` | List saved auth profiles. |
|
|
907
930
|
| `auth show <name>` | Show auth profile metadata. |
|
|
908
931
|
| `auth delete <name>` | Delete an auth profile; `auth remove <name>` is the upstream alias. |
|
|
@@ -1015,7 +1038,7 @@ Example config:
|
|
|
1015
1038
|
}
|
|
1016
1039
|
```
|
|
1017
1040
|
|
|
1018
|
-
Browser
|
|
1041
|
+
Browser defaults are scoped: global/override `defaultProfile` with `policy: "always"` and a Chrome profile name (not a path), plus `executablePath`, become native subprocess defaults only for automatic root browsers and their helpers. Roots have distinct named sessions and restore keys; parents and descendants share one root through `PI_SUBAGENT_ROOT_SESSION_ID`. These defaults never apply to unrelated explicit sessions, script, or Electron launches. Profile paths, other policies, and project-only guidance remain advisory. Native restore keeps cookies/localStorage/sessionStorage, not new IndexedDB, service workers, or memory-only grants; verify app access after a real restart. Avoid global native profile changes or a shared writable profile path; see [shared browser defaults](../README.md#shared-browser-defaults). Configure profile/executable guidance globally, in trusted project config, or through `PI_AGENT_BROWSER_CONFIG`. Ask the agent to run `profiles` and `doctor` when profile resolution fails, then use the reported Chrome profile directory name, a full profile/user-data directory path if upstream accepts one, or the configured `browser.executablePath` with top-level `sessionMode: "fresh"`.
|
|
1019
1042
|
|
|
1020
1043
|
## Important global flags, config, and environment
|
|
1021
1044
|
|
|
@@ -1039,6 +1062,8 @@ Browser default config is conservative: it adds agent guidance for signed-in/acc
|
|
|
1039
1062
|
|
|
1040
1063
|
### Browser launch and runtime flags
|
|
1041
1064
|
|
|
1065
|
+
The extension composes stock `--args --no-startup-window` for local Chrome startup without changing the headless default or external browser engines/attachments. Caller arguments retain native precedence. Plain active follow-ups do not repeat bootstrap settings; older custom-argument sessions can restart once when the new argument changes native launch identity. URL-less `open` runs native `get url` to lazily launch or preserve the active page, including batch/script calls; the result exposes the actual command and URL, not a fabricated launch receipt. See [the startup contract](TOOL_CONTRACT.md#headed-and-local-fixture-limits).
|
|
1066
|
+
|
|
1042
1067
|
- `--executable-path <path>`: custom Chromium-compatible browser executable, such as Brave/Edge/Arc/Vivaldi when upstream can launch that binary. Environment: `AGENT_BROWSER_EXECUTABLE_PATH`.
|
|
1043
1068
|
- `--extension <path>`: load browser extensions; repeatable. Environment: `AGENT_BROWSER_EXTENSIONS`.
|
|
1044
1069
|
- `--args <args>`: browser launch args, comma or newline separated. Chromium switches belong in this value, for example `{ "args": ["--args", "--no-sandbox", "open", "https://example.com"], "sessionMode": "fresh" }`. A bare `--no-sandbox` is diagnosed when it occupies the command slot (unknown command) or an `open` / `goto` / `navigate` option position (ignored by upstream); literal operands in other commands are left alone. For batches, put `--args` before `batch` in top-level `args`, not inside a row. Environment: `AGENT_BROWSER_ARGS`.
|
|
@@ -1124,14 +1149,14 @@ Other useful environment variables include `AGENT_BROWSER_DEFAULT_TIMEOUT`, `AGE
|
|
|
1124
1149
|
<!-- agent-browser-capability-baseline:start capability-token-baseline -->
|
|
1125
1150
|
<!-- Generated from scripts/agent-browser-capability-baseline.mjs. Run `npm run docs -- command-reference write` to update. Do not edit manually. -->
|
|
1126
1151
|
<details>
|
|
1127
|
-
<summary>Generated verifier capability baseline for agent-browser 0.
|
|
1152
|
+
<summary>Generated verifier capability baseline for agent-browser 0.38.1</summary>
|
|
1128
1153
|
|
|
1129
1154
|
This generated block is review data for maintainers. The human-authored reference sections above remain the readable command guide.
|
|
1130
1155
|
|
|
1131
1156
|
#### Source evidence
|
|
1132
1157
|
- repository: `vercel-labs/agent-browser`
|
|
1133
|
-
- upstream HEAD: `
|
|
1134
|
-
- upstream package version: `0.
|
|
1158
|
+
- upstream HEAD: `aff6125c023b810ea3f2e5deec5379e9a4270bdc`
|
|
1159
|
+
- upstream package version: `0.38.1`
|
|
1135
1160
|
- inspected: `agent-browser --version`
|
|
1136
1161
|
- inspected: `agent-browser --help`
|
|
1137
1162
|
- inspected: `selected agent-browser <command> --help output`
|
|
@@ -1160,6 +1185,9 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1160
1185
|
- inspected: `cli/src/native/daemon.rs`
|
|
1161
1186
|
- inspected: `cli/src/native/element.rs`
|
|
1162
1187
|
- inspected: `cli/src/native/recording.rs`
|
|
1188
|
+
- inspected: `cli/src/native/snapshot.rs`
|
|
1189
|
+
- inspected: `cli/src/native/interaction.rs`
|
|
1190
|
+
- inspected: `cli/src/native/screenshot.rs`
|
|
1163
1191
|
- inspected: `cli/src/native/stream/cdp_loop.rs`
|
|
1164
1192
|
- inspected: `cli/src/native/stream/dashboard.rs`
|
|
1165
1193
|
- inspected: `cli/src/native/test_fixtures/webmcp_frame_probe.html`
|
|
@@ -1206,6 +1234,7 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1206
1234
|
- get help: `agent-browser get --help`
|
|
1207
1235
|
- is help: `agent-browser is --help`
|
|
1208
1236
|
- mouse help: `agent-browser mouse --help`
|
|
1237
|
+
- drag help: `agent-browser drag --help`
|
|
1209
1238
|
- set help: `agent-browser set --help`
|
|
1210
1239
|
- tab help: `agent-browser tab --help`
|
|
1211
1240
|
- snapshot help: `agent-browser snapshot --help`
|
|
@@ -1249,11 +1278,11 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1249
1278
|
|
|
1250
1279
|
#### Inventory sections
|
|
1251
1280
|
- Built-in skills: 19 human-doc token(s), 24 upstream token(s)
|
|
1252
|
-
- Core page, element, navigation, and extraction commands:
|
|
1281
|
+
- Core page, element, navigation, and extraction commands: 89 human-doc token(s), 94 upstream token(s)
|
|
1253
1282
|
- Sessions, state, tabs, frames, dialogs, and windows: 28 human-doc token(s), 26 upstream token(s)
|
|
1254
|
-
- Network, storage, artifacts, diagnostics, and performance:
|
|
1255
|
-
- Batch, auth, confirmations, setup, dashboard, devices, and AI commands:
|
|
1256
|
-
- Global flags, config, providers, policy, and environment:
|
|
1283
|
+
- Network, storage, artifacts, diagnostics, and performance: 62 human-doc token(s), 71 upstream token(s)
|
|
1284
|
+
- Batch, auth, confirmations, setup, dashboard, devices, and AI commands: 37 human-doc token(s), 41 upstream token(s)
|
|
1285
|
+
- Global flags, config, providers, policy, and environment: 153 human-doc token(s), 120 upstream token(s)
|
|
1257
1286
|
|
|
1258
1287
|
#### Human-authored doc tokens required
|
|
1259
1288
|
##### Built-in skills
|
|
@@ -1324,6 +1353,13 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1324
1353
|
- `screenshot [path]`
|
|
1325
1354
|
- `screenshot --full`
|
|
1326
1355
|
- `screenshot --annotate`
|
|
1356
|
+
- `screenshot --if-changed`
|
|
1357
|
+
- `screenshot --threshold <0-1>`
|
|
1358
|
+
- `snapshot --delta`
|
|
1359
|
+
- `snapshot --delta --full`
|
|
1360
|
+
- `click <sel> --human`
|
|
1361
|
+
- `drag <src> <dst> --human`
|
|
1362
|
+
- `mouse move <x> <y> --duration <ms> --steps <n> --human --seed <n>`
|
|
1327
1363
|
- `pdf <path>`
|
|
1328
1364
|
- `snapshot`
|
|
1329
1365
|
- `snapshot --cursor`
|
|
@@ -1407,6 +1443,7 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1407
1443
|
- `cookies set --curl <file>`
|
|
1408
1444
|
- `storage <local|session>`
|
|
1409
1445
|
- `webmcp list`
|
|
1446
|
+
- `webmcp list [tool] [--frame <frame-id>]`
|
|
1410
1447
|
- `webmcp invoke <tool>`
|
|
1411
1448
|
- `webmcp invoke <tool> --params <json|@file>`
|
|
1412
1449
|
- `webmcp invoke <tool> --frame <frame-id>`
|
|
@@ -1426,6 +1463,9 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1426
1463
|
- `record start <path> [url]`
|
|
1427
1464
|
- `record restart <path> [url]`
|
|
1428
1465
|
- `--fps <n>`
|
|
1466
|
+
- `--cursor`
|
|
1467
|
+
- `--contact-sheet`
|
|
1468
|
+
- `--contact-sheet-threshold <n>`
|
|
1429
1469
|
- `record stop`
|
|
1430
1470
|
- `console [--clear]`
|
|
1431
1471
|
- `errors [--clear]`
|
|
@@ -1458,6 +1498,7 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1458
1498
|
- `auth save <name> --username-selector <s> --password-selector <s> --submit-selector <s>`
|
|
1459
1499
|
- `auth save <name> --password-stdin`
|
|
1460
1500
|
- `auth login <name>`
|
|
1501
|
+
- `auth login <name> --no-navigate`
|
|
1461
1502
|
- `auth list`
|
|
1462
1503
|
- `auth show <name>`
|
|
1463
1504
|
- `auth delete <name>`
|
|
@@ -1561,6 +1602,7 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1561
1602
|
- `AGENT_BROWSER_DOWNLOAD_PATH`
|
|
1562
1603
|
- `--engine <name>`
|
|
1563
1604
|
- `AGENT_BROWSER_ENGINE`
|
|
1605
|
+
- `--input-mode <mode>`
|
|
1564
1606
|
- `--no-auto-dialog`
|
|
1565
1607
|
- `AGENT_BROWSER_NO_AUTO_DIALOG`
|
|
1566
1608
|
- `--json`
|
|
@@ -1752,6 +1794,15 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1752
1794
|
- keyboard help: `inserttext <text>`
|
|
1753
1795
|
- screenshot help: `--full, -f`
|
|
1754
1796
|
- screenshot help: `--annotate`
|
|
1797
|
+
- screenshot help: `--if-changed`
|
|
1798
|
+
- screenshot help: `--threshold <0-1>`
|
|
1799
|
+
- snapshot help: `--delta`
|
|
1800
|
+
- snapshot help: `--full`
|
|
1801
|
+
- click help: `--human`
|
|
1802
|
+
- drag help: `--human`
|
|
1803
|
+
- mouse help: `--duration <ms>`
|
|
1804
|
+
- mouse help: `--steps <n>`
|
|
1805
|
+
- mouse help: `--seed <n>`
|
|
1755
1806
|
- find help: `role <role>`
|
|
1756
1807
|
- find help: `testid <id>`
|
|
1757
1808
|
- tap help: `tap <selector>`
|
|
@@ -1796,7 +1847,7 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1796
1847
|
- root help: `cookies [get|set|clear]`
|
|
1797
1848
|
- root help: `cookies set --curl <file>`
|
|
1798
1849
|
- root help: `storage <local|session>`
|
|
1799
|
-
- root help: `webmcp list`
|
|
1850
|
+
- root help: `webmcp list [tool]`
|
|
1800
1851
|
- root help: `webmcp invoke <tool>`
|
|
1801
1852
|
- root help: `--params <json|@file>`
|
|
1802
1853
|
- root help: `--frame <frame-id>`
|
|
@@ -1852,6 +1903,9 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1852
1903
|
- profiler help: `--categories <list>`
|
|
1853
1904
|
- record help: `record restart <path.webm|path.mp4> [url] [--fps <n>]`
|
|
1854
1905
|
- record help: `--fps <n>`
|
|
1906
|
+
- record help: `--cursor`
|
|
1907
|
+
- record help: `--contact-sheet`
|
|
1908
|
+
- record help: `--contact-sheet-threshold <n>`
|
|
1855
1909
|
- console help: `--clear`
|
|
1856
1910
|
- errors help: `--clear`
|
|
1857
1911
|
|
|
@@ -1892,6 +1946,7 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1892
1946
|
- root help: `plugin show <name>`
|
|
1893
1947
|
- root help: `plugin run <name> <type>`
|
|
1894
1948
|
- auth help: `--credential-provider <p>`
|
|
1949
|
+
- auth help: `--no-navigate`
|
|
1895
1950
|
- mcp help: `agent_browser_open`
|
|
1896
1951
|
- mcp help: `--tools`
|
|
1897
1952
|
- plugin help: `Add a plugin from npm or GitHub`
|
|
@@ -1965,6 +2020,7 @@ This generated block is review data for maintainers. The human-authored referenc
|
|
|
1965
2020
|
- root help: `AGENT_BROWSER_DOWNLOAD_PATH`
|
|
1966
2021
|
- root help: `--engine <name>`
|
|
1967
2022
|
- root help: `AGENT_BROWSER_ENGINE`
|
|
2023
|
+
- root help: `--input-mode <mode>`
|
|
1968
2024
|
- root help: `--no-auto-dialog`
|
|
1969
2025
|
- root help: `AGENT_BROWSER_NO_AUTO_DIALOG`
|
|
1970
2026
|
- root help: `--json`
|
package/docs/ELECTRON.md
CHANGED
|
@@ -210,7 +210,7 @@ On Pi `quit`, active wrapper-owned Electron launches are best-effort cleaned. On
|
|
|
210
210
|
| --- | --- | --- |
|
|
211
211
|
| `launch` | Host-side wait for `DevToolsActivePort` and CDP readiness | **15 s**, hard-capped at **120 s** (`normalizeTimeoutMs` in `extensions/agent-browser/lib/electron/launch.ts`) |
|
|
212
212
|
| `status` | Each optional managed-session `get url` / `get title` subprocess, including `get cdp-url` when verifying a restored connection | Normal wrapper subprocess budget (**35 s**, or `PI_AGENT_BROWSER_PROCESS_TIMEOUT_MS`); localhost CDP probes use **1000 ms** each (`ELECTRON_CDP_FETCH_TIMEOUT_MS` in `extensions/agent-browser/lib/electron/cdp.ts`) |
|
|
213
|
-
| `cleanup` | Applied separately to managed-session `close` and the initial tracked-process exit wait; not a deadline for debug-port checks or profile removal | `PI_AGENT_BROWSER_IMPLICIT_SESSION_CLOSE_TIMEOUT_MS` when set, else **
|
|
213
|
+
| `cleanup` | Applied separately to managed-session `close` and the initial tracked-process exit wait; not a deadline for debug-port checks or profile removal | `PI_AGENT_BROWSER_IMPLICIT_SESSION_CLOSE_TIMEOUT_MS` when set, else **35000 ms** (`getImplicitSessionCloseTimeoutMs` in `extensions/agent-browser/lib/runtime.ts`, passed through `cleanupTrackedElectronHostLaunches` in `extensions/agent-browser/lib/orchestration/electron-host/index.ts`) |
|
|
214
214
|
| `probe` | **Each** upstream read: optional `get cdp-url` verification, then `get url`, `get title`, focused `eval --stdin`, `tab list`, and `snapshot -i` | Same wrapper subprocess default (**35 s**, or `PI_AGENT_BROWSER_PROCESS_TIMEOUT_MS`, from `getAgentBrowserProcessTimeoutMs` in `extensions/agent-browser/lib/process.ts`) |
|
|
215
215
|
|
|
216
216
|
## `qa.attached` — current-session smoke check
|
package/docs/RELEASE.md
CHANGED
|
@@ -47,7 +47,7 @@ npm run verify -- pre-pr
|
|
|
47
47
|
3. `npm run verify -- package-pi`, which first validates package contents via `npm pack --json --dry-run` and then smoke-loads the packed package in Pi isolation
|
|
48
48
|
4. `npm run smoke:platform:doctor` and the full Crabbox matrix from [`platform-smoke.md`](platform-smoke.md): macOS SSH, Ubuntu local-container, and native Windows Parallels targets running fast target-local `platform-build` plus `browser-dogfood-smoke`
|
|
49
49
|
|
|
50
|
-
The 0.6.
|
|
50
|
+
The 0.6.14 release uses the documented [local macOS and hosted native-Windows alternatives](platform-smoke.md#alternate-native-transports) instead of SSH and Parallels. Run and inspect those target-local suites separately alongside the remaining release checks. The default composed gate is unchanged; alternate evidence must not be labeled a passing Crabbox matrix.
|
|
51
51
|
|
|
52
52
|
`npm publish` runs npm’s `prepublishOnly` script from `package.json`, which executes the same `npm run verify -- release` gate and then `npm pack --dry-run`. That concatenated gate is everything in the default `npm run verify` step (generated playbook drift, clean `dist/` build, TypeScript, the unit/fake suite, generated command-reference blocks, and live upstream command-reference sampling against the targeted `agent-browser` on `PATH`), the configured-source lifecycle harness, the packaged Pi smoke in `package-pi`, and the release-blocking Crabbox platform matrix. Using `npm publish --ignore-scripts` skips that contract intentionally.
|
|
53
53
|
|
|
@@ -221,7 +221,7 @@ Run the automated harness for deterministic configured-source lifecycle regressi
|
|
|
221
221
|
npm run verify -- lifecycle
|
|
222
222
|
```
|
|
223
223
|
|
|
224
|
-
The harness creates an isolated `PI_CODING_AGENT_DIR`, writes settings with exactly one temporary configured package source, runs `pi` in `tmux` with `--approve`, default model **`zai/glm-5.2`**, and a deterministic `--session-id`, puts a deterministic fake `agent-browser` first on `PATH`, drives `/reload`, closes Pi, and relaunches with the same exact session id instead of typing `/resume`. It also asserts the JSONL session header id, same-page managed-session continuity, compiled JS code pickup after full process relaunch, persisted spill reachability, and real Pi `tool_result` failure-patch semantics for a QA reclassification. Per-step tmux waits default to **180000 ms** (three minutes) in [`scripts/verify-lifecycle.mjs`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/scripts/verify-lifecycle.mjs) (`DEFAULT_TIMEOUT_MS`); override with `--timeout-ms <ms>` when slower models or cold starts need more headroom. Override the model when needed:
|
|
224
|
+
The harness creates an isolated `PI_CODING_AGENT_DIR`, writes settings with exactly one temporary configured package source, runs `pi` in `tmux` with `--approve`, default model **`zai/glm-5.2`**, and a deterministic `--session-id`, puts a deterministic fake `agent-browser` first on `PATH`, starts an explicit `sessionMode: "fresh"` managed browser, drives `/reload`, closes Pi, and relaunches with the same exact session id instead of typing `/resume`. It also asserts the JSONL session header id, same-page managed-session continuity, compiled JS code pickup after full process relaunch, persisted spill reachability, and real Pi `tool_result` failure-patch semantics for a QA reclassification. Per-step tmux waits default to **180000 ms** (three minutes) in [`scripts/verify-lifecycle.mjs`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/scripts/verify-lifecycle.mjs) (`DEFAULT_TIMEOUT_MS`); override with `--timeout-ms <ms>` when slower models or cold starts need more headroom. Override the model when needed:
|
|
225
225
|
|
|
226
226
|
```bash
|
|
227
227
|
npm run verify -- lifecycle --model openai-codex/gpt-5.5:minimal
|
|
@@ -269,13 +269,14 @@ That npm script sets `PI_AGENT_BROWSER_REAL_UPSTREAM=1` for the test process. To
|
|
|
269
269
|
|
|
270
270
|
This suite requires the installed stable `agent-browser --version` to meet the minimum in `scripts/agent-browser-target.mjs`; the output-shape fixture and command-reference verifier remain aligned to the current recommended baseline. It serves fixture pages from localhost and checks stable `details`/`data` keys via `test/fixtures/agent-browser-real-output-shapes.json`. Coverage groups:
|
|
271
271
|
|
|
272
|
-
- **Inspection and skills (stateless JSON):** `--version`, `--help`, `snapshot --help`, `skills list`, `skills get … --full` (including `webmcp-gen` on the 0.
|
|
273
|
-
- **
|
|
272
|
+
- **Inspection and skills (stateless JSON):** `--version`, `--help`, `snapshot --help`, `skills list`, `skills get … --full` (including `webmcp-gen` on the 0.38.1 target), `skills path …` (no managed `sessionName` / `usedImplicitSession`).
|
|
273
|
+
- **Native 0.38 observation/recording:** full/unchanged delta snapshots, persistent refs, partial batch ref follow-ups, conditional screenshot suppression, sticky pointer mode and timed mouse movement, cursor recording and verified contact-sheet output. These options are skipped when explicitly validating the older stable floor.
|
|
274
|
+
- **WebMCP target contract:** on the 0.38.1 target, `webmcp list`, `invoke` with params/frame selection, detached `result` / `cancel`, ref invalidation after page tools, and a separate fresh launch with `--no-webmcp` returning an empty list.
|
|
274
275
|
- **Navigation metadata and native tab setup:** plain pages stay quiet; a page with tools retains positive native `data.webmcp` and shows the `webmcp list` hint. New tabs inherit configured headers before their first request, and clearing headers removes them on the next tab. No wrapper inheritance code is involved.
|
|
275
276
|
- **Recording FPS paths and pinning:** the opt-in `test/agent-browser.batch-fidelity.test.ts` native case checks direct/raw/stdin preflight before dispatch, actual start/restart destinations and pinned targets with leading `--fps`, conservative start-ref protection, FPS-only restart continuity, and valid 12-fps WebM output after explicitly logged 12-second fixture captures. Run it with `PI_AGENT_BROWSER_REAL_UPSTREAM=1`; it requires native 0.37 or newer. Keep focused older-native controls for fresh-page starts and the start-then-ref batch latch when changing that policy.
|
|
276
277
|
- **Managed session core and safe diagnostic matrix:** fresh `open` on the contract fixture, then implicit reuse across `eval --stdin`, `snapshot -i`, interaction commands (`click`, `dblclick`, `fill`, `type`, `type --clear --delay`, `focus`, `keyboard` with `type` / `inserttext`, `press`, `hover`, `check`, `uncheck`, `select`, failed `select` no-match, `upload`, `drag`, `mouse`, `scroll`, off-viewport click, `scrollintoview`, `wait` on selectors in the main frame and a selected iframe), extraction (`get` variants, `is` variants, `find label … fill` via native `<label>`, `aria-label`, and `aria-labelledby`, inline `eval`), file outputs (`screenshot`, `pdf`), navigation (`back`, `forward`, `reload`, `tab list`, another `open` to the same fixture), `batch` stdin, `pushstate`, `vitals … --json`, network route/requests/HAR, diff snapshot/screenshot/url, trace/profiler, console/errors/highlight, stream enable/status/disable, and `cookies set --curl`.
|
|
277
|
-
- **Managed restore correctness and persistence:** while the restore-enabled managed daemon is active, assert raw argument and stdin batches containing nested `connect` fail before upstream spawn; a new
|
|
278
|
-
- **Cold first-read continuity:** the focused `contract suite matches cold URL reopen after quit` case runs actual quit cleanup, waits for the exact old daemon to exit, reloads the saved branch, and requests `snapshot -i` before any explicit navigation. Empty storage and origin storage must both reach their remembered non-root URL, report fresh refs in the main frame, and retain storage without pretending to retain unsaved forms or JavaScript memory. Separate deterministic cold-resume/boundary tests cover first `get url` and history commands, non-page daemon-starting calls and batch prefixes, hash routes, pending-state transcript replay, live missing tabs versus explicit URL destinations, close retirement, and caller-owned/attached/restore-disabled boundaries. Those fake-upstream checks do not replace native-browser or real Pi lifecycle qualification of the complete candidate.
|
|
278
|
+
- **Managed restore correctness and persistence:** while the restore-enabled managed daemon is active, assert raw argument and stdin batches containing nested `connect` fail before upstream spawn; a new harness replaying the owned launch result must also reject incompatible reuse of that live same-name daemon. Seed a cookie plus localStorage/sessionStorage, close the first managed browser while a conflicting parent namespace is set, verify the default-namespace daemon actually closed, create a new extension harness with the same cwd, reopen the fixture with `sessionMode: "fresh"`, and assert all three values restore before closing the second browser. On POSIX, separate isolated real-browser launches assert automatic restore stays disabled and no snapshot is written through either a symlinked `sessions` directory or a file symlink in `sessions/.tmp`; a relative `HOME`, untrusted writable HOME ancestry, and a non-Git cwd must fail closed. Verify a checkout rename preserves its generation identity but starts a fresh composite restore key (fail-closed, because the cwd-derived managed-session base name changes), a copied or path-replacement checkout gets a new key, and changing the Git-generation marker between planning and spawn prevents agent-browser from starting. Run two same-identity harnesses concurrently so a compatible launch publishes its daemon policy before a waiting incompatible launch re-inspects and fails without reaching its main spawn; also fail a fresh non-batch command after daemon creation and verify shutdown closes the retained identity.
|
|
279
|
+
- **Cold first-read continuity:** the focused `contract suite matches cold URL reopen after quit` case starts an explicit `sessionMode: "fresh"` managed browser, runs actual quit cleanup, waits for the exact old daemon to exit, reloads the saved branch, and requests `snapshot -i` before any explicit navigation. Empty storage and origin storage must both reach their remembered non-root URL, report fresh refs in the main frame, and retain storage without pretending to retain unsaved forms or JavaScript memory. Separate deterministic cold-resume/boundary tests cover first `get url` and history commands, non-page daemon-starting calls and batch prefixes, hash routes, pending-state transcript replay, live missing tabs versus explicit URL destinations, close retirement, and caller-owned/attached/restore-disabled boundaries. Those fake-upstream checks do not replace native-browser or real Pi lifecycle qualification of the complete candidate.
|
|
279
280
|
- **Failure shape:** `react tree` on a page opened with `--enable react-devtools` but without a React app (expects a clear missing-renderer error with session-bound `details`).
|
|
280
281
|
- **Async download:** `open` on the `/download` fixture, anchor-triggered export, then `wait --download <path>` metadata and wrapper artifact reporting for the requested path.
|
|
281
282
|
|