pi-agent-browser-native 0.6.13 → 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.
Files changed (36) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +8 -6
  3. package/dist/extensions/agent-browser/index.js +7 -4
  4. package/dist/extensions/agent-browser/lib/argv-grammar.js +1 -0
  5. package/dist/extensions/agent-browser/lib/command-taxonomy.js +4 -0
  6. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +14 -3
  7. package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +1 -1
  8. package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +18 -2
  9. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +15 -4
  10. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +3 -0
  11. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +2 -0
  12. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +14 -3
  13. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +5 -2
  14. package/dist/extensions/agent-browser/lib/playbook.js +1 -0
  15. package/dist/extensions/agent-browser/lib/recording-reservations.js +8 -1
  16. package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +15 -1
  17. package/dist/extensions/agent-browser/lib/results/presentation/batch.js +18 -9
  18. package/dist/extensions/agent-browser/lib/results/presentation/common.js +3 -0
  19. package/dist/extensions/agent-browser/lib/results/presentation/registry.js +1 -1
  20. package/dist/extensions/agent-browser/lib/results/presentation.js +7 -3
  21. package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +14 -2
  22. package/dist/extensions/agent-browser/lib/results/snapshot.js +12 -5
  23. package/dist/extensions/agent-browser/lib/runtime.js +3 -1
  24. package/dist/extensions/agent-browser/lib/session-page-state.js +7 -3
  25. package/dist/extensions/agent-browser/lib/webmcp-observation.js +28 -0
  26. package/dist/scripts/agent-browser-target.mjs +1 -1
  27. package/docs/ARCHITECTURE.md +7 -1
  28. package/docs/COMMAND_REFERENCE.md +67 -14
  29. package/docs/ELECTRON.md +1 -1
  30. package/docs/RELEASE.md +4 -3
  31. package/docs/SUPPORT_MATRIX.md +12 -8
  32. package/docs/TOOL_CONTRACT.md +13 -3
  33. package/docs/platform-smoke.md +2 -2
  34. package/package.json +1 -1
  35. package/scripts/agent-browser-capability-baseline.mjs +34 -3
  36. package/scripts/agent-browser-target.mjs +1 -1
@@ -5,7 +5,7 @@ import { buildAgentBrowserNextActions } from "./action-recommendations.js";
5
5
  import { buildAgentBrowserResultCategoryDetails } from "./categories.js";
6
6
  import { detectConfirmationRequired } from "./confirmation.js";
7
7
  import { buildSnapshotPresentation } from "./snapshot.js";
8
- import { redactModelFacingText } from "./presentation/common.js";
8
+ import { formatWebMcpCatalogUpdate, redactModelFacingText } from "./presentation/common.js";
9
9
  import { applyArtifactManifest, attachInlineImage, buildArtifactVerificationSummary, buildManifestEntriesForFileArtifacts, classifyPresentationSuccessCategory, extractFileArtifacts, extractImagePath, formatArtifactMetadataLines, formatArtifactSummary, formatMissingArtifactFailureText, getSavedFileDetails, hasMissingFileArtifact, isManifestFileArtifact, } from "./presentation/artifacts.js";
10
10
  import { buildBatchPresentation, isAgentBrowserBatchResultArray, redactBatchStepErrorData } from "./presentation/batch.js";
11
11
  import { getPresentationPaths, isStringArray } from "./presentation/content.js";
@@ -72,7 +72,7 @@ export async function buildToolPresentation(options) {
72
72
  const presentationData = commandInfo.command === "batch" && isAgentBrowserBatchResultArray(data)
73
73
  ? redactBatchSpillData(data)
74
74
  : redactPresentationData(commandInfoWithTokens, data);
75
- const artifacts = await extractFileArtifacts({ artifactManifest, artifactMaxUpdatedAtMs: options.artifactMaxUpdatedAtMs, artifactMinUpdatedAtMs: options.artifactMinUpdatedAtMs, artifactRequest, commandInfo: presentationCommandInfo, cwd, data, namespace, recordingOutcome: recordingCommand ? envelope?.success : undefined, recordingPending: options.recordingPending, sessionName });
75
+ const artifacts = await extractFileArtifacts({ artifactManifest, artifactMaxUpdatedAtMs: options.artifactMaxUpdatedAtMs, artifactMinUpdatedAtMs: options.artifactMinUpdatedAtMs, artifactRequest, commandInfo: presentationCommandInfo, cwd, data, namespace, recordingOutcome: recordingCommand ? envelope?.success : undefined, recordingPending: options.recordingPending, previousRecordingContactSheetPath: options.previousRecordingContactSheetPath, sessionName });
76
76
  const artifactVerification = buildArtifactVerificationSummary(artifacts);
77
77
  const artifactSummary = formatArtifactSummary(artifacts);
78
78
  const summary = artifactSummary ?? formatPresentationSummary(commandInfoWithTokens, data, compiledSemanticAction);
@@ -130,6 +130,9 @@ export async function buildToolPresentation(options) {
130
130
  presentation.savedFilePath = savedFile.path;
131
131
  }
132
132
  }
133
+ if (isRecord(presentationData) && isRecord(presentationData.webmcp) && (Array.isArray(presentationData.webmcp.tools) || presentationData.webmcp.status === "unavailable") && presentation.content[0]?.type === "text") {
134
+ presentation.content[0] = { ...presentation.content[0], text: `${presentation.content[0].text}\n\n${formatWebMcpCatalogUpdate(presentationData.webmcp)}` };
135
+ }
133
136
  if (shouldAddAnnotatedScreenshotGuidance(commandInfo, args) && presentation.content[0]?.type === "text") {
134
137
  const guidance = "Annotated screenshot note: dense pages can produce overlapping labels. If the labels are noisy, capture a scoped element screenshot, take a non-annotated screenshot, or use snapshot -i high-value refs as the machine-readable map.";
135
138
  presentation.content[0] = { ...presentation.content[0], text: `${presentation.content[0].text}\n\n${guidance}` };
@@ -138,7 +141,8 @@ export async function buildToolPresentation(options) {
138
141
  if (keyboardInsertTextWarning && presentation.content[0]?.type === "text") {
139
142
  presentation.content[0] = { ...presentation.content[0], text: `${presentation.content[0].text}\n\n${keyboardInsertTextWarning}` };
140
143
  }
141
- const imagePath = artifactRequest?.absolutePath ?? extractImagePath(commandInfo, cwd, data);
144
+ const imagePath = artifactRequest?.absolutePath ?? extractImagePath(commandInfo, cwd, data)
145
+ ?? (recordingCommand ? artifacts.find((artifact) => artifact.kind === "image" && artifact.status === "saved")?.absolutePath : undefined);
142
146
  const presentationWithImage = imagePath ? await attachInlineImage(presentation, imagePath) : presentation;
143
147
  const compactedPresentation = await compactLargePresentationOutput({
144
148
  artifactManifest,
@@ -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
- return isRecord(data) && isRecord(data.refs) ? data.refs : undefined;
15
+ const full = getFullSnapshotData(data);
16
+ return full && isRecord(full.refs) ? full.refs : undefined;
6
17
  }
7
18
  export function getSnapshotLineTextByRef(data) {
8
- const snapshot = isRecord(data) && typeof data.snapshot === "string" ? data.snapshot : "";
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
- return typeof data.snapshot === "string" ? data.snapshot : undefined;
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
- const refs = isRecord(data.refs) ? Object.keys(data.refs).length : 0;
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 = isRecord(data.refs) ? Object.keys(data.refs).length : 0;
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
- if (!shouldCompactSnapshot(rawText, data)) {
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
- const DEFAULT_IMPLICIT_SESSION_CLOSE_TIMEOUT_MS = 5_000;
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(data) {
192
- if (!isRecord(data))
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.37.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}`;
@@ -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.
@@ -182,7 +188,7 @@ Practical policy:
182
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
183
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)
184
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
185
- - 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
186
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
187
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
188
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
@@ -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.37.0` command/help surface, audited against vercel-labs/agent-browser@471ab3852b47b98847f1d9c855c272bb62d0d50b. 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.
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
- The recommended release keeps the stable 0.35.0 floor and no upper version cap.
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.
@@ -476,7 +497,7 @@ Typical lifecycle:
476
497
  { "electron": { "action": "cleanup", "launchId": "electron-…" } }
477
498
  ```
478
499
 
479
- `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 (**5s** 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.
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.
480
501
 
481
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.
482
503
 
@@ -722,7 +743,7 @@ Skill-source debugging note: upstream honors `AGENT_BROWSER_SKILLS_DIR` as an ov
722
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. |
723
744
  | `screenshot [path]` | Take a screenshot and optionally save it to a path. |
724
745
  | `pdf <path>` | Save the page as a PDF. |
725
- | `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 --cursor` / `snapshot -C` for cursor/focus context when upstream returns it. |
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. |
726
747
  | `eval <js>` | Run JavaScript. Use `eval --stdin` through this wrapper for larger snippets, or `eval -b <base64>` for shell-escaping-safe one-liners. |
727
748
  | `connect <port|url>` | Connect to a browser through CDP. |
728
749
  | `close [--all]` | Close the current browser or all sessions; `quit` and `exit` are upstream close aliases. |
@@ -835,10 +856,11 @@ With `--pin-tab`, a closed bound tab fails as `tab_gone` (`data.targetId`, optio
835
856
  | `snapshot -i` / `snapshot --interactive` | Include only interactive elements. |
836
857
  | `snapshot -i --urls` | Include only interactive elements and link hrefs. |
837
858
  | `snapshot -u` / `snapshot --urls` | Include href URLs for link elements. |
838
- | `snapshot -C` / `snapshot --cursor` | Include cursor/focus context when upstream provides it. |
859
+ | `snapshot -C` / `snapshot --cursor` | Deprecated no-ops; cursor-interactive elements are included by default. |
839
860
  | `snapshot -c` / `snapshot --compact` | Remove empty structural elements. |
840
861
  | `snapshot -d <n>` / `snapshot --depth <n>` | Limit tree depth. |
841
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). |
842
864
 
843
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)).
844
866
 
@@ -903,7 +925,7 @@ Long-running or lifecycle commands should be explicitly paired with cleanup call
903
925
  | --- | --- |
904
926
  | `batch [--bail] ["cmd" ...]` | Execute multiple commands sequentially from args or stdin. |
905
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`. |
906
- | `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. |
907
929
  | `auth list` | List saved auth profiles. |
908
930
  | `auth show <name>` | Show auth profile metadata. |
909
931
  | `auth delete <name>` | Delete an auth profile; `auth remove <name>` is the upstream alias. |
@@ -1127,14 +1149,14 @@ Other useful environment variables include `AGENT_BROWSER_DEFAULT_TIMEOUT`, `AGE
1127
1149
  <!-- agent-browser-capability-baseline:start capability-token-baseline -->
1128
1150
  <!-- Generated from scripts/agent-browser-capability-baseline.mjs. Run `npm run docs -- command-reference write` to update. Do not edit manually. -->
1129
1151
  <details>
1130
- <summary>Generated verifier capability baseline for agent-browser 0.37.0</summary>
1152
+ <summary>Generated verifier capability baseline for agent-browser 0.38.1</summary>
1131
1153
 
1132
1154
  This generated block is review data for maintainers. The human-authored reference sections above remain the readable command guide.
1133
1155
 
1134
1156
  #### Source evidence
1135
1157
  - repository: `vercel-labs/agent-browser`
1136
- - upstream HEAD: `471ab3852b47b98847f1d9c855c272bb62d0d50b`
1137
- - upstream package version: `0.37.0`
1158
+ - upstream HEAD: `aff6125c023b810ea3f2e5deec5379e9a4270bdc`
1159
+ - upstream package version: `0.38.1`
1138
1160
  - inspected: `agent-browser --version`
1139
1161
  - inspected: `agent-browser --help`
1140
1162
  - inspected: `selected agent-browser <command> --help output`
@@ -1163,6 +1185,9 @@ This generated block is review data for maintainers. The human-authored referenc
1163
1185
  - inspected: `cli/src/native/daemon.rs`
1164
1186
  - inspected: `cli/src/native/element.rs`
1165
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`
1166
1191
  - inspected: `cli/src/native/stream/cdp_loop.rs`
1167
1192
  - inspected: `cli/src/native/stream/dashboard.rs`
1168
1193
  - inspected: `cli/src/native/test_fixtures/webmcp_frame_probe.html`
@@ -1209,6 +1234,7 @@ This generated block is review data for maintainers. The human-authored referenc
1209
1234
  - get help: `agent-browser get --help`
1210
1235
  - is help: `agent-browser is --help`
1211
1236
  - mouse help: `agent-browser mouse --help`
1237
+ - drag help: `agent-browser drag --help`
1212
1238
  - set help: `agent-browser set --help`
1213
1239
  - tab help: `agent-browser tab --help`
1214
1240
  - snapshot help: `agent-browser snapshot --help`
@@ -1252,11 +1278,11 @@ This generated block is review data for maintainers. The human-authored referenc
1252
1278
 
1253
1279
  #### Inventory sections
1254
1280
  - Built-in skills: 19 human-doc token(s), 24 upstream token(s)
1255
- - Core page, element, navigation, and extraction commands: 82 human-doc token(s), 85 upstream token(s)
1281
+ - Core page, element, navigation, and extraction commands: 89 human-doc token(s), 94 upstream token(s)
1256
1282
  - Sessions, state, tabs, frames, dialogs, and windows: 28 human-doc token(s), 26 upstream token(s)
1257
- - Network, storage, artifacts, diagnostics, and performance: 58 human-doc token(s), 68 upstream token(s)
1258
- - Batch, auth, confirmations, setup, dashboard, devices, and AI commands: 36 human-doc token(s), 40 upstream token(s)
1259
- - Global flags, config, providers, policy, and environment: 152 human-doc token(s), 119 upstream token(s)
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)
1260
1286
 
1261
1287
  #### Human-authored doc tokens required
1262
1288
  ##### Built-in skills
@@ -1327,6 +1353,13 @@ This generated block is review data for maintainers. The human-authored referenc
1327
1353
  - `screenshot [path]`
1328
1354
  - `screenshot --full`
1329
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>`
1330
1363
  - `pdf <path>`
1331
1364
  - `snapshot`
1332
1365
  - `snapshot --cursor`
@@ -1410,6 +1443,7 @@ This generated block is review data for maintainers. The human-authored referenc
1410
1443
  - `cookies set --curl <file>`
1411
1444
  - `storage <local|session>`
1412
1445
  - `webmcp list`
1446
+ - `webmcp list [tool] [--frame <frame-id>]`
1413
1447
  - `webmcp invoke <tool>`
1414
1448
  - `webmcp invoke <tool> --params <json|@file>`
1415
1449
  - `webmcp invoke <tool> --frame <frame-id>`
@@ -1429,6 +1463,9 @@ This generated block is review data for maintainers. The human-authored referenc
1429
1463
  - `record start <path> [url]`
1430
1464
  - `record restart <path> [url]`
1431
1465
  - `--fps <n>`
1466
+ - `--cursor`
1467
+ - `--contact-sheet`
1468
+ - `--contact-sheet-threshold <n>`
1432
1469
  - `record stop`
1433
1470
  - `console [--clear]`
1434
1471
  - `errors [--clear]`
@@ -1461,6 +1498,7 @@ This generated block is review data for maintainers. The human-authored referenc
1461
1498
  - `auth save <name> --username-selector <s> --password-selector <s> --submit-selector <s>`
1462
1499
  - `auth save <name> --password-stdin`
1463
1500
  - `auth login <name>`
1501
+ - `auth login <name> --no-navigate`
1464
1502
  - `auth list`
1465
1503
  - `auth show <name>`
1466
1504
  - `auth delete <name>`
@@ -1564,6 +1602,7 @@ This generated block is review data for maintainers. The human-authored referenc
1564
1602
  - `AGENT_BROWSER_DOWNLOAD_PATH`
1565
1603
  - `--engine <name>`
1566
1604
  - `AGENT_BROWSER_ENGINE`
1605
+ - `--input-mode <mode>`
1567
1606
  - `--no-auto-dialog`
1568
1607
  - `AGENT_BROWSER_NO_AUTO_DIALOG`
1569
1608
  - `--json`
@@ -1755,6 +1794,15 @@ This generated block is review data for maintainers. The human-authored referenc
1755
1794
  - keyboard help: `inserttext <text>`
1756
1795
  - screenshot help: `--full, -f`
1757
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>`
1758
1806
  - find help: `role <role>`
1759
1807
  - find help: `testid <id>`
1760
1808
  - tap help: `tap <selector>`
@@ -1799,7 +1847,7 @@ This generated block is review data for maintainers. The human-authored referenc
1799
1847
  - root help: `cookies [get|set|clear]`
1800
1848
  - root help: `cookies set --curl <file>`
1801
1849
  - root help: `storage <local|session>`
1802
- - root help: `webmcp list`
1850
+ - root help: `webmcp list [tool]`
1803
1851
  - root help: `webmcp invoke <tool>`
1804
1852
  - root help: `--params <json|@file>`
1805
1853
  - root help: `--frame <frame-id>`
@@ -1855,6 +1903,9 @@ This generated block is review data for maintainers. The human-authored referenc
1855
1903
  - profiler help: `--categories <list>`
1856
1904
  - record help: `record restart <path.webm|path.mp4> [url] [--fps <n>]`
1857
1905
  - record help: `--fps <n>`
1906
+ - record help: `--cursor`
1907
+ - record help: `--contact-sheet`
1908
+ - record help: `--contact-sheet-threshold <n>`
1858
1909
  - console help: `--clear`
1859
1910
  - errors help: `--clear`
1860
1911
 
@@ -1895,6 +1946,7 @@ This generated block is review data for maintainers. The human-authored referenc
1895
1946
  - root help: `plugin show <name>`
1896
1947
  - root help: `plugin run <name> <type>`
1897
1948
  - auth help: `--credential-provider <p>`
1949
+ - auth help: `--no-navigate`
1898
1950
  - mcp help: `agent_browser_open`
1899
1951
  - mcp help: `--tools`
1900
1952
  - plugin help: `Add a plugin from npm or GitHub`
@@ -1968,6 +2020,7 @@ This generated block is review data for maintainers. The human-authored referenc
1968
2020
  - root help: `AGENT_BROWSER_DOWNLOAD_PATH`
1969
2021
  - root help: `--engine <name>`
1970
2022
  - root help: `AGENT_BROWSER_ENGINE`
2023
+ - root help: `--input-mode <mode>`
1971
2024
  - root help: `--no-auto-dialog`
1972
2025
  - root help: `AGENT_BROWSER_NO_AUTO_DIALOG`
1973
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 **5000 ms** (`getImplicitSessionCloseTimeoutMs` in `extensions/agent-browser/lib/runtime.ts`, passed through `cleanupTrackedElectronHostLaunches` in `extensions/agent-browser/lib/orchestration/electron-host/index.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 **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.13 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.
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
 
@@ -269,8 +269,9 @@ 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.37.0 target), `skills path …` (no managed `sessionName` / `usedImplicitSession`).
273
- - **WebMCP target contract:** on the 0.37.0 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.
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`.