pi-agent-browser-native 0.2.62 → 0.2.64

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 CHANGED
@@ -2,6 +2,33 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.2.64 - 2026-07-01
6
+
7
+ ### Fixed
8
+
9
+ - Clarified `agent_browser` prompt, command-reference, and error-hint guidance so selector-required getters such as `get text/html/value/count <selector>` and `get attr <selector> <name>` are no longer grouped with selector-less `get title/url`.
10
+ - Expanded adjacent shorthand command guidance for React, network, diff, trace/profiler/record, and clipboard families so prompts do not imply missing arguments are valid.
11
+
12
+ ### Validation
13
+
14
+ - Ran `npm run verify`, focused prompt/error/doc tests, `git diff --check`, and a reviewer subagent loop until both reviewers returned `GREEN`.
15
+
16
+ ## 0.2.63 - 2026-06-26
17
+
18
+ ### Changed
19
+
20
+ - Rebaselined upstream capability metadata, command reference, support docs, and real-upstream output-shape metadata for `agent-browser` `0.31.1` / vercel-labs/agent-browser@ed2e10598c9064aecfaeb7cf21b540684db4be2c.
21
+ - Recorded upstream's React renderer bugfix for `react tree`, `react inspect`, and `react suspense`; no wrapper CLI/schema/runtime compatibility change was needed.
22
+ - Isolated the real-upstream `wait --download` contract's browser download directory under the test temp root so upstream's known saveAs limitation no longer spills fixture files into `~/Downloads`.
23
+ - Made Windows browser-dogfood platform smoke fail fast instead of hanging silently by bounding `agent-browser` prewarm commands, killing timed-out process trees, and printing per-suite progress for single-suite runs.
24
+ - Hardened Windows platform-smoke doctor cleanup so disposable probe stop failures fail the doctor instead of leaking Crabbox VMs/leases.
25
+ - Removed a redundant dogfood `domcontentloaded` wait that could race after a successful file-page open on Windows.
26
+
27
+ ### Validation
28
+
29
+ - Ran `npm run docs -- command-reference check`, `npm run verify -- command-reference`, `npm run verify -- real-upstream`, `npm run verify -- dogfood`, `npm run smoke:platform:ubuntu-image`, `npm run verify -- release`, `npm publish --dry-run`, and `git diff --check`.
30
+ - Used subagent and intercom review to confirm 0.31.1 changes are limited to upstream React renderer selection plus version/changelog metadata.
31
+
5
32
  ## 0.2.62 - 2026-06-26
6
33
 
7
34
  ### Changed
@@ -20,7 +20,7 @@ export const QUICK_START_GUIDELINES = [
20
20
  "Locator-first clicks/fills and native select changes without hand-building argv: { semanticAction: { action: \"click\", locator: \"text\", value: \"Close\" } }, { semanticAction: { action: \"fill\", locator: \"label\", value: \"Email\", text: \"user@example.com\" } }, direct current targets such as { semanticAction: { action: \"fill\", selector: \"@e1\", text: \"prompt\" } }, or { semanticAction: { action: \"select\", selector: \"#flavor\", value: \"chocolate\" } }; add semanticAction.session when targeting a named upstream browser session; details.compiledSemanticAction shows the semantic target, while details.effectiveArgs may show a resolved current @ref for active-session role/name click/check/fill actions to avoid hidden duplicate matches; semanticAction does not expose uncheck while upstream find ... uncheck is not runtime-supported, so use raw uncheck with a stable selector or current ref; selector-not-found failures may append bounded click try-*-candidate next actions or, for fill misses with current editable refs, details.richInputRecovery with focus/click actions that do not copy fill text; stale-ref failures can return retry-semantic-action-after-stale-ref for compiled find actions when retry safety is provable.",
21
21
  `Common advanced calls: { args: ["batch"], stdin: "[[\"open\",\"https://example.com\"],[\"snapshot\",\"-i\"]]" }, { job: { steps: [{ action: "open", url: "https://example.com" }, { action: "assertText", text: "Example Domain" }, { action: "screenshot", path: ".dogfood/example.png" }] } }, { qa: { url: "https://example.com", expectedText: "Example Domain", screenshotPath: ".dogfood/qa-example.png" } } (example.com smoke only; elsewhere match exact visible text from snapshot -i), { electron: { action: "list", query: "code" } }, { electron: { action: "launch", appName: "Visual Studio Code", handoff: "snapshot" } }, { electron: { action: "probe" } }, { qa: { attached: true, expectedText: "Explorer" } }, { args: ["eval", "--stdin"], stdin: "document.title", outputPath: "logs/page-title.json" }, { args: ["auth", "save", "name", "--password-stdin"], stdin: "<password from user-approved secret source>" }, { args: ["--profile", "Default", "open", "https://example.com/account"], sessionMode: "fresh" }, and { args: ["open", "--enable", "react-devtools", "https://example.com"], sessionMode: "fresh" }. For app pages with a native dropdown, job steps can include { action: "select", selector: "#flavor", value: "chocolate" } before the dependent assertion; for locator-friendly pages, job click/fill steps can use semantic locator fields such as { action: "fill", locator: "role", role: "searchbox", name: "Search", text: "agent browser" }; for human-paced input, job type steps can use { action: "type", selector: "#prompt", text: "hello", delayMs: 20, press: "Enter" }; delayed typing is capped at 200 characters per step, and generated per-character rows are compacted in visible batch prose while full rows remain in details.batchSteps.`,
22
22
  "Constrained job navigation is explicit only: click (and select/submit flows that may navigate) does not prove the next page loaded; add assertUrl and/or assertText after navigation-prone steps before screenshot or later interactions. Keep jobs short around navigation, click, and rerender boundaries on dynamic React/product apps; avoid a whole checkout in one job. If a long job times out and details.timeoutPartialProgress shows a mutating incomplete step, inspect current page state and continue with a shorter job or single action instead of blindly retrying the mutating step. Example: { job: { steps: [{ action: \"open\", url: \"https://shop.example/checkout\" }, { action: \"fill\", selector: \"#email\", text: \"user@example.com\" }, { action: \"click\", selector: \"#continue\" }, { action: \"assertUrl\", url: \"**/shipping\" }, { action: \"assertText\", text: \"Shipping address\" }, { action: \"screenshot\", path: \".dogfood/shipping.png\" }] } }. Top-level click may add pageChangeSummary hints, but job never auto-inserts post-click asserts.",
23
- "High-value command reference: click <selector> --new-tab opens link-like targets in a new tab; select <selector> <value...> changes native dropdown values; scroll <dir> [px] --selector <sel>, wrapper-handled scroll <selector> <dir> [px|percent] targets nested scrollers, and wrapper-handled scroll to end/top targets document scrolling; download <selector> <path> saves a file triggered by a click; get title/url/text/html/value/attr/count reads page state; screenshot [selector] [path] captures a page or element image; pdf <path> saves a PDF; tab list and tab <tab-id-or-label> inspect or recover the active tab; react tree/inspect/renders/suspense introspect React after --enable react-devtools; vitals [url] measures Core Web Vitals; pushstate <url> performs SPA navigation; tap <selector> and swipe <direction> [distance] support iOS/provider touch flows.",
23
+ "High-value command reference: click <selector> --new-tab opens link-like targets in a new tab; select <selector> <value...> changes native dropdown values; scroll <dir> [px] --selector <sel>, wrapper-handled scroll <selector> <dir> [px|percent] targets nested scrollers, and wrapper-handled scroll to end/top targets document scrolling; download <selector> <path> saves a file triggered by a click; get title/url need no selector; get text/html/value/count <selector> and get attr <selector> <name> read elements/page state (use body for whole-page text/html); screenshot [selector] [path] captures a page or element image; pdf <path> saves a PDF; tab list and tab <tab-id-or-label> inspect or recover the active tab; react tree, react inspect <fiberId>, react renders start/stop, and react suspense introspect React after --enable react-devtools; vitals [url] measures Core Web Vitals; pushstate <url> performs SPA navigation; tap <selector> and swipe <direction> [distance] support iOS/provider touch flows.",
24
24
  "For artifact-producing commands, read the visible artifact block and details.artifactVerification before using files: check requested path, absolute path, existence, size bytes, artifact kind, optional mediaType, status, optional limitation, and verified/missing/pending/unverified counts. details.artifacts contains per-file metadata; record start rows are pending/openRecording until record stop writes the target. The wrapper creates parent directories for direct artifact paths and can save simple loopback HTTP(S) anchor downloads directly to the requested path before upstream download fallback. Browser close does not delete explicit saved files; if close reports details.artifactCleanup, use host file tools to remove paths listed in explicitArtifactPaths (when non-empty) after inspection. If close fails with details.promptGuard.reason=requested-artifacts-missing-before-close, save the exact required artifact path before closing. For annotated screenshots inside batch, put --annotate in top-level args (for example { args: [\"--annotate\", \"batch\"], stdin: \"[[\\\"screenshot\\\",\\\"/tmp/page.png\\\"]]\" }) rather than inside the screenshot step; if annotation labels crowd a dense page, use a scoped or non-annotated screenshot plus snapshot refs instead.",
25
25
  "When details.nextActions is present, prefer those exact native agent_browser follow-up payloads over prose guidance; they may include args, stdin, sessionMode, networkSourceLookup, safety notes, or artifactPath for saved files.",
26
26
  ];
@@ -41,7 +41,7 @@ export const SHARED_BROWSER_PLAYBOOK_GUIDELINES = [
41
41
  "For first-navigation setup, use open without a URL plus network route --resource-type <csv>, cookies set --curl <file>, or --init-script/--enable before navigate/opening the target page.",
42
42
  "For stateful browser context work, prefer purpose-specific page actions before dumping browser data: use auth save --password-stdin with the tool stdin field for credentials, auth list/show/delete/remove for local auth-profile maintenance, auth login when you need the browser to fill a saved profile, state save/load for portable test state, state list/show/rename/clear/clear -a/clean for saved-state lifecycle cleanup, cookies get/set/clear and storage local|session only when the task needs those values, and expect cookie/storage/auth/state summaries to redact credential-like fields while allowing benign primitive storage values when useful for local QA.",
43
43
  "For batch chains that touch cookies, storage, auth, or other secret-bearing commands, use details.batchSteps for per-step artifacts, categories, spill paths, and full structured errors; top-level details.data on batch is only a compact redacted step matrix (success, argv-redacted command, redacted result or scrubbed error text) built from the same presentation rules as standalone calls.",
44
- "For non-core families, pass current upstream commands through the native tool directly: network route/requests/har (including request filters like --type/--method/--status), diff snapshot/screenshot/url with scoped/baseline options, trace/profiler/record, console/errors/highlight/inspect/clipboard, stream enable/disable/status, dashboard start/stop, device list for iOS simulator inventory, and chat. For compact network requests output, prefer details.nextActions for request detail, route-mock diagnostics, actionable failed-request networkSourceLookup, filtering, clearing the aggregate buffer before repro, or HAR capture follow-ups instead of guessing request-id syntax. Artifact-producing commands report details.artifacts and verification state; long-running starts such as stream, dashboard, trace/profiler, and record should be paired with the matching stop/disable command when the task is done; stream enable already-enabled outcomes are treated as idempotent success with status/disable follow-ups.",
44
+ "For non-core families, pass current upstream commands through the native tool directly: network requests, network route <url>, network har start/stop [path], diff snapshot, diff screenshot --baseline <file>, diff url <u1> <u2>, trace start, trace stop [path], profiler start, profiler stop [path], record start <path>, record stop, console/errors [--clear], highlight <selector>, inspect, clipboard read, clipboard write <text>, clipboard copy/paste, stream enable/disable/status, dashboard start/stop, device list for iOS simulator inventory, and chat <message>. For compact network requests output, prefer details.nextActions for request detail, route-mock diagnostics, actionable failed-request networkSourceLookup, filtering, clearing the aggregate buffer before repro, or HAR capture follow-ups instead of guessing request-id syntax. Artifact-producing commands report details.artifacts and verification state; long-running starts such as stream, dashboard, trace/profiler, and record should be paired with the matching stop/disable command when the task is done; stream enable already-enabled outcomes are treated as idempotent success with status/disable follow-ups.",
45
45
  "For Electron desktop apps, prefer top-level electron for wrapper-owned discovery, isolated launch, status, compact probe, and cleanup: list first, treat likely-sensitive annotations as hints rather than enforcement, launch with the default snapshot handoff unless handoff: \"tabs\" is the safer diagnostic starting point, use electron.probe or snapshot -i/qa.attached for current-session state, and always cleanup the returned launchId when done. electron.launch uses an isolated temporary profile; it does not reuse the app's normal signed-in profile or attach to an already-running authenticated app. For signed-in local app state, host-launch the normal app with --remote-debugging-port when appropriate, then use raw args connect <port|url>; after connect, inspect tab list, select the stable tab id such as tab t2, then run a condition wait or snapshot -i before using refs. close commands (`close`, `quit`, or `exit`) only close the browser/CDP session; leave manually launched app shutdown, profile cleanup, and explicit artifacts to the host owner.",
46
46
  "For provider or specialized app workflows, load version-matched upstream guidance with skills get agentcore|electron|slack|dogfood|vercel-sandbox through the native tool; add --full when you need references/templates, and use skills get --all only for broad skill audits. Hosted sandbox workflows should use upstream @agent-browser/sandbox helpers outside this wrapper. Provider launches such as -p ios, --provider browserbase/kernel/browseruse/browserless/agentcore, and iOS --device are upstream-owned setup paths; use sessionMode fresh when switching providers and expect external credentials or local Appium/Xcode setup to be required.",
47
47
  "For dialogs and frames, use dialog status/accept/dismiss and frame <selector|main> through native args; dialog commands and eval snippets that look like alert/confirm/prompt/dialog triggers are shorter-bounded than normal browser calls, and timed-out dialog-like interactions may add inspect-dialog-after-timeout, dismiss-dialog-after-timeout, or recover-fresh-session-after-dialog-timeout nextActions. When --confirm-actions produces a pending confirmation, use details.nextActions or exact confirm <id> / deny <id> calls instead of inventing ids.",
@@ -90,7 +90,7 @@ export const RUNTIME_PROMPT_GUIDELINES = [
90
90
  "Use agent_browser sessionMode=fresh for launch-scoped flags; never put --session-mode in args. Use requested/configured profiles only; on profile failures run profiles/doctor. Profile content is model-visible.",
91
91
  "For agent_browser artifacts, use exact user paths and verify details.artifactVerification/details.artifacts before claiming success. Save details.promptGuard-required artifacts before close; record stop needs ffmpeg; close keeps files; waited:timeout is not proof.",
92
92
  "When agent_browser details.nextActions exists, use exact payloads over guessed selectors/prose. Dense snapshots: check Omitted high-value controls/highValueControlRefIds. Dashboards: verify scroll with screenshot/snapshot.",
93
- "For agent_browser extraction, prefer get title/url/text/html/value/attr/count or eval --stdin returning a plain value, not console.log. Batch three-plus known reads; selector visibility warnings mean use visible @refs/nextActions.",
93
+ "For agent_browser extraction, use get title/url; get text/html/value/count <selector> or get attr <selector> <name>; or eval --stdin returning a value. Use get text body for full-page text. Batch 3+ reads; heed selector visibility warnings.",
94
94
  ];
95
95
  export function buildBrowserExecutablePathGuideline(executablePath) {
96
96
  if (!executablePath)
@@ -53,11 +53,11 @@ export function reorderWindowsLeadingGlobalArgs(args) {
53
53
  return args;
54
54
  return [args[index], ...leadingGlobals, ...args.slice(index + 1)];
55
55
  }
56
- function buildAgentBrowserSpawnCommand(args) {
57
- if (processPlatform !== "win32") {
56
+ export function buildAgentBrowserSpawnCommand(args, platform = processPlatform) {
57
+ if (platform !== "win32") {
58
58
  return { command: "agent-browser", args };
59
59
  }
60
- const commandLine = ["&", "agent-browser", ...reorderWindowsLeadingGlobalArgs(args).map(quoteWindowsPowerShellArg)].join(" ");
60
+ const commandLine = ["&", "agent-browser.cmd", ...reorderWindowsLeadingGlobalArgs(args).map(quoteWindowsPowerShellArg)].join(" ");
61
61
  return { command: "powershell.exe", args: ["-NoLogo", "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command", commandLine] };
62
62
  }
63
63
  function terminateSpawnedChild(child, signal) {
@@ -104,7 +104,7 @@ export function redactClipboardPermissionErrorValue(commandInfo, value, payloadC
104
104
  const UNKNOWN_COMMAND_SUGGESTIONS = {
105
105
  attr: [{ description: "Use `get attr <selector> <name>` to read an attribute from a selector or current `@ref`." }],
106
106
  count: [{ description: "Use `get count <selector>` to count matching elements." }],
107
- html: [{ description: "Use `get html <selector>` to read element HTML, or `get html` for the page when upstream supports it." }],
107
+ html: [{ description: "Use `get html <selector>` to read element HTML from a selector or current `@ref`; use `get html body` when you need whole-page body HTML." }],
108
108
  text: [{ description: "Use `get text <selector>` to read text from a selector or current `@ref`; run `snapshot -i` first when you need a safe `@ref`." }],
109
109
  title: [{ args: ["get", "title"], description: "Use `get title` to read the current page title.", id: "use-get-title" }],
110
110
  url: [{ args: ["get", "url"], description: "Use `get url` to read the current page URL.", id: "use-get-url" }],
@@ -18,13 +18,17 @@ This project intentionally blocks normal `agent-browser` bash usage in most agen
18
18
 
19
19
  <!-- agent-browser-capability-baseline:start upstream-baseline -->
20
20
  <!-- Generated from scripts/agent-browser-capability-baseline.mjs. Run `npm run docs -- command-reference write` to update. Do not edit manually. -->
21
- This reference is baselined to the locally installed `agent-browser 0.31.0` command/help surface, audited against vercel-labs/agent-browser@5acf7f9dc153cd51dcc6c79e1aebb09c83b2261d. 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.
21
+ This reference is baselined to the locally installed `agent-browser 0.31.1` command/help surface, audited against vercel-labs/agent-browser@ed2e10598c9064aecfaeb7cf21b540684db4be2c. 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.
22
22
 
23
23
  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.
24
24
 
25
25
  Use `npm run benchmark:agent-browser` or `npm run verify -- benchmark` before and after agent-facing workflow abstractions to measure task success, tool calls, model-visible output size, stale-ref behavior, artifact success, failure-category coverage, and elapsed-time estimates.
26
26
  <!-- agent-browser-capability-baseline:end upstream-baseline -->
27
27
 
28
+ ### Upstream 0.31.1 rebaseline
29
+
30
+ The 0.31.1 rebaseline is a React bugfix release: `react tree`, `react inspect <id>`, and `react suspense` now pick the `react-dom` renderer with mounted fiber roots instead of hardcoding renderer id `1`. This fixes empty React trees on Next.js 16.3 / Turbopack / RSC pages. No CLI/help/schema surface changed, so the wrapper only updates baseline evidence and keeps the 0.31.0 restore/session handling below.
31
+
28
32
  ### Upstream 0.31.0 rebaseline
29
33
 
30
34
  The 0.31.0 rebaseline adds restore workflow and namespace/session lifecycle surfaces: `--restore [name]`, `--restore-save <policy>`, restore check flags, `--namespace <name>`, `session id`, and `session info`. The wrapper parses those globals, keeps `--namespace` before `--session`, carries namespace context through managed-session probes and state, and keeps `session id` / `session info` sessionless. Use `agent_browser` with `args: ["session", "id", "--scope", "worktree", "--prefix", "my-skill"]` to derive reusable session ids from inside Pi; use `--restore=<key>` when passing an explicit key that could be confused with a command word.
@@ -243,7 +247,7 @@ Use `batch --bail` when later steps should stop after the first failed command.
243
247
 
244
248
  For short constrained flows, use top-level `job` instead of hand-writing `batch` stdin. Supported job steps are `open`, `click`, `fill`, `type`, `select`, `wait`, `assertText`, `assertUrl`, `waitForDownload`, `snapshot`, and `screenshot`. `open` can include `loadState: "domcontentloaded" | "load" | "networkidle"` to insert a `wait --load …` row immediately after navigation before the next click/read step. `click` and `fill` accept either a stable `selector` or the same semantic locator fields as top-level `semanticAction` (`locator`, plus `role`/`name` or `value` as appropriate) and compile locator steps to upstream `find` argv. `type` focuses an optional selector, sends text through upstream keyboard typing, can insert `wait` rows via `delayMs` for human-paced input, and can append a final `press` key such as `Enter`; delayed typing is capped at 200 characters per step, and generated per-character rows are compacted in model-visible batch text while remaining available in `details.batchSteps`. `select` requires `selector` plus `value` or `values`, and compiles to upstream `select <selector> <value...>`. By default the wrapper compiles steps to upstream `batch --bail` so a failed setup/fill/assertion step stops later mutating clicks; set `failFast: false` only when you explicitly need continue-after-error diagnostics. The wrapper records `details.compiledJob.steps[]` plus `details.compiledJob.failFast`. There is still no separate first-class catalog of reusable named browser recipes above `job`, the `qa` preset, and raw `batch`; see [`ARCHITECTURE.md`](ARCHITECTURE.md#no-reusable-recipe-layer-yet) for the closed `RQ-0068` decision and revisit bar.
245
249
 
246
- **Job navigation is explicit.** A `click` step (or other navigation-prone interaction) does not prove the next page loaded. The wrapper does not auto-insert `assertUrl` or `assertText` after clicks inside `job`; add those steps yourself with the exact URL, a `*` / `**` glob-style URL pattern, or on-page text you expect, especially after forms, checkout, tabs, or submit buttons, before screenshots or later steps. Exact and glob-style `assertUrl` values compile to `wait --url` unchanged, including query strings and literal `?`; upstream `agent-browser 0.31.0` matches `*` / `**` patterns against the full active URL. Do not put a whole dynamic checkout into one long job: split around login, sorting/cart mutations, checkout navigation, and final evidence capture so refs and app state can be rechecked between phases.
250
+ **Job navigation is explicit.** A `click` step (or other navigation-prone interaction) does not prove the next page loaded. The wrapper does not auto-insert `assertUrl` or `assertText` after clicks inside `job`; add those steps yourself with the exact URL, a `*` / `**` glob-style URL pattern, or on-page text you expect, especially after forms, checkout, tabs, or submit buttons, before screenshots or later steps. Exact and glob-style `assertUrl` values compile to `wait --url` unchanged, including query strings and literal `?`; upstream `agent-browser 0.31.1` matches `*` / `**` patterns against the full active URL. Do not put a whole dynamic checkout into one long job: split around login, sorting/cart mutations, checkout navigation, and final evidence capture so refs and app state can be rechecked between phases.
247
251
 
248
252
  ```json
249
253
  {
@@ -369,7 +373,7 @@ Top-level `networkSourceLookup` does the same for failed browser requests. When
369
373
 
370
374
  Do not omit the load state value; use `wait --load <state>` with `load`, `domcontentloaded`, or `networkidle`.
371
375
 
372
- For desktop-host readiness, prefer condition waits over fixed sleeps. Use this ladder: `wait --text` / `wait --url` / `wait --fn` / `wait --load <state>` / `wait --download` when a real condition exists; after raw `connect`, run `tab list` → `tab t<N>` → condition wait or `snapshot -i`; after wrapper-owned `electron.launch`, use `electron.probe` / `electron.status` for launch health or target mismatch; use `qa.attached` when expected text or selector plus diagnostics can express the check. Upstream `agent-browser 0.31.0` supports `wait --url` glob forms such as `**/dashboard` against the full active URL. Fixed waits are a last resort: use explicit `--timeout` or top-level `timeoutMs` for legitimately slow waits, and treat a successful fixed-wait payload such as `"waited":"timeout"` as elapsed time only, not proof that the desktop host finished. Verify with an observed condition, fresh snapshot, or screenshot before continuing.
376
+ For desktop-host readiness, prefer condition waits over fixed sleeps. Use this ladder: `wait --text` / `wait --url` / `wait --fn` / `wait --load <state>` / `wait --download` when a real condition exists; after raw `connect`, run `tab list` → `tab t<N>` → condition wait or `snapshot -i`; after wrapper-owned `electron.launch`, use `electron.probe` / `electron.status` for launch health or target mismatch; use `qa.attached` when expected text or selector plus diagnostics can express the check. Upstream `agent-browser 0.31.1` supports `wait --url` glob forms such as `**/dashboard` against the full active URL. Fixed waits are a last resort: use explicit `--timeout` or top-level `timeoutMs` for legitimately slow waits, and treat a successful fixed-wait payload such as `"waited":"timeout"` as elapsed time only, not proof that the desktop host finished. Verify with an observed condition, fresh snapshot, or screenshot before continuing.
373
377
 
374
378
  Use `wait --download [path]` after an earlier action has already started a browser download, such as a dashboard export button that responds asynchronously:
375
379
 
@@ -612,7 +616,9 @@ These calls return plain text and stay stateless: the extension does not inject
612
616
 
613
617
  | Family | Surface |
614
618
  | --- | --- |
615
- | `get <what> [selector]` | `text`, `html`, `value`, `attr <name>`, `title`, `url`, `count`, `get box <selector>`, `get styles <selector>`, and `get cdp-url`. |
619
+ | `get title`, `get url`, `get cdp-url` | Read page/browser metadata without a selector. Upstream root help summarizes this family as `get <what> [selector]`, but the selector is not optional for DOM getters. |
620
+ | `get text/html/value/count <selector>` | Read matched elements; use `get text body` for whole-page text. |
621
+ | `get attr <selector> <name>`, `get box <selector>`, `get styles <selector>` | Read an attribute, bounding box, or computed styles from matched elements. |
616
622
  | `is <what> <selector>` | Check `visible`, `enabled`, or `checked`. |
617
623
  | `find <locator> <value> <action> [text]` | Locator types include `role`, `text`, `label`, `placeholder`, `alt`, `title`, and `testid`; selector helpers include `find first <sel>`, `find last <sel>`, and `find nth <n> <sel>`. Role/text filters include `find role <role> --name <name>` and `find ... --exact`. |
618
624
  | `mouse <action> [args]` | `move <x> <y>`, `down [btn]`, `up [btn]`, `wheel <dy> [dx]`. |
@@ -899,14 +905,14 @@ Other useful environment variables include `AGENT_BROWSER_DEFAULT_TIMEOUT`, `AGE
899
905
  <!-- agent-browser-capability-baseline:start capability-token-baseline -->
900
906
  <!-- Generated from scripts/agent-browser-capability-baseline.mjs. Run `npm run docs -- command-reference write` to update. Do not edit manually. -->
901
907
  <details>
902
- <summary>Generated verifier capability baseline for agent-browser 0.31.0</summary>
908
+ <summary>Generated verifier capability baseline for agent-browser 0.31.1</summary>
903
909
 
904
910
  This generated block is review data for maintainers. The human-authored reference sections above remain the readable command guide.
905
911
 
906
912
  #### Source evidence
907
913
  - repository: `vercel-labs/agent-browser`
908
- - upstream HEAD: `5acf7f9dc153cd51dcc6c79e1aebb09c83b2261d`
909
- - upstream package version: `0.31.0`
914
+ - upstream HEAD: `ed2e10598c9064aecfaeb7cf21b540684db4be2c`
915
+ - upstream package version: `0.31.1`
910
916
  - inspected: `agent-browser --version`
911
917
  - inspected: `agent-browser --help`
912
918
  - inspected: `selected agent-browser <command> --help output`
@@ -26,10 +26,10 @@ When upstream ships a new `agent-browser` or the inventory changes:
26
26
 
27
27
  ## Audit result
28
28
 
29
- - Target upstream: `agent-browser 0.31.0` (must match `CAPABILITY_BASELINE.targetVersion` in [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs)).
29
+ - Target upstream: `agent-browser 0.31.1` (must match `CAPABILITY_BASELINE.targetVersion` in [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs)).
30
30
  - Source of truth: `CAPABILITY_BASELINE.inventorySections` in the same file (stable `id` keys: `skills`, `core-commands`, `state-tabs-frames-dialogs`, `network-storage-artifacts-diagnostics`, `batch-auth-setup-ai`, `options-and-env`).
31
- - Status: command-surface supported for the current wrapper contract after the 2026-06-25 0.31.0 audit; 0.31.0 evidence covered the default local gate, command-reference sampling, runtime probes, namespace/session lifecycle review, and restore workflow parser support.
32
- - High-priority support gaps: 2026-05-26 audit found sessionless local commands and command-scoped value flags needed sharper wrapper handling; runtime/tests/docs now cover those paths. The 0.28.0 rebaseline added local `mcp` and `plugin` surfaces plus plugin-backed credential login; wrapper docs/tests mark `mcp` and known `plugin` commands sessionless, with no compatibility shim for older upstream releases. The 0.29.1 rebaseline added upstream `@agent-browser/sandbox` helper-package guidance and stricter `install --with-deps` failure semantics; no new wrapper runtime mode or bundled dependency was required. The 0.30.1 rebaseline fixed upstream `wait --url` glob matching, so constrained `job.assertUrl` delegates glob and exact patterns directly to `wait --url`. The 0.31.0 rebaseline adds restore workflow and namespace/session lifecycle surfaces (`--restore`, restore checks, `--namespace`, `session id`, and `session info`) without adding a wrapper compatibility layer. Prior upstream fixes for click reliability, frame-scoped selectors/waits, form-command fixes, daemon retry improvements, and glibc-pinned release artifacts remain thin passthrough. Remaining upstream-owned caveat: current help still mentions `wait <selector> --state hidden` / `detached` and `find ... uncheck`, but runtime probes show those advertised shapes still fail, so wrapper docs keep `wait --fn` predicates and direct `uncheck` passthrough guidance.
31
+ - Status: command-surface supported for the current wrapper contract after the 2026-06-26 0.31.1 audit; 0.31.1 evidence confirmed no CLI/help/schema drift from 0.31.0 beyond the version string.
32
+ - High-priority support gaps: 2026-05-26 audit found sessionless local commands and command-scoped value flags needed sharper wrapper handling; runtime/tests/docs now cover those paths. The 0.28.0 rebaseline added local `mcp` and `plugin` surfaces plus plugin-backed credential login; wrapper docs/tests mark `mcp` and known `plugin` commands sessionless, with no compatibility shim for older upstream releases. The 0.29.1 rebaseline added upstream `@agent-browser/sandbox` helper-package guidance and stricter `install --with-deps` failure semantics; no new wrapper runtime mode or bundled dependency was required. The 0.30.1 rebaseline fixed upstream `wait --url` glob matching, so constrained `job.assertUrl` delegates glob and exact patterns directly to `wait --url`. The 0.31.0 rebaseline adds restore workflow and namespace/session lifecycle surfaces (`--restore`, restore checks, `--namespace`, `session id`, and `session info`) without adding a wrapper compatibility layer. The 0.31.1 rebaseline fixes upstream React renderer selection for `react tree`, `react inspect`, and `react suspense`; no wrapper runtime change was required. Remaining upstream-owned caveat: current help still mentions `wait <selector> --state hidden` / `detached` and `find ... uncheck`, but runtime probes show those advertised shapes still fail, so wrapper docs keep `wait --fn` predicates and direct `uncheck` passthrough guidance.
33
33
  - Post-`v0.2.29` review state: commits `eb55320` through `86abbfb` add browser guidance/smoke coverage plus `RQ-0086` click-probe reduction, `RQ-0087` same-snapshot form fill batching, `RQ-0088` current-ref fallback on locator misses, `RQ-0089` direct-upstream click mutation investigation, and `RQ-0090` stop-boundary/artifact-path guidance. Verification gates below were rerun on 2026-05-18 after those tasks landed. Constrained `job` (`RQ-0064`), the lightweight `qa` preset (`RQ-0065`), the experimental `sourceLookup` helper (`RQ-0066`), the experimental `networkSourceLookup` helper (`RQ-0067`), optional Exa/Brave-backed `agent_browser_web_search` with Pi-scoped package config (`RQ-0121`), and agent recovery for search/profile configuration failures (`RQ-0122`) are implemented; see [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#job), [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#qa), [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#sourcelookup), [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#networksourcelookup), and [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#optional-companion-web-search). Reusable browser recipes (`RQ-0068`) are intentionally not adopted as a runtime surface; see [`ARCHITECTURE.md`](ARCHITECTURE.md#no-reusable-recipe-layer-yet).
34
34
 
35
35
  ## Open UX/reliability follow-ups from 2026-05-29 agent feedback
@@ -47,23 +47,24 @@ Current summary:
47
47
  | RQ-0129 | Upstream `agent-browser 0.29.1` rebaseline shipped; sandbox helpers are documented upstream package guidance, not a wrapper runtime. | [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md) |
48
48
  | RQ-0130 | Upstream `agent-browser 0.30.1` rebaseline shipped; `wait --url` glob support replaces the wrapper `job.assertUrl` predicate workaround. | [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md) |
49
49
  | RQ-0131 | Upstream `agent-browser 0.31.0` rebaseline shipped; restore workflow and namespace/session lifecycle globals are parsed, documented, and carried through wrapper-managed probes/state. | [`docs/COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#upstream-0310-rebaseline) |
50
+ | RQ-0132 | Upstream `agent-browser 0.31.1` rebaseline shipped; React renderer selection is upstream-fixed for `react tree`, `react inspect`, and `react suspense`, with no wrapper CLI/schema changes. | [`docs/COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#upstream-0311-rebaseline) |
50
51
 
51
52
  ## Verification evidence
52
53
 
53
- Re-run the gates below before each release; this table records what the closure audit exercised. Rows marked current for 0.31.0 were rerun on 2026-06-25; older 0.29.1/Pi 0.79.10 rows remain as prior release/platform evidence until the next full release gate refresh.
54
+ Re-run the gates below before each release; this table records what the closure audit exercised. Rows marked current for 0.31.1 were rerun on 2026-06-26; older 0.29.1/Pi 0.79.10 rows remain as prior release/platform evidence until the next full release gate refresh.
54
55
 
55
56
  | Gate | Evidence | Status |
56
57
  | --- | --- | --- |
57
- | Default local gate | `npm run verify` checks generated playbook drift, clean-builds generated `dist/`, runs `tsc --noEmit`, unit/fake tests, generated command-reference blocks, and live command-reference sampling. | **Current for 0.31.0:** pass on 2026-06-25 (`npm run verify`; unit/fake suite plus live command-reference sampling). **Prior release evidence for 0.29.1:** pass on 2026-06-21 inside `npm run verify -- release`; Pi 0.79.10 refresh passed on 2026-06-22 (`npm run verify`). |
58
+ | Default local gate | `npm run verify` checks generated playbook drift, clean-builds generated `dist/`, runs `tsc --noEmit`, unit/fake tests, generated command-reference blocks, and live command-reference sampling. | **Current for 0.31.1:** pass on 2026-06-26 (`npm run verify`; unit/fake suite plus live command-reference sampling). **Prior release evidence for 0.29.1:** pass on 2026-06-21 inside `npm run verify -- release`; Pi 0.79.10 refresh passed on 2026-06-22 (`npm run verify`). |
58
59
  | Pre-PR local gate | `npm run verify -- pre-pr` composes the default gate with package-content verification. Use before larger local handoffs or PR-ready claims when lifecycle/platform/live dogfood cost is not warranted. | Added 2026-06-10; orchestration is locked by `test/project-verify.test.ts` and does not change release mode. |
59
- | Real upstream contract | `npm run verify -- real-upstream` runs the localhost fixture matrix against the real installed `agent-browser` matching the baseline. | **Current for 0.31.0:** pass on 2026-06-25 (`npm run verify -- real-upstream`; localhost fixture matrix and plugin list probe passed against installed `agent-browser 0.31.0`). This pass depends on skipping immediate helper probes after CSS selector clicks that lack upstream href/navigation fields; enabling those probes reproduced the `get text #status` failure in the real-upstream fixture. |
60
- | Packaged Pi smoke | `npm run verify -- package-pi` validates package contents, loads the packaged `agent_browser` tool without requiring optional Brave config, and executes fake-upstream `--version`. | **Current for 0.29.1:** pass on 2026-06-21 as part of `npm run verify -- release` (`verify-package.mjs --smoke-pi`; packaged `agent_browser --version` invocation passed). **Pi 0.79.10 refresh:** pass on 2026-06-22 (`npm run verify -- package-pi`). |
60
+ | Real upstream contract | `npm run verify -- real-upstream` runs the localhost fixture matrix against the real installed `agent-browser` matching the baseline. | **Current for 0.31.1:** pass on 2026-06-26 (`npm run verify -- real-upstream`; localhost fixture matrix and plugin list probe passed against installed `agent-browser 0.31.1`). This pass depends on skipping immediate helper probes after CSS selector clicks that lack upstream href/navigation fields; enabling those probes reproduced the `get text #status` failure in the real-upstream fixture. |
61
+ | Packaged Pi smoke | `npm run verify -- package-pi` validates package contents, loads the packaged `agent_browser` tool without requiring optional Brave config, and executes fake-upstream `--version`. | **Current for 0.31.1:** pass on 2026-06-26 as part of `npm run verify -- release` (`verify-package.mjs --smoke-pi`; packaged `agent_browser --version` invocation passed). **Pi 0.79.10 refresh:** pass on 2026-06-22 (`npm run verify -- package-pi`). |
61
62
  | Startup profile | `npm run verify -- startup-profile --samples <n>` clean-builds generated `dist/`, records direct package entrypoint import/factory timing in fresh Node processes, and writes `.artifacts/startup-profile/latest.json`. It must not launch Pi, tmux, mise, npm, browsers, or `agent-browser`; full Pi TUI ready-prompt profiling is intentionally excluded after it proved too invasive for routine verification. Run this opt-in evidence when package layout, the compiled entrypoint, top-level imports, schema registration, or prompt/config startup logic changes. | **Current for compiled entrypoint:** pass on 2026-06-21 (`npm run verify -- startup-profile --samples 3`; direct compiled entrypoint import+factory median 47.3 ms, below the 250 ms budget). Full-Pi startup numbers from the unsafe tmux profiler are not accepted as ongoing release evidence. |
62
- | Deterministic dogfood smoke | `npm run verify -- dogfood` (`scripts/verify-agent-browser-dogfood.ts`) drives the native wrapper against a local file fixture through top-level `qa`, `semanticAction`, constrained `job`, screenshot artifact verification, and session close with the real `agent-browser` on `PATH`. | **Current for 0.29.1:** pass on 2026-06-21 (`npm run verify -- dogfood`; `qa-url`, fresh/current opens, semantic click, job screenshot artifact verification, and close all passed). |
63
+ | Deterministic dogfood smoke | `npm run verify -- dogfood` (`scripts/verify-agent-browser-dogfood.ts`) drives the native wrapper against a local file fixture through top-level `qa`, `semanticAction`, constrained `job`, screenshot artifact verification, and session close with the real `agent-browser` on `PATH`. | **Current for 0.31.1:** pass on 2026-06-26 (`npm run verify -- dogfood`; `qa-url`, fresh/current opens, semantic click, URL follow-up, job screenshot artifact verification, and close all passed). |
63
64
  | Efficiency benchmark | `npm run verify -- benchmark` runs deterministic browser workflow accounting plus focused benchmark tests, including JSONL sampling fixtures and job/qa/sourceLookup/networkSourceLookup/Electron scenario coverage. | **Current:** pass on 2026-06-21 (`npm run verify -- benchmark`; 13/13 deterministic scenarios passed). |
64
- | Crabbox platform smoke | `npm run check:platform-smoke` syntax-checks the harness and cheap invariants. `npm run smoke:platform:ubuntu-image` builds the project-owned Linux image, `npm run smoke:platform:doctor` checks Crabbox 0.26.0+ and local target readiness, and `npm run smoke:platform:all` runs doctor first, then fast target-local `platform-build` (`npm run verify -- platform-target`, pack, clean Pi install) plus `browser-dogfood-smoke` on Crabbox `macos`, `ubuntu`, and `windows-native`; see [`platform-smoke.md`](platform-smoke.md). Target artifacts include Crabbox/provider/work-root metadata, and release review also checks provider-specific `crabbox list` commands for leftover leases/clones. | **Current for 0.29.1:** pass on 2026-06-21 inside `npm run verify -- release`; rebuilt Ubuntu image `pi-agent-browser-native-platform:node24-agent-browser0.29.1`, refreshed the Windows `crabbox-ready` template snapshot to `agent-browser 0.29.1`, doctor passed, then Crabbox platform smoke passed for macOS, Ubuntu, and native Windows. **Pi 0.79.10 refresh:** pass on 2026-06-22 (`npm run check:platform-smoke`, `npm run smoke:platform:doctor`, `npm run smoke:platform:all`). |
65
- | `verify -- release` / `prepublishOnly` | `npm run verify -- release` chains the default gate with the configured-source lifecycle harness, packaged Pi smoke, and the release-blocking Crabbox platform matrix (`verifySteps` `release` in [`scripts/project.mjs`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/scripts/project.mjs)). `package.json` `prepublishOnly` runs that compose before `npm pack --dry-run` during `npm publish`. It intentionally omits standalone real-upstream, host-only dogfood, and benchmark modes—see [`RELEASE.md`](RELEASE.md#pre-release-checks). | **Current for 0.29.1 / Pi 0.79.10:** pass on 2026-06-22 (`npm run verify -- release`), including default unit/fake gate, generated docs checks, live command-reference sampling, lifecycle harness, packaged Pi smoke, and macOS/Ubuntu/native-Windows Crabbox platform smoke. |
66
- | Configured-source lifecycle | `npm run verify -- lifecycle` (`scripts/verify-lifecycle.mjs`) drives `/reload`, closes and relaunches Pi with the same exact `--session-id`, checks the JSONL session header id, session continuity, slash-command sentinel tokens (`v1` before reload and `v2` after full relaunch because compiled JS package modules are process-cached), persisted spill reachability, and real Pi `tool_result` failure-patch semantics for a QA reclassification with a fake upstream on `PATH`. Default Pi model is `zai/glm-5.2`; default per-step wait is **180000 ms** (`DEFAULT_TIMEOUT_MS`); override model with `--model <id>` and waits with `--timeout-ms <ms>`. Passthrough flags in [`scripts/project.mjs`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/scripts/project.mjs): `--keep-artifacts`, `--model`, `--verbose`, and `--timeout-ms` plus a value (for example `npm run verify -- lifecycle --model openai-codex/gpt-5.5:minimal --keep-artifacts --verbose --timeout-ms 600000`). | **Current for 0.29.1:** pass on 2026-06-21 as part of `npm run verify -- release`; managed browser session continuity and persisted full output verified before cleanup. **Pi 0.79.10 refresh:** pass on 2026-06-22 (`npm run verify -- lifecycle`; managed browser session and persisted full output verified before cleanup). |
65
+ | Crabbox platform smoke | `npm run check:platform-smoke` syntax-checks the harness and cheap invariants. `npm run smoke:platform:ubuntu-image` builds the project-owned Linux image, `npm run smoke:platform:doctor` checks Crabbox 0.26.0+ and local target readiness, and `npm run smoke:platform:all` runs doctor first, then fast target-local `platform-build` (`npm run verify -- platform-target`, pack, clean Pi install) plus `browser-dogfood-smoke` on Crabbox `macos`, `ubuntu`, and `windows-native`; see [`platform-smoke.md`](platform-smoke.md). Target artifacts include Crabbox/provider/work-root metadata, and release review also checks provider-specific `crabbox list` commands for leftover leases/clones. | **Current for 0.31.1:** pass on 2026-06-26 inside `npm run verify -- release`; rebuilt Ubuntu image `pi-agent-browser-native-platform:node24-agent-browser0.31.1`, refreshed the Windows `crabbox-ready` template snapshot to `agent-browser 0.31.1`, doctor passed, then Crabbox platform smoke passed for macOS, Ubuntu, and native Windows. **Pi 0.79.10 refresh:** pass on 2026-06-22 (`npm run check:platform-smoke`, `npm run smoke:platform:doctor`, `npm run smoke:platform:all`). |
66
+ | `verify -- release` / `prepublishOnly` | `npm run verify -- release` chains the default gate with the configured-source lifecycle harness, packaged Pi smoke, and the release-blocking Crabbox platform matrix (`verifySteps` `release` in [`scripts/project.mjs`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/scripts/project.mjs)). `package.json` `prepublishOnly` runs that compose before `npm pack --dry-run` during `npm publish`. It intentionally omits standalone real-upstream, host-only dogfood, and benchmark modes—see [`RELEASE.md`](RELEASE.md#pre-release-checks). | **Current for 0.31.1:** pass on 2026-06-26 (`npm run verify -- release`), including default unit/fake gate, generated docs checks, live command-reference sampling, lifecycle harness, packaged Pi smoke, and macOS/Ubuntu/native-Windows Crabbox platform smoke. |
67
+ | Configured-source lifecycle | `npm run verify -- lifecycle` (`scripts/verify-lifecycle.mjs`) drives `/reload`, closes and relaunches Pi with the same exact `--session-id`, checks the JSONL session header id, session continuity, slash-command sentinel tokens (`v1` before reload and `v2` after full relaunch because compiled JS package modules are process-cached), persisted spill reachability, and real Pi `tool_result` failure-patch semantics for a QA reclassification with a fake upstream on `PATH`. Default Pi model is `zai/glm-5.2`; default per-step wait is **180000 ms** (`DEFAULT_TIMEOUT_MS`); override model with `--model <id>` and waits with `--timeout-ms <ms>`. Passthrough flags in [`scripts/project.mjs`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/scripts/project.mjs): `--keep-artifacts`, `--model`, `--verbose`, and `--timeout-ms` plus a value (for example `npm run verify -- lifecycle --model openai-codex/gpt-5.5:minimal --keep-artifacts --verbose --timeout-ms 600000`). | **Current for 0.31.1:** pass on 2026-06-26 as part of `npm run verify -- release`; managed browser session continuity and persisted full output verified before cleanup. **Pi 0.79.10 refresh:** pass on 2026-06-22 (`npm run verify -- lifecycle`; managed browser session and persisted full output verified before cleanup). |
67
68
  | Quick isolated Pi smoke | `pi --approve --no-extensions --no-skills -e . --tools agent_browser` from trusted repo root; native `agent_browser` only. | **Current for 0.29.1 / Pi 0.79.9:** pass on 2026-06-21 via tmux with `pi --approve --no-extensions --no-skills -e . --model openai-codex/gpt-5.5:minimal --tools agent_browser`. Covered the public Sauce Demo checkout-overview flow with clean context, native sorting/click/fill flow, screenshot and recording evidence, console/page-error/network diagnostics, and no order placement. A one-line screenshot-plus-recording close-guard smoke on `https://example.com` passed after rebuilding `dist/`, proving close succeeds after both artifact paths are verified. Temp artifacts and tmux sessions were cleaned after evidence capture. |
68
69
 
69
70
  Runtime floor note: package metadata keeps Pi core package peer ranges wildcard per installed Pi package docs, but `pi-agent-browser-doctor` / `npm run doctor` treats `pi --version` below 0.79.10 as a setup failure. This keeps package dependency shape aligned with Pi package loading while still making unsupported host Pi versions a release and first-run blocker.
@@ -155,7 +155,7 @@ The extension always plans normal browser commands with `--json` prepended in `e
155
155
  - For first-navigation setup, use open without a URL plus network route --resource-type <csv>, cookies set --curl <file>, or --init-script/--enable before navigate/opening the target page.
156
156
  - For stateful browser context work, prefer purpose-specific page actions before dumping browser data: use auth save --password-stdin with the tool stdin field for credentials, auth list/show/delete/remove for local auth-profile maintenance, auth login when you need the browser to fill a saved profile, state save/load for portable test state, state list/show/rename/clear/clear -a/clean for saved-state lifecycle cleanup, cookies get/set/clear and storage local|session only when the task needs those values, and expect cookie/storage/auth/state summaries to redact credential-like fields while allowing benign primitive storage values when useful for local QA.
157
157
  - For batch chains that touch cookies, storage, auth, or other secret-bearing commands, use details.batchSteps for per-step artifacts, categories, spill paths, and full structured errors; top-level details.data on batch is only a compact redacted step matrix (success, argv-redacted command, redacted result or scrubbed error text) built from the same presentation rules as standalone calls.
158
- - For non-core families, pass current upstream commands through the native tool directly: network route/requests/har (including request filters like --type/--method/--status), diff snapshot/screenshot/url with scoped/baseline options, trace/profiler/record, console/errors/highlight/inspect/clipboard, stream enable/disable/status, dashboard start/stop, device list for iOS simulator inventory, and chat. For compact network requests output, prefer details.nextActions for request detail, route-mock diagnostics, actionable failed-request networkSourceLookup, filtering, clearing the aggregate buffer before repro, or HAR capture follow-ups instead of guessing request-id syntax. Artifact-producing commands report details.artifacts and verification state; long-running starts such as stream, dashboard, trace/profiler, and record should be paired with the matching stop/disable command when the task is done; stream enable already-enabled outcomes are treated as idempotent success with status/disable follow-ups.
158
+ - For non-core families, pass current upstream commands through the native tool directly: network requests, network route <url>, network har start/stop [path], diff snapshot, diff screenshot --baseline <file>, diff url <u1> <u2>, trace start, trace stop [path], profiler start, profiler stop [path], record start <path>, record stop, console/errors [--clear], highlight <selector>, inspect, clipboard read, clipboard write <text>, clipboard copy/paste, stream enable/disable/status, dashboard start/stop, device list for iOS simulator inventory, and chat <message>. For compact network requests output, prefer details.nextActions for request detail, route-mock diagnostics, actionable failed-request networkSourceLookup, filtering, clearing the aggregate buffer before repro, or HAR capture follow-ups instead of guessing request-id syntax. Artifact-producing commands report details.artifacts and verification state; long-running starts such as stream, dashboard, trace/profiler, and record should be paired with the matching stop/disable command when the task is done; stream enable already-enabled outcomes are treated as idempotent success with status/disable follow-ups.
159
159
  - For Electron desktop apps, prefer top-level electron for wrapper-owned discovery, isolated launch, status, compact probe, and cleanup: list first, treat likely-sensitive annotations as hints rather than enforcement, launch with the default snapshot handoff unless handoff: "tabs" is the safer diagnostic starting point, use electron.probe or snapshot -i/qa.attached for current-session state, and always cleanup the returned launchId when done. electron.launch uses an isolated temporary profile; it does not reuse the app's normal signed-in profile or attach to an already-running authenticated app. For signed-in local app state, host-launch the normal app with --remote-debugging-port when appropriate, then use raw args connect <port|url>; after connect, inspect tab list, select the stable tab id such as tab t2, then run a condition wait or snapshot -i before using refs. close commands (`close`, `quit`, or `exit`) only close the browser/CDP session; leave manually launched app shutdown, profile cleanup, and explicit artifacts to the host owner.
160
160
  - For provider or specialized app workflows, load version-matched upstream guidance with skills get agentcore|electron|slack|dogfood|vercel-sandbox through the native tool; add --full when you need references/templates, and use skills get --all only for broad skill audits. Hosted sandbox workflows should use upstream @agent-browser/sandbox helpers outside this wrapper. Provider launches such as -p ios, --provider browserbase/kernel/browseruse/browserless/agentcore, and iOS --device are upstream-owned setup paths; use sessionMode fresh when switching providers and expect external credentials or local Appium/Xcode setup to be required.
161
161
  - For dialogs and frames, use dialog status/accept/dismiss and frame <selector|main> through native args; dialog commands and eval snippets that look like alert/confirm/prompt/dialog triggers are shorter-bounded than normal browser calls, and timed-out dialog-like interactions may add inspect-dialog-after-timeout, dismiss-dialog-after-timeout, or recover-fresh-session-after-dialog-timeout nextActions. When --confirm-actions produces a pending confirmation, use details.nextActions or exact confirm <id> / deny <id> calls instead of inventing ids.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-agent-browser-native",
3
- "version": "0.2.62",
3
+ "version": "0.2.64",
4
4
  "description": "pi extension that exposes agent-browser as a native tool for browser automation",
5
5
  "type": "module",
6
6
  "author": "Mitch Fultz (https://github.com/fitchmultz)",
@@ -14,8 +14,8 @@ export const COMMAND_REFERENCE_BASELINE_BLOCK_IDS = Object.freeze(["upstream-bas
14
14
 
15
15
  const sourceEvidence = Object.freeze({
16
16
  repository: "vercel-labs/agent-browser",
17
- upstreamHead: "5acf7f9dc153cd51dcc6c79e1aebb09c83b2261d",
18
- upstreamPackageVersion: "0.31.0",
17
+ upstreamHead: "ed2e10598c9064aecfaeb7cf21b540684db4be2c",
18
+ upstreamPackageVersion: "0.31.1",
19
19
  inspectedSources: Object.freeze([
20
20
  "agent-browser --version",
21
21
  "agent-browser --help",
@@ -774,7 +774,7 @@ const inventorySections = Object.freeze([
774
774
  ]);
775
775
 
776
776
  export const CAPABILITY_BASELINE = Object.freeze({
777
- targetVersion: "0.31.0",
777
+ targetVersion: "0.31.1",
778
778
  sourceEvidence,
779
779
  helpCommands,
780
780
  inventorySections,
@@ -16,14 +16,23 @@ function Write-Section($Name, $Path) {
16
16
  Write-Output "--- $Name END ---"
17
17
  }
18
18
 
19
- function Get-AgentBrowserVersion() {
20
- if (-not (Get-Command agent-browser -ErrorAction SilentlyContinue)) { return "" }
21
- return (& agent-browser --version 2>$null)
19
+ function Get-AgentBrowserCommandPath() {
20
+ foreach ($Name in @("agent-browser.cmd", "agent-browser.exe", "agent-browser")) {
21
+ $Command = Get-Command $Name -ErrorAction SilentlyContinue | Select-Object -First 1
22
+ if ($Command) { return $Command.Source }
23
+ }
24
+ return ""
25
+ }
26
+
27
+ function Get-AgentBrowserVersion($AgentBrowserPath) {
28
+ if (-not $AgentBrowserPath) { return "" }
29
+ return (& $AgentBrowserPath --version 2>$null)
22
30
  }
23
31
 
24
- function Test-AgentBrowser($Version) {
32
+ function Test-AgentBrowser($Version, $AgentBrowserPath) {
25
33
  $Expected = "agent-browser $Version"
26
- $Current = Get-AgentBrowserVersion
34
+ $Current = Get-AgentBrowserVersion $AgentBrowserPath
35
+ Write-Output "PLATFORM_AGENT_BROWSER_PATH=$AgentBrowserPath"
27
36
  Write-Output "PLATFORM_AGENT_BROWSER_VERSION=$Current"
28
37
  $script:AgentBrowserReadyExit = if ($Current -eq $Expected) { 0 } else { 1 }
29
38
  }
@@ -46,6 +55,34 @@ function Test-AgentBrowserBrowserCache() {
46
55
  $script:BrowserCacheExit = 1
47
56
  }
48
57
 
58
+ function Invoke-AgentBrowserWithTimeout($AgentBrowserPath, [string[]]$Arguments, [int]$TimeoutSeconds) {
59
+ $script:LastAgentBrowserCommandExit = 1
60
+ if (-not $script:AgentBrowserCommandCounter) { $script:AgentBrowserCommandCounter = 0 }
61
+ $script:AgentBrowserCommandCounter += 1
62
+ $OutPath = Join-Path $DogfoodDir ("agent-browser-{0}.stdout.txt" -f $script:AgentBrowserCommandCounter)
63
+ $ErrPath = Join-Path $DogfoodDir ("agent-browser-{0}.stderr.txt" -f $script:AgentBrowserCommandCounter)
64
+ $Process = Start-Process -FilePath $AgentBrowserPath -ArgumentList $Arguments -RedirectStandardOutput $OutPath -RedirectStandardError $ErrPath -PassThru -WindowStyle Hidden
65
+
66
+ $TimedOut = -not $Process.WaitForExit($TimeoutSeconds * 1000)
67
+ if ($TimedOut) {
68
+ & taskkill.exe /PID $Process.Id /T /F 2>$null | Out-Null
69
+ Write-Output "PLATFORM_AGENT_BROWSER_COMMAND_TIMEOUT=${TimeoutSeconds}s args=$($Arguments -join ' ')"
70
+ $script:LastAgentBrowserCommandExit = 124
71
+ }
72
+
73
+ $StdoutText = if (Test-Path $OutPath) { Get-Content -Raw $OutPath } else { "" }
74
+ $StderrText = if (Test-Path $ErrPath) { Get-Content -Raw $ErrPath } else { "" }
75
+ if (-not $TimedOut) {
76
+ if ($null -ne $Process.ExitCode) { $script:LastAgentBrowserCommandExit = $Process.ExitCode }
77
+ elseif ($StdoutText -match '"success"\s*:\s*true') { $script:LastAgentBrowserCommandExit = 0 }
78
+ else { $script:LastAgentBrowserCommandExit = 1 }
79
+ }
80
+
81
+ if ($StdoutText) { Write-Output $StdoutText }
82
+ if ($StderrText) { Write-Output $StderrText }
83
+ Write-Output "PLATFORM_AGENT_BROWSER_COMMAND_EXIT=$($script:LastAgentBrowserCommandExit)"
84
+ }
85
+
49
86
  Write-Output "Starting browser-dogfood-smoke in $SourceRoot at $((Get-Date).ToUniversalTime().ToString('o'))"
50
87
  Write-Output "PLATFORM_RUN_ROOT=$RunRoot"
51
88
  Write-Output "PLATFORM_DOGFOOD_ARTIFACT_DIR=$DogfoodArtifactDir"
@@ -57,8 +94,9 @@ Write-Output "PLATFORM_NODE_VERSION=$NodeVersion"
57
94
  $NpmCiExit = $LASTEXITCODE
58
95
  Write-Output "PLATFORM_NPM_CI_EXIT=$NpmCiExit"
59
96
 
97
+ $AgentBrowserPath = Get-AgentBrowserCommandPath
60
98
  $script:AgentBrowserReadyExit = 1
61
- Test-AgentBrowser $AgentBrowserVersion
99
+ Test-AgentBrowser $AgentBrowserVersion $AgentBrowserPath
62
100
  $AgentBrowserExit = $script:AgentBrowserReadyExit
63
101
  Write-Output "PLATFORM_AGENT_BROWSER_READY_EXIT=$AgentBrowserExit"
64
102
  $script:BrowserCacheExit = 1
@@ -72,10 +110,15 @@ if ($BrowserCacheExit -eq 0) {
72
110
  $PrewarmUrl = "file:///" + ($PrewarmPath -replace "\\", "/")
73
111
  for ($Attempt = 1; $Attempt -le 3; $Attempt++) {
74
112
  Write-Output "PLATFORM_AGENT_BROWSER_PREWARM_ATTEMPT=$Attempt"
75
- & agent-browser open --json --session "platform-smoke-prewarm-$Attempt" $PrewarmUrl 2>&1
76
- $BrowserPrewarmExit = $LASTEXITCODE
77
- & agent-browser close --json --session "platform-smoke-prewarm-$Attempt" 2>&1
78
- if ($BrowserPrewarmExit -eq 0) { break }
113
+ $PrewarmSession = "platform-smoke-prewarm-$Attempt"
114
+ Invoke-AgentBrowserWithTimeout $AgentBrowserPath @("open", "--json", "--session", $PrewarmSession, $PrewarmUrl) 45
115
+ $BrowserPrewarmExit = $script:LastAgentBrowserCommandExit
116
+ if ($BrowserPrewarmExit -eq 0) {
117
+ Invoke-AgentBrowserWithTimeout $AgentBrowserPath @("close", "--json", "--session", $PrewarmSession) 15
118
+ $CloseExit = $script:LastAgentBrowserCommandExit
119
+ Write-Output "PLATFORM_AGENT_BROWSER_PREWARM_CLOSE_EXIT=$CloseExit"
120
+ break
121
+ }
79
122
  Start-Sleep -Seconds 2
80
123
  }
81
124
  }
@@ -5,6 +5,7 @@ import { accessSync, constants, mkdirSync, unlinkSync, writeFileSync } from "nod
5
5
  import { resolve } from "node:path";
6
6
 
7
7
  import { CAPABILITY_BASELINE } from "../agent-browser-capability-baseline.mjs";
8
+ import { buildTargetBaseArgs } from "./crabbox-runner.mjs";
8
9
 
9
10
  const DEFAULT_UBUNTU_IMAGE = `pi-agent-browser-native-platform:node24-agent-browser${CAPABILITY_BASELINE.targetVersion}`;
10
11
 
@@ -155,6 +156,69 @@ function checkCrabboxProvider(cbox, args, label, failures) {
155
156
  }
156
157
  }
157
158
 
159
+ function crabbox(cbox, args, timeout = 300_000) {
160
+ try {
161
+ return {
162
+ ok: true,
163
+ stdout: execFileSync(cbox, args, { timeout, stdio: "pipe", env: { ...process.env, CRABBOX_SYNC_GIT_SEED: "false" } }).toString(),
164
+ stderr: "",
165
+ };
166
+ } catch (error) {
167
+ return {
168
+ ok: false,
169
+ stdout: error.stdout?.toString?.() ?? "",
170
+ stderr: error.stderr?.toString?.() ?? error.message,
171
+ };
172
+ }
173
+ }
174
+
175
+ function parseLeaseId(text) {
176
+ return text.match(/\bleased\s+(\S+)/)?.[1]
177
+ ?? text.match(/\blease=(\S+)/)?.[1]
178
+ ?? null;
179
+ }
180
+
181
+ export function disposableWindowsAgentBrowserProbe(cbox, config, expectedVersion) {
182
+ const slug = "piab-doctor-agent-browser";
183
+ const baseArgs = buildTargetBaseArgs("windows-native", config);
184
+ const warm = crabbox(cbox, ["warmup", ...baseArgs, "--slug", slug, "--keep", "--reclaim"], 300_000);
185
+ const leaseId = parseLeaseId(`${warm.stdout}\n${warm.stderr}`) ?? slug;
186
+ if (!warm.ok) return { ok: false, message: `warmup failed: ${(warm.stderr || warm.stdout).slice(-500)}` };
187
+
188
+ let outcome;
189
+ try {
190
+ const probeScript = `$ErrorActionPreference = "Stop"
191
+ $cmd = Get-Command "agent-browser.cmd" -ErrorAction SilentlyContinue | Select-Object -First 1
192
+ if (-not $cmd) { throw "agent-browser.cmd missing" }
193
+ $version = & $cmd.Source --version
194
+ Write-Output "PLATFORM_DOCTOR_AGENT_BROWSER_PATH=$($cmd.Source)"
195
+ Write-Output "PLATFORM_DOCTOR_AGENT_BROWSER_VERSION=$version"
196
+ $roots = @((Join-Path $env:USERPROFILE ".agent-browser\\browsers"), "C:\\WINDOWS\\system32\\config\\systemprofile\\.agent-browser\\browsers")
197
+ $chrome = Get-ChildItem -Path $roots -Recurse -Filter chrome.exe -ErrorAction SilentlyContinue | Select-Object -First 1
198
+ if (-not $chrome) { throw "agent-browser browser cache missing chrome.exe" }
199
+ Write-Output "PLATFORM_DOCTOR_AGENT_BROWSER_CHROME=$($chrome.FullName)"`;
200
+ const probeCommand = `powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -EncodedCommand ${Buffer.from(probeScript, "utf16le").toString("base64")}`;
201
+ const run = crabbox(cbox, ["run", ...baseArgs, "--id", leaseId, "--no-sync", "--shell", probeCommand], 180_000);
202
+ if (!run.ok) outcome = { ok: false, message: `probe failed: ${(run.stderr || run.stdout).slice(-700)}` };
203
+ else {
204
+ const output = run.stdout;
205
+ const versionLine = output.match(/^PLATFORM_DOCTOR_AGENT_BROWSER_VERSION=(.*)$/m)?.[1]?.trim() ?? "";
206
+ const pathLine = output.match(/^PLATFORM_DOCTOR_AGENT_BROWSER_PATH=(.*)$/m)?.[1]?.trim() ?? "";
207
+ const chromeLine = output.match(/^PLATFORM_DOCTOR_AGENT_BROWSER_CHROME=(.*)$/m)?.[1]?.trim() ?? "";
208
+ if (versionLine !== `agent-browser ${expectedVersion}`) outcome = { ok: false, message: `expected agent-browser ${expectedVersion}, got ${versionLine || "missing version"}` };
209
+ else if (!pathLine || !chromeLine) outcome = { ok: false, message: "agent-browser path or browser cache marker missing" };
210
+ else outcome = { ok: true, message: `${versionLine} | ${pathLine} | ${chromeLine}` };
211
+ }
212
+ } finally {
213
+ const stop = crabbox(cbox, ["stop", ...baseArgs, "--id", leaseId], 90_000);
214
+ if (!stop.ok) {
215
+ const prior = outcome?.ok === false ? `; prior result: ${outcome.message}` : "";
216
+ outcome = { ok: false, message: `cleanup failed: ${(stop.stderr || stop.stdout).slice(-500)}${prior}` };
217
+ }
218
+ }
219
+ return outcome;
220
+ }
221
+
158
222
  function checkAgentBrowserVersion(expectedVersion, failures, command = "agent-browser") {
159
223
  const version = shell(`${command} --version`);
160
224
  if (!version) {
@@ -289,6 +353,9 @@ export async function runDoctor(config) {
289
353
  fail(`snapshot ${snapshot} not found on ${vmName}`, failures);
290
354
  }
291
355
  checkCrabboxProvider(cbox, ["--provider", "parallels", "--target", "windows", "--windows-mode", "normal", "--parallels-source", vmName, "--parallels-source-snapshot", snapshot, "--parallels-user", user, "--parallels-work-root", workRoot], "windows parallels", failures);
356
+ const agentBrowserProbe = disposableWindowsAgentBrowserProbe(cbox, { ...config, windowsParallels: { ...config?.windowsParallels, sourceVm: vmName, snapshot, user, workRoot } }, agentBrowserVersion);
357
+ if (agentBrowserProbe.ok) ok(`Windows disposable agent-browser: ${agentBrowserProbe.message}`);
358
+ else fail(`Windows disposable agent-browser probe failed: ${agentBrowserProbe.message}`, failures);
292
359
  }
293
360
  }
294
361
  } else {
@@ -497,8 +497,10 @@ export async function runTargetSuites(config, targetName, suiteNames) {
497
497
  try {
498
498
  let sync = true;
499
499
  for (const suiteName of suiteNames) {
500
+ console.log(` Suite: ${suiteName}`);
500
501
  const result = await runTargetSuite(config, targetName, suiteName, { ...lease, sync }, runId);
501
502
  results.push(result);
503
+ console.log(` ${result.ok ? "PASS" : "FAIL"} ${suiteName} on ${targetName}`);
502
504
  sync = false;
503
505
  if (!result.ok) break;
504
506
  }
@@ -123,7 +123,7 @@ export async function main(argv = process.argv.slice(2)) {
123
123
  }
124
124
 
125
125
  if (args.command === "run") {
126
- const { runTargetSuite, runTargetSuites } = await import("./platform-smoke/targets.mjs");
126
+ const { runTargetSuites } = await import("./platform-smoke/targets.mjs");
127
127
  const targets = args.target ? args.target.split(",").map((name) => name.trim()).filter(Boolean) : config.requiredTargets;
128
128
  const suites = args.suite ? [args.suite] : config.requiredSuites;
129
129
  const supportedTargets = config.supportedTargets ?? config.requiredTargets;
@@ -131,9 +131,7 @@ export async function main(argv = process.argv.slice(2)) {
131
131
  validateNames("suite", suites, config.requiredSuites);
132
132
  const runs = targets.map(async (targetName) => {
133
133
  console.log(`\n=== Target: ${targetName} ===`);
134
- const result = args.suite
135
- ? await runTargetSuite(config, targetName, suites[0])
136
- : await runTargetSuites(config, targetName, suites);
134
+ const result = await runTargetSuites(config, targetName, suites);
137
135
  return { targetName, result };
138
136
  });
139
137
  const results = await Promise.all(runs);