pi-agent-browser-native 0.6.17 → 0.7.1
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 +19 -0
- package/README.md +55 -167
- package/dist/extensions/agent-browser/index.js +312 -223
- package/dist/extensions/agent-browser/lib/browser-transcript.js +33 -0
- package/dist/extensions/agent-browser/lib/execution-cwd.js +4 -2
- package/dist/extensions/agent-browser/lib/input-modes/job.js +2 -213
- package/dist/extensions/agent-browser/lib/input-modes/params.js +146 -142
- package/dist/extensions/agent-browser/lib/input-modes/script.js +64 -92
- package/dist/extensions/agent-browser/lib/managed-session-policy-lock.js +170 -24
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +13 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +26 -13
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +21 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +4 -2
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +1 -3
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +35 -20
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery.js +3 -1
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-observation.js +79 -0
- package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +3 -4
- package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +19 -52
- package/dist/extensions/agent-browser/lib/orchestration/native-session-defaults.js +3 -3
- package/dist/extensions/agent-browser/lib/orchestration/output-file.js +3 -3
- package/dist/extensions/agent-browser/lib/orchestration/script-mode.js +91 -278
- package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +9 -9
- package/dist/extensions/agent-browser/lib/playbook.js +46 -25
- package/dist/extensions/agent-browser/lib/process-identity.js +22 -6
- package/dist/extensions/agent-browser/lib/process.js +16 -13
- package/dist/extensions/agent-browser/lib/results/action-recommendations.js +2 -2
- package/dist/extensions/agent-browser/lib/results/next-actions.js +1 -2
- package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +25 -4
- package/dist/extensions/agent-browser/lib/results/presentation/batch.js +6 -2
- package/dist/extensions/agent-browser/lib/results/presentation/common.js +2 -0
- package/dist/extensions/agent-browser/lib/results/presentation/content.js +39 -0
- package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +3 -3
- package/dist/extensions/agent-browser/lib/results/presentation/large-output.js +41 -1
- package/dist/extensions/agent-browser/lib/results/presentation.js +16 -11
- package/dist/extensions/agent-browser/lib/runtime.js +18 -6
- package/dist/extensions/agent-browser/lib/session-page-state.js +3 -4
- package/dist/extensions/agent-browser/lib/tool-surface.js +138 -0
- package/dist/extensions/agent-browser/script-worker.js +4 -1
- package/docs/ARCHITECTURE.md +46 -62
- package/docs/COMMAND_REFERENCE.md +77 -136
- package/docs/ELECTRON.md +51 -49
- package/docs/RELEASE.md +35 -21
- package/docs/REQUIREMENTS.md +18 -14
- package/docs/SUPPORT_MATRIX.md +33 -15
- package/docs/TOOL_CONTRACT.md +216 -405
- package/docs/platform-smoke.md +2 -2
- package/package.json +1 -1
- package/scripts/doctor.mjs +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.1 - 2026-09-22
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Defer the native replay helper import until awaited session restoration, preserving fast package registration and the complete restored tool surface. Public browser commands and saved-session behavior remain unchanged.
|
|
8
|
+
|
|
9
|
+
## 0.7.0 - 2026-09-22
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Keep `agent_browser` focused on native commands and batches. Replace its `script` input with `agent_browser_code`, whose fresh JavaScript context controls the same persistent browser and authentication as direct calls.
|
|
14
|
+
- Replace the `job` DSL with native batch/code. Move actions, QA, Electron, and source lookups to five flat tools discovered through `agent_browser_tools`; activation uses Pi's native additive tool history.
|
|
15
|
+
- Return bounded browser observations with exact recovery actions and explicit JSON/image selection from code. Report measured screenshot pixel/CSS geometry and unknown mappings without guessing coordinates.
|
|
16
|
+
- Coordinate cooperating Pi processes across complete helper/action operations and whole code calls. Persist ordered browser-state transitions so interrupted code and branch replay retain truthful page/ref state.
|
|
17
|
+
- Preserve the captured execution directory across queued direct/code calls while browser/configuration and recording ownership remain anchored.
|
|
18
|
+
- Require Pi 0.87.0 and compose browser guidance through native prompt sections. Keep upstream `agent-browser` separately installed.
|
|
19
|
+
|
|
20
|
+
See the [migration guide](docs/TOOL_CONTRACT.md#07-migration). Restart participating Pi processes after upgrading; mixed package versions do not share the new coordination guarantee.
|
|
21
|
+
|
|
3
22
|
## 0.6.17 - 2026-09-22
|
|
4
23
|
|
|
5
24
|
### Fixed
|
package/README.md
CHANGED
|
@@ -42,10 +42,10 @@ The agent gets a native tool, not a bash workaround:
|
|
|
42
42
|
```json
|
|
43
43
|
{ "args": ["open", "https://react.dev"] }
|
|
44
44
|
{ "args": ["snapshot", "-i"] }
|
|
45
|
-
{ "
|
|
45
|
+
{ "args": ["find", "text", "Learn React", "click"] }
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
Use native commands for individual actions, `batch --bail` for fixed sequences, and `agent_browser_code` for loops or branches. Specialized tools are available through `agent_browser_tools`; see [common calls](#common-agent-calls).
|
|
49
49
|
|
|
50
50
|
The result is optimized for agent work:
|
|
51
51
|
|
|
@@ -81,28 +81,28 @@ The result is optimized for agent work:
|
|
|
81
81
|
|
|
82
82
|
| Pain | Native wrapper capability | Proof surface |
|
|
83
83
|
|---|---|---|
|
|
84
|
-
| Agents build fragile shell commands or repeat browser calls for loops and branches | Exposes `agent_browser`
|
|
84
|
+
| Agents build fragile shell commands or repeat browser calls for loops and branches | Exposes compact `agent_browser` for native commands and batch, `agent_browser_code` for fresh JavaScript against the same persistent browser, and discoverable action, QA, Electron, and source tools | `extensions/agent-browser/index.ts`, `extensions/agent-browser/lib/input-modes/`, [`docs/TOOL_CONTRACT.md`](docs/TOOL_CONTRACT.md) |
|
|
85
85
|
| Page snapshots are too large or viewport-blind | Shows compact, main-content-first summaries, surfaces an `Omitted high-value controls` section (plus `details.data.highValueControlRefIds`) when dense pages or desktop host screens hide editables, named surfaces/tabs, primary action buttons, and high-signal named links such as repository results from the trimmed ref lists, supports wrapper-side `snapshot -i --search <text>` / `--filter role=<role>` to trim dense pages while preserving full `details.refSnapshot`, supports `snapshot --viewport` for scroll/viewport metadata, supports `snapshot --diff` for quick ref-map deltas versus the prior tracked snapshot, and stores full redacted output in spill files when needed | `extensions/agent-browser/lib/results/snapshot.ts`, `extensions/agent-browser/lib/orchestration/browser-run/prepare.ts`, `test/agent-browser.presentation.test.ts`, `test/agent-browser.extension-validation.test.ts` |
|
|
86
86
|
| Screenshots/downloads get lost in text | Normalizes artifact paths, creates missing parent directories, leaves click/download execution to native download, and reports existence, size, cwd, session, and repair status | [`docs/COMMAND_REFERENCE.md`](docs/COMMAND_REFERENCE.md#download-screenshot-and-pdf-files) |
|
|
87
87
|
| Profile restores and tab drift confuse agents | Tracks managed sessions, keeps every upstream helper probe on the same idle-timeout launch configuration so the background browser is not restarted between a snapshot and action, re-selects target tabs after observed drift, live-verifies the active target and refreshes its title after successful tab selection or `tab close` (while retaining deliberate `about:blank` selections and post-close blank targets), rehydrates branch-backed session state on Pi session-tree changes, and pins later commands only for sessions with drift/restored-session risk | generated tab-recovery notes below; `test/agent-browser.extension-tab-recovery.test.ts` (drift and about:blank recovery), `test/agent-browser.extension-tabs.test.ts` (post-close target), `test/agent-browser.extension-ref-guards.test.ts` (snapshot/action environment and session-tree rehydration), `test/agent-browser.resume-state.test.ts` (persisted session / resume planning) |
|
|
88
88
|
| Auth/profile workflows can leak secrets | Supports `auth save --password-stdin`, redacts sensitive args, SAML/OAuth-bearing URLs, stdout/stderr, details, and snapshot spills, and discards malformed oversized stdout instead of persisting a parse-failure spill | `test/agent-browser.extension-security-redaction.test.ts` |
|
|
89
|
-
| Stateful cookies/storage/auth output bloats or leaks context | Presentation layer redacts `details.data` for cookies and credential-like storage values while keeping low-risk local QA values such as `theme: dark` readable; recursively scrubs other structured upstream JSON (network, diff, trace/profiler, stream, dashboard, chat, auth, dialog, frame, state, and similar) using sensitive key names plus string heuristics; masks sensitive argv flags and positionals; scrubs secrets from failed batch step errors; and exposes a compact redacted `batch` matrix on top-level `details.data` | `extensions/agent-browser/lib/results/presentation.ts`, `extensions/agent-browser/lib/results/presentation/diagnostics.ts`, `extensions/agent-browser/lib/runtime.ts`, `test/agent-browser.presentation-diagnostics.test.ts` |
|
|
89
|
+
| Stateful cookies/storage/auth output bloats or leaks context | Presentation layer redacts `details.data` for cookies and credential-like storage values while keeping low-risk local QA values such as `theme: dark` readable; recursively scrubs other structured upstream JSON (network, diff, trace/profiler, stream, dashboard, chat, auth, dialog, frame, state, and similar) using sensitive key names plus string heuristics; masks sensitive argv flags and positionals, including raw batch rows and ordered code journals; scrubs secrets from failed batch step errors; and exposes a compact redacted `batch` matrix on top-level `details.data` | `extensions/agent-browser/lib/results/presentation.ts`, `extensions/agent-browser/lib/results/presentation/diagnostics.ts`, `extensions/agent-browser/lib/runtime.ts`, `test/agent-browser.presentation-diagnostics.test.ts` |
|
|
90
90
|
| Stale `@eN` refs fail mysteriously | Records per-session `details.refSnapshot`, rejects mismatched URLs / unknown refs / unsafe `batch` stdin ordering before spawn, adds recovery guidance to rerun `snapshot -i` or use stable `find` locators | `extensions/agent-browser/index.ts`, `extensions/agent-browser/lib/session-page-state.ts`, `test/agent-browser.session-page-state.test.ts`, `test/agent-browser.results.test.ts`, `test/agent-browser.extension-ref-guards.test.ts`, `test/agent-browser.extension-semantic-recovery.test.ts` |
|
|
91
91
|
| Agents need stable success/failure buckets | Exposes bounded `resultCategory`, `successCategory`, and `failureCategory` on tool `details` for branching without parsing prose; a `tool_result` hook also aligns real Pi `isError` semantics, naming `Pi tool isError: true` in prose output while preserving parseable caller-requested `--json` output | [`docs/TOOL_CONTRACT.md`](docs/TOOL_CONTRACT.md#details), `extensions/agent-browser/lib/results/categories.ts`, `extensions/agent-browser/index.ts`, `extensions/agent-browser/lib/pi-tool-rendering.ts`, `test/agent-browser.results.test.ts`, `test/agent-browser.extension-validation.test.ts`, `test/agent-browser.pi-pipeline.test.ts` |
|
|
92
92
|
| Clicks can report success without the page receiving the event | Top-level non-Electron direct `click` calls on `xpath=` targets or role-gated current `@e…` refs (`button`, `checkbox`, `menuitem`, `radio`, `switch`, `tab`) install a bounded target-specific DOM-event probe; eligible `@e…` refs require a unique role/name in both the latest snapshot and the live candidates. A per-probe temporary DOM marker must be read back by native `get attr <original-selector> <marker>` before the candidate can verify dispatch, including XPath scope. Missing or mismatched identity cleans up the probe and leaves the native click unverified, not failed. Duplicate-name refs pass through without a probe: their old ordinal cannot prove which element received the click. If upstream reports success but no trusted event reaches the resolved target, the wrapper fails the tool, exposes `details.clickDispatch`, and suggests explicit retry/inspect next actions (no in-page replay), including a nested-scroll `scrollintoview` action when the probe sees the target outside a scroll container or viewport. Unresolved locator clicks such as raw `find … click` are left upstream-owned to avoid false failures for frame-scoped targets. Other click results still expose `details.pageChangeSummary`; `observed: false` explicitly marks dispatch-only mutation summaries and adds a visible `Action dispatched; application change unverified` warning. Unchanged-URL clicks can surface evidence-backed `details.overlayBlockers` candidates. | [`docs/TOOL_CONTRACT.md`](docs/TOOL_CONTRACT.md#details), `extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.ts`, `extensions/agent-browser/lib/results/presentation/navigation.ts`, `test/agent-browser.presentation.test.ts`, `test/agent-browser.extension-click-dispatch.test.ts` |
|
|
93
93
|
| Dashboard scroll commands can look successful while nothing moves | Handles standard `scroll <dir> [px]` against the document first (including pages whose smooth-scroll CSS defeats upstream wheel timing), falls back upstream when the document cannot move, and samples viewport/containers around the fallback; explicit CSS-container scrolling uses instant movement so smooth-scroll CSS cannot cause a premature no-movement failure; unchanged positions fail as `upstream-error` with `details.scrollNoop`, visible recovery guidance, and exact snapshot/screenshot checks. Unsupported `scrollintoview text=...` fails before dispatch, including inside effective batch rows, and shows exact native `find text ... hover` and snapshot/ref recovery payloads; help remains native pass-through. | [`docs/TOOL_CONTRACT.md`](docs/TOOL_CONTRACT.md#details), [`docs/COMMAND_REFERENCE.md`](docs/COMMAND_REFERENCE.md#core-page-and-element-commands), `test/agent-browser.extension-validation.test.ts` |
|
|
94
|
-
| Dropdown/combobox clicks can focus or hit native option box-model errors | Adds first-class `select <selector> <value...>` paths through
|
|
94
|
+
| Dropdown/combobox clicks can focus or hit native option box-model errors | Adds first-class `select <selector> <value...>` paths through native `args` and `agent_browser_action`; semantic role/name or label select resolves exactly one current visible combobox/listbox ref before action. Custom combobox clicks still detect focused controls with explicit `aria-expanded` state but no visible options and return `details.comboboxFocus` plus exact recovery `nextActions` | [`docs/TOOL_CONTRACT.md`](docs/TOOL_CONTRACT.md#details), [`docs/COMMAND_REFERENCE.md`](docs/COMMAND_REFERENCE.md#core-page-and-element-commands), `extensions/agent-browser/lib/input-modes/semantic-action.ts`, `test/agent-browser.extension-input-modes.test.ts`, `test/agent-browser.extension-validation.test.ts` |
|
|
95
95
|
| Recording workflows fail late when `ffmpeg` is missing or report stale lifecycle state | After successful `record start` / `record restart`, reports `successCategory: "artifact-pending"`, returns an exact `stop-pending-recording` action, warns when older natives report pending output without `ffmpeg`, and conservatively invalidates prior page-scoped `@e…` refs on every executed start attempt and URL-bearing restart to protect older supported natives. This is not evidence of a page change: 0.37 records the active page unless a URL is supplied; FPS-only calls keep the intended tab; an unbounded transcript-backed namespace/session index reserves active destinations across aliases, serializes artifact lifecycle and explicit wait/output writes, persists cross-branch close tombstones, retires every successful close path (including every matching namespace owner for `close --all`), rejects missing/stale restart output, coalesces terminal batch state, keeps only the newest pending path per identity, rejects recording starts after a nested close, folds Unicode path aliases, and retains exact cleanup actions with visible guidance on any later same-session failure | [`docs/TOOL_CONTRACT.md`](docs/TOOL_CONTRACT.md#details), [`docs/COMMAND_REFERENCE.md`](docs/COMMAND_REFERENCE.md#diff-debug-and-streaming), `test/agent-browser.extension-validation.test.ts`, `test/agent-browser.presentation-artifacts-batch.test.ts` |
|
|
96
96
|
| Upstream CLI drift can silently invalidate wrapper behavior | Publishes a repo-readable command reference, verifies it against the recommended 0.38.1 target, and probes browser-backed calls once per cwd/PATH so stable versions below the 0.35.0 floor fail before browser launch with installed/expected version evidence | `npm run verify` |
|
|
97
97
|
| Pages can expose structured workflows through experimental WebMCP | Shows native positive WebMCP availability in navigation summaries and passes through `webmcp list`, `invoke`, detached `result` / `cancel`, params/frame/timeout options, and the bundled `webmcp-gen` skill; treats `--no-webmcp` as launch-scoped, keeps pending or unsuccessfully settled targets unverified with an actionable `get url` follow-up, invalidates stale refs after page tools run, and budgets effective raw or stdin batch timeouts | [`docs/COMMAND_REFERENCE.md`](docs/COMMAND_REFERENCE.md#webmcp-page-tools), `test/agent-browser.extension-ref-guards.test.ts`, `test/agent-browser.wait-timeouts.test.ts`, `test/agent-browser.real-upstream-contract.test.ts` |
|
|
98
|
-
| Desktop Electron apps need discovery, CDP attach, and safe teardown |
|
|
98
|
+
| Desktop Electron apps need discovery, CDP attach, and safe teardown | `agent_browser_electron` runs host `list` / isolated `launch` (temp profile, OS-chosen debug port) / `status` / `probe` / `cleanup`, merges `launchId` plus managed `sessionName`, supports `handoff` `snapshot` / `tabs` / `connect`, and surfaces mismatch and post-command health guidance; wrapper cleanup applies only to launches it created | `extensions/agent-browser/lib/electron/discovery.ts`, `launch.ts`, `cleanup.ts`, [`docs/TOOL_CONTRACT.md`](docs/TOOL_CONTRACT.md#agent_browser_electron), [`docs/COMMAND_REFERENCE.md`](docs/COMMAND_REFERENCE.md#electron-desktop-apps) |
|
|
99
99
|
| Agents need bundled `skills` text and local setup/status commands without touching the live session | Treats `skills list/get/path`, local auth/profile/setup commands, `session list`, and local state lifecycle commands as sessionless reads/actions when upstream does not need a live page. Session/state rows and targets remain visible, and supported upstream state/config/path operations pass through unchanged. Browser-backed workflows still receive an implicit session only when the caller did not choose one. | [`docs/COMMAND_REFERENCE.md`](docs/COMMAND_REFERENCE.md#built-in-skills), `extensions/agent-browser/lib/command-policy.ts`, `extensions/agent-browser/lib/runtime.ts` |
|
|
100
100
|
|
|
101
101
|
Artifact results show known requested paths separately from reported/resolved locations and infer image MIME types from file headers, not suffixes. Parent-directory failures return path-specific `validation-error` guidance before browser dispatch. Prefer absolute artifact paths in raw batch strings because the daemon's working directory may differ from Pi's. When execution cwd differs from the launch/project root, the wrapper binds relative file operands, including raw batch rows, to the captured execution cwd. Dispatched `record start` and URL-bearing `record restart` attempts also return one fresh-snapshot warning on success or failure, including in JSON output. It describes conservative ref invalidation, not an observed page change; unreached rows do not emit it.
|
|
102
102
|
|
|
103
103
|
## Fastest way to try it
|
|
104
104
|
|
|
105
|
-
Use Pi 0.
|
|
105
|
+
Use Pi 0.87.0 or newer. This package keeps optional Pi core imports as wildcard `peerDependencies` because Pi package docs require the host Pi install to provide those packages, pins its direct Pi validation dependencies to 0.87.0, and makes hosts below 0.87.0 a setup failure through `pi-agent-browser-doctor`. There are no compatibility shims for older Pi releases.
|
|
106
106
|
|
|
107
107
|
Install upstream `agent-browser` first and make sure it is on `PATH`:
|
|
108
108
|
|
|
@@ -135,11 +135,11 @@ agent-browser --version
|
|
|
135
135
|
which chromium
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
-
The `which` package and launcher symlink satisfy upstream's existing Linux system-browser discovery even when tests or Pi sessions isolate `HOME`.
|
|
138
|
+
The `which` package and launcher symlink satisfy upstream's existing Linux system-browser discovery even when tests or Pi sessions isolate `HOME`. Browser code uses the same native launch configuration as direct calls.
|
|
139
139
|
|
|
140
|
-
Reapply the musl command symlink after reinstalling or upgrading upstream until #1587 is resolved. The wrapper uses Termux-private socket/policy storage, compact 80-bit managed identities so ordinary namespaces and fresh rotations fit the Unix socket-path limit, Termux's `ps`, and Android app-sandbox trust rules automatically.
|
|
140
|
+
Reapply the musl command symlink after reinstalling or upgrading upstream until #1587 is resolved. The wrapper uses Termux-private socket/policy storage, compact 80-bit managed identities so ordinary namespaces and fresh rotations fit the Unix socket-path limit, Termux's `ps`, and Android app-sandbox trust rules automatically. Historical 0.6 Android validation covered headless browser flows, managed restore, namespaced sessions, the former script/job inputs, QA, screenshots, and recording; it does not qualify the 0.7 code contract. Electron desktop discovery/lifecycle is not applicable to Android apps. Android remains outside the release-blocking Crabbox macOS/Ubuntu/native-Windows matrix until a repeatable Android provider target is added.
|
|
141
141
|
|
|
142
|
-
The native tool also gives agents absolute installed-package doc paths in its compact runtime guidance. Raw `args` are the 1:1 upstream CLI coverage path for the targeted `agent-browser` release; `
|
|
142
|
+
The native tool also gives agents absolute installed-package doc paths in its compact runtime guidance. Raw `args` are the 1:1 upstream CLI coverage path for the targeted `agent-browser` release; `agent_browser_code` adds bounded JavaScript orchestration over the same browser, while advanced tools preserve semantic actions, diagnostic QA, source lookup, and Electron lifecycle. Agents should read `README.md` for setup/dependencies, `docs/COMMAND_REFERENCE.md` for targeted command workflows, and `docs/TOOL_CONTRACT.md` for result/detail contracts only when deeper guidance is needed.
|
|
143
143
|
|
|
144
144
|
Then install this Pi package:
|
|
145
145
|
|
|
@@ -312,7 +312,7 @@ npm exec --yes --package pi-agent-browser-native@latest -- pi-agent-browser-conf
|
|
|
312
312
|
npm exec --yes --package pi-agent-browser-native@latest -- pi-agent-browser-config browser executable set "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"
|
|
313
313
|
```
|
|
314
314
|
|
|
315
|
-
|
|
315
|
+
Profile hints with `authenticated-only` remain advisory. Global/override profile names with `policy: "always"` and executable defaults bootstrap inactive automatic root browsers; active roots and unrelated explicit sessions retain their native settings. Configure profile/executable guidance globally, in trusted project config, or through `PI_AGENT_BROWSER_CONFIG`. Ask the agent to run `agent_browser` with `args: ["profiles"]` and `args: ["doctor"]` when profile resolution fails. The upstream `profiles` command lists Chrome profiles from Chrome's user data directory; `Default` is not canonical on every machine. Use the displayed profile directory name, a full profile/user-data directory path when upstream accepts one, or a configured `browser.executablePath` plus `sessionMode: "fresh"` for a different Chromium-compatible browser.
|
|
316
316
|
|
|
317
317
|
## Common agent calls
|
|
318
318
|
|
|
@@ -329,7 +329,7 @@ Chromium launch switches belong in the value of `--args`, for example `{ "args":
|
|
|
329
329
|
|
|
330
330
|
Local Chrome startup uses the stock binary's `--args --no-startup-window` capability to suppress Chrome's extra startup window. Headless remains the default. Caller launch arguments keep native CLI → environment → config precedence and follow this default; browsers started before this change with custom arguments may restart once when their native launch configuration changes. Ordinary follow-ups do not resend bootstrap settings. CDP, providers, Electron, and Lightpanda remain native-owned; no tabs are deleted or profiles edited by this behavior.
|
|
331
331
|
|
|
332
|
-
`open` without a URL uses native `get url`: it launches when needed and otherwise preserves the current page. This also applies to effective batch rows and
|
|
332
|
+
`open` without a URL uses native `get url`: it launches when needed and otherwise preserves the current page. This also applies to effective batch rows and code calls. `details.args` preserves the request, while `effectiveArgs`, command, URL data, and lifecycle describe the actual native operation. Use `open about:blank` only when you intend to navigate there. Help/version requests remain unchanged.
|
|
333
333
|
|
|
334
334
|
Watch a browser window during a demo, QA run, or user-completed login by adding upstream's global `--headed` flag on the first launch. Use `sessionMode: "fresh"` if a managed session may already exist, because headed/headless state is launch-scoped. A successful first/fresh local wrapper-managed headed launch, including a launch inside `batch`, returns `details.browserWindow = { mode: "headed", ownership: "wrapper-managed", sessionName, visibility: "unverified" }` and one visible handoff sentence; CDP, auto-connect, provider, and Electron attachments do not. This proves that the wrapper requested and upstream launched headed mode, not that the OS window is visible on the user's display; remote, container, or virtual-display setups can still hide it. After the user finishes in the window, continue with `sessionMode: "auto"`.
|
|
335
335
|
|
|
@@ -431,196 +431,84 @@ Download a file from a known link or control:
|
|
|
431
431
|
{ "args": ["download", "@e5", "/tmp/report.pdf"] }
|
|
432
432
|
```
|
|
433
433
|
|
|
434
|
-
###
|
|
434
|
+
### Persistent browser code
|
|
435
435
|
|
|
436
|
-
Use
|
|
437
|
-
|
|
438
|
-
- `await browser({ args, stdin?, timeoutMs? })` runs one ordinary native browser call through the same validation, policy, redaction, presentation, artifact, and timeout pipeline as top-level `args`. It resolves to `{ ok, data, details?, error?, failureCategory?, nextActions?, resultCategory, successCategory?, summary, text }`; check `ok` before consuming `data`. Script-visible browser `nextActions` keep only policy-compatible calls with the wrapper-owned isolated identity prefix removed, so their `params` can be passed back to `browser()`.
|
|
439
|
-
- `emit(value)` adds a JSON-compatible output value. One emission is returned directly; multiple emissions are returned as an array. With no emission, the async body’s return value is used; when it returns nothing, `details.data` is omitted.
|
|
436
|
+
Use `agent_browser_code` for loops, branching, or aggregation. Each call gets fresh JavaScript variables and the same browser selected by ordinary `agent_browser` calls. Cookies, open tabs, and authenticated browser state persist according to native session/profile settings; finishing a code call does not close the browser.
|
|
440
437
|
|
|
441
438
|
```json
|
|
442
439
|
{
|
|
443
|
-
"
|
|
440
|
+
"code": "const titles = []; for (const url of ['https://example.com', 'https://example.org']) { const opened = await browser({ args: ['open', url] }); if (!opened.success) throw new Error(opened.error); const title = await browser({ args: ['get', 'title'] }); if (!title.success) throw new Error(title.error); titles.push({ url, title: title.data.title ?? title.data.result }); } emit(titles);"
|
|
444
441
|
}
|
|
445
442
|
```
|
|
446
443
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
Limits are fixed: 25 attempted `browser()` calls, 64 KiB source, 64 KiB final emitted JSON, a 120-second default timeout, and a 300-second hard timeout ceiling. Final data is redacted, serialized compactly, and checked again before presentation; unsafe depth or post-redaction growth becomes a structured validation failure rather than unbounded prose. One approved top-level `agent_browser` call can authorize all 25 inner calls, so inspect the visible script source before approving it: the collapsed Pi tool row shows a bounded terminal-safe preview with source line breaks marked as `↵`, and expanding that row shows the full terminal-safe source with JavaScript line terminators preserved as visible newlines and removed controls marked visibly. The extension rehydrates only wrapper-verified parse-valid compact-result spills before returning inner `data`; ordinary result redaction still applies. Inner `summary` and `text` are bounded, and a complete envelope that still exceeds the IPC message cap becomes a handleable `upstream-error` browser result instead of breaking the sandbox bridge. Pi session persistence is required so the wrapper can append a model-invisible cleanup lease before the first browser launch and retry a failed close after restart. A rejected inner policy/validation call fails the top-level result even when source handles its returned envelope; an uncaught source exception returns `failureCategory: "script-error"`; a failed cleanup overrides any script outcome with `failureCategory: "cleanup-failed"`, `details.scriptSession.closeCommandArgs`, and an exact `close-script-session-after-cleanup-failure` next action. Compact prose confirms a successful isolated-session close after browser-bearing runs. Pi branch changes, quit, and reload abort active scripts, wait for isolated-session cleanup, and reap the sandbox child before restoring branch-visible state.
|
|
450
|
-
|
|
451
|
-
Use normal `args`, `job`, or `qa` for linear work. Use ordinary profile/attached flows for authenticated browser state. Do not store code mode source under a name or treat it as shared workflow configuration.
|
|
452
|
-
|
|
453
|
-
### Locator shorthand (`semanticAction`)
|
|
454
|
-
|
|
455
|
-
For supported upstream `find` flows, direct selector/ref `click` / `check` / `fill`, and native dropdown selection you can omit hand-built `args` and pass a top-level `semanticAction` object instead. The wrapper compiles locator actions to the same `find` argv upstream already understands, direct selector/ref actions to matching upstream commands, or `action: "select"` to upstream `select <selector> <value...>`; compiled argv is echoed as `details.compiledSemanticAction` when the unified result includes that field. Full field rules live in [`docs/TOOL_CONTRACT.md#semanticaction`](docs/TOOL_CONTRACT.md#semanticaction).
|
|
456
|
-
|
|
457
|
-
```json
|
|
458
|
-
{ "semanticAction": { "action": "click", "locator": "text", "value": "Submit" } }
|
|
459
|
-
{ "semanticAction": { "action": "click", "locator": "role", "role": "button", "name": "Continue without Signing In" } }
|
|
460
|
-
{ "semanticAction": { "action": "fill", "locator": "label", "value": "Email", "text": "user@example.com" } }
|
|
461
|
-
{ "semanticAction": { "action": "fill", "selector": "@e1", "text": "prompt text" } }
|
|
462
|
-
{ "semanticAction": { "action": "click", "selector": "#submit" } }
|
|
463
|
-
{ "semanticAction": { "action": "select", "selector": "#flavor", "value": "chocolate" } }
|
|
464
|
-
{ "semanticAction": { "action": "click", "locator": "text", "value": "Close", "session": "named-browser" } }
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
Typical pitfalls:
|
|
468
|
-
|
|
469
|
-
- Supply **exactly one** of `script`, `args`, `semanticAction`, `job`, `qa`, `sourceLookup`, `networkSourceLookup`, or `electron` per call (not more, not none). Prefer `script` only for one-shot loops/branches/aggregation, `args` for routine browse; `semanticAction` for stable locators; `job`/`qa` for multi-step checks; `electron` for desktop apps; treat `sourceLookup` / `networkSourceLookup` as experimental candidates-only.
|
|
470
|
-
- Omit `--json` for ordinary prose; include it when you need parseable JSON text.
|
|
471
|
-
- `semanticAction` and `job` are **not** valid inside `batch` stdin; batch steps stay upstream argv string arrays (spell a `find` step as tokens there if you need it in a batch).
|
|
472
|
-
- Commands or locators outside the supported shorthand still require explicit `args`. Common page getters are grouped under `get`: use `get title`, `get url`, or `get text <selector>` rather than shortcut commands such as `title` or `url`; unknown getter shortcuts can return read-only `details.nextActions` like `use-get-title`.
|
|
473
|
-
- For `locator: "role"`, pass either `value: "button"` or `role: "button"`; if both are present they must match.
|
|
474
|
-
- Use `semanticAction.session` to target a named upstream browser session; the wrapper prepends `--session <name>` before the compiled `find` or `select` argv and keeps that prefix on retry/candidate actions. In active sessions, role/name click/check/fill shorthands may resolve through the current `snapshot -i` refs before execution so hidden duplicate matches do not steal the action; fill only resolves when the current snapshot has one exact editable ref match. `details.effectiveArgs` shows the exact executed argv.
|
|
475
|
-
- Do not reuse `@e…` refs across navigation or in-place rerenders. The wrapper records the latest snapshot refs per session and fails stale/recycled getter and mutation refs, including batched getters, before upstream can silently read or hit a different current-page element; use the session-aware `refresh-interactive-refs` next action.
|
|
476
|
-
- If upstream classifies the failure as `stale-ref` and `details.compiledSemanticAction` is present for a compiled `find` action, `details.nextActions` may list `retry-semantic-action-after-stale-ref` after `refresh-interactive-refs`, carrying the same compiled `find` argv so you can retry the locator-stable target once it is safe to do so. `select` calls that used stale `@refs` only get refresh guidance; use a fresh snapshot or stable selector before retrying (contract in [`docs/TOOL_CONTRACT.md#semanticaction`](docs/TOOL_CONTRACT.md#semanticaction)).
|
|
477
|
-
- If the failure is `selector-not-found`, the wrapper may take one fresh snapshot and add `Current snapshot ref fallback` when that snapshot has exact visible role/name matches for the failed `find` / `semanticAction` target. Non-fill targets can include direct `try-current-visible-ref*` next actions, and semantic click misses can still add bounded `Agent-browser candidate fallbacks` such as `button`/`link` role retries for `text` clicks. `semanticAction` does not expose `uncheck` while upstream `find ... uncheck` is not runtime-supported; use raw `args: ["uncheck", <selector-or-ref>]` after a stable selector or fresh snapshot ref. For semantic `fill` misses on desktop or host-controlled rich inputs, prefer `details.richInputRecovery`: refresh refs, choose the current editable `@ref`, focus or click it, then use `keyboard type` for framework-controlled editors that require real key events. `keyboard inserttext` is paste-like and can change a DOM value without updating application state, so use it only with separate application-state verification. Direct contenteditable fills are verified with `get text` when snapshot metadata proves the target is contenteditable; if replacement did not happen, `details.fillVerification` warns before any submit step. Those recovery nextActions do not copy the fill text and do not press `Enter` or submit; only submit when the user flow explicitly calls for it (same contract link).
|
|
478
|
-
- A successful upstream `click` is not proof that the web app handled the event or changed state. For top-level non-Electron direct clicks on `xpath=` targets and eligible current `@e…` refs, the wrapper may fail the tool with `details.clickDispatch` and a `Click dispatch diagnostic` line when upstream reported success but no trusted DOM event reached the resolved target. Raw `find … click` locator calls are not probed because the wrapper has no concrete element before upstream resolves the locator, and document-level probes can falsely fail frame-scoped clicks. `@e…` ref click probes are limited to current snapshot refs with accessible role `button`, `checkbox`, `menuitem`, `radio`, `switch`, or `tab`, with a unique role/name in both the saved snapshot and the live candidates. Ref and XPath candidates must also match native `get attr <original-selector> <marker>` readback of a per-probe temporary DOM marker. If identity is missing or mismatched, the wrapper cleans up and abstains from dispatch verification while the native click runs. Duplicate-name refs remain upstream-owned; snapshot order is not target identity. Use the suggested `inspect-click-dispatch-miss` / `retry-click-after-dispatch-miss` next actions instead of assuming the click mutated the page; when `details.clickDispatch.scrollContainer` is present, use `scroll-target-into-view-after-dispatch-miss` first. When the task depends on a mutation, follow `inspect-after-mutation` / `pageChangeSummary` evidence with a wait, URL/text check, or fresh snapshot before trusting the result; if the target still did not change, retry with a current visible ref or stable selector and report the workflow issue instead of silently continuing. For static local fixtures where the user only needs to exercise app code, an explicit `eval --stdin` programmatic click such as `document.querySelector("#demo").click()` can be a diagnostic workaround, but treat it as an untrusted scripted activation rather than proof a real user click works, and never use it to bypass user instructions. Respect explicit user stop boundaries yourself: if the user says to stop before order/post/purchase/submit, gather evidence on that page and do not click the final action. The wrapper does not parse broad prompt text into business-intent action blocks; `details.promptGuard` is reserved for concrete artifact-before-close checks.
|
|
479
|
-
- A successful upstream `click` can deliver no input at all on some sites. Reproduced against `https://www.saucedemo.com/` with upstream `agent-browser` 0.34.0 and no wrapper involved: when every CLI invocation in the flow is spaced ~0.6s apart, the React add-to-cart click reports success while **zero** DOM events reach a capture-phase listener and the cart badge never updates (0/5 runs succeeded, versus 4/5 with no spacing). A single idle gap is harmless (5/5); only sustained spacing across the flow triggers it. In that state a scripted `document.querySelector(...).click()` still works and updates the badge, so the page and its handlers are fine and the input never arrives; retries, `scrollintoview`, headed mode, and re-navigation do not recover it. This looks site-specific — React TodoMVC and react.dev were unaffected under the same pacing and command count. Wrapper calls do more per-command work than raw CLI calls, so they sit in the slow regime more often. Running the interaction steps as one `batch` keeps them inside a single upstream process and succeeded 5/5; prefer `batch` for consecutive real-app click flows, and treat a click whose `pageChangeSummary`/`navigationSummary` shows no change as unproven. When a `wait --url` or `assertUrl` times out after a suspected missed click, use the `fresh-session-after-url-wait-timeout` next action (`sessionMode: "fresh"` + `open about:blank`): replace about:blank with the target URL and replay the flow as one batch in a fresh session instead of retrying the wait.
|
|
480
|
-
- A successful `snapshot -i` can surface `Possible overlay blockers` immediately when refs already contain strong dialog/alertdialog evidence plus close/dismiss controls. If a **top-level** `@e…`/`ref=` click succeeds (unified command `click`, not a `batch` step), upstream reports `data.clicked`, and `details.navigationSummary.url` stays on the same tab URL under the same normalization as ref preflight (fragment-insensitive), the wrapper may take one extra `snapshot -i` and add `Possible overlay blockers` with `details.overlayBlockers` (`candidates`, `summary`, optional `snapshot` refresh for refs) plus session-aware `inspect-overlay-state` / bounded `try-overlay-blocker-candidate-*` next actions when that snapshot shows strong modal context (`dialog` / `alertdialog`) and close/dismiss-like controls. Page-wide words like privacy, sign in, or banner alone do not trigger this diagnostic. The unchanged-URL check compares the prior pinned tab target with `details.navigationSummary.url`; CSS selector clicks do not run this overlay probe. Also skipped when tab correction or about-blank recovery already ran on that result. Separately, when upstream rejects a click because another element covers the target's click point (`is covered by` … `at its click point`), the wrapper keeps `failureCategory: "upstream-error"` and adds only the session-aware `inspect-overlay-state` snapshot action; it does not retry the blocked click or guess a dismiss control without fresh snapshot evidence. This covers direct `click`, `semanticAction` click, raw `find` clicks (including `nth` and an omitted action that defaults to click), and failed `batch`/`job` rows; it does not diagnose silent input-dispatch failures.
|
|
481
|
-
- If `get text <selector>` reads a non-ref, non-simple-id CSS selector with multiple matches or a hidden first match while visible matches exist, including successful `batch` steps, the wrapper may add `Selector text visibility warning`, `details.selectorTextVisibility` (plus `selectorTextVisibilityAll` for multiple batched warnings), and `inspect-visible-text-candidates` next actions; the warning names the matching `details.nextActions` id. Prefer a visible `@ref`, a scoped selector, or a targeted `eval --stdin` over hidden tab content.
|
|
482
|
-
- In wrapper-tracked attached Electron sessions, broad selectors such as `body`, `html`, `main`, or `[role=application]` may read the whole app shell. The wrapper may add `Broad Electron get text selector warning`, `details.electronGetTextScopeWarning`, and `snapshot-for-electron-text-scope`; ordinary browser pages do not qualify without Electron launch provenance. Prefer `snapshot -i`, a current `@ref`, or a narrower panel selector.
|
|
483
|
-
|
|
484
|
-
### Constrained browser jobs
|
|
485
|
-
|
|
486
|
-
For short repeatable workflows, pass a top-level `job` instead of hand-writing `batch` stdin. Keep dynamic app jobs short around navigation, click, and rerender boundaries; avoid packing a whole checkout into one job. The wrapper only supports constrained steps (`open`, `click`, `fill`, `type`, `select`, `wait`, `assertText`, `assertUrl`, `waitForDownload`, `snapshot`, and `screenshot`), compiles them to existing upstream `batch` commands, and echoes the compiled commands as `details.compiledJob` for auditability. `open` steps can include `loadState` (`domcontentloaded`, `load`, or `networkidle`) to insert a readiness wait before the next step. `click` and `fill` steps can use either CSS `selector` or semantic locator fields (`locator`, `role`/`value`, optional `name`) so a job can express flows like role/name search without brittle selectors. `type` can use `selector`, `text`, optional `delayMs` for per-character pacing, and optional `press` for a final key such as `Enter`; paced type compiles to existing `focus`, `keyboard type`, `wait`, and `press` batch rows, is capped at 200 characters per delayed step, and compacts model-visible batch text while full rows remain in `details.batchSteps`. The same compile path backs top-level `qa`, so long `qa` runs surface the same timeout evidence shape. If a long `job`, `qa`, or `batch` hits the wrapper watchdog, `details.timeoutPartialProgress` may recover per-step status (`completed`, `failed`, `pending`, or `unknown`), current page URL plus a title after the URL is verified, declared artifact paths that already exist on disk, and either a `retry-timeout-step` next action for the first incomplete read-only or idempotent step, `inspect-current-page-after-timeout` when the target is already verified, or a fail-fast `verify-page-target-after-timeout` batch that runs `get url` before `snapshot -i` when the target is unknown (see [`docs/TOOL_CONTRACT.md#details`](docs/TOOL_CONTRACT.md#details)). Timeout recovery follows the effective batch source and native artifact operand positions, including literal dash-leading paths. Executable retries preserve the original row in a one-row batch. There is no separate catalog of reusable named browser recipes above one-shot ad hoc `script`, `job`, `qa`, and raw `batch`; `script` has no names, registry, or persistent workflow state; see [`docs/ARCHITECTURE.md#no-reusable-recipe-layer-yet`](docs/ARCHITECTURE.md#no-reusable-recipe-layer-yet) for the closed `RQ-0068` decision and when to revisit it.
|
|
487
|
-
|
|
488
|
-
`assertText` accepts only `text`, not selector or locator fields. Clicks can stale later `@refs`; split the job and take a fresh snapshot before using them.
|
|
489
|
-
|
|
490
|
-
**Navigation inside `job` is explicit.** A successful `click` does not prove the next page loaded; add `assertUrl` and/or `assertText` after navigation-prone clicks (forms, checkout, tabs, submit buttons) before screenshots or steps that assume the new page. `assertUrl` accepts exact URLs and `*` / `**` glob-style patterns and now compiles directly to upstream `wait --url` for both forms.
|
|
444
|
+
`await browser({ args, stdin?, timeoutMs? })` returns the canonical observation: `success`, `data`, error/category information, exact `nextActions`, and artifact/image evidence when available. Emit the selected JSON the model needs instead of entire observations. `emitImage(observation.imageObservations[0])` selects a verified image from this code call for actual image attachment; emitting a path as JSON does not attach it. Stop at observations that need model judgment rather than guessing the next action in code.
|
|
491
445
|
|
|
492
446
|
```json
|
|
493
447
|
{
|
|
494
|
-
"
|
|
495
|
-
"steps": [
|
|
496
|
-
{ "action": "open", "url": "https://example.com" },
|
|
497
|
-
{ "action": "assertText", "text": "Example Domain" },
|
|
498
|
-
{ "action": "screenshot", "path": ".dogfood/example.png" }
|
|
499
|
-
]
|
|
500
|
-
}
|
|
448
|
+
"code": "const shot = await browser({ args: ['screenshot', '/tmp/current-page.png'] }); if (!shot.success) throw new Error(shot.error); emit(shot.artifactVerification); if (shot.imageObservations?.length) emitImage(shot.imageObservations[0]);"
|
|
501
449
|
}
|
|
502
450
|
```
|
|
503
451
|
|
|
504
|
-
|
|
505
|
-
{
|
|
506
|
-
"job": {
|
|
507
|
-
"steps": [
|
|
508
|
-
{ "action": "open", "url": "https://shop.example/checkout" },
|
|
509
|
-
{ "action": "fill", "selector": "#email", "text": "user@example.com" },
|
|
510
|
-
{ "action": "click", "selector": "#continue" },
|
|
511
|
-
{ "action": "assertUrl", "url": "**/shipping" },
|
|
512
|
-
{ "action": "assertText", "text": "Shipping address" },
|
|
513
|
-
{ "action": "screenshot", "path": ".dogfood/shipping.png" }
|
|
514
|
-
]
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
```
|
|
452
|
+
Optional `session` and `namespace` select one native identity for the whole code call; omitted fields follow normal browser defaults. Inner native commands can use batch, auth, profiles, state, connect, and close, but cannot change that identity or issue namespace-wide `close --all`. Use the direct tool for those operations. Parent-side native commands keep normal auth/config/environment behavior. The fresh permissioned Node child exposes no host filesystem, network, process APIs, imports, timers, or dynamic code generation.
|
|
518
453
|
|
|
519
|
-
|
|
454
|
+
Limits: 25 attempted browser calls; 64 KiB source and emitted JSON; 1 MiB per IPC message and 8 MiB cumulative IPC; 120 seconds by default, 300 seconds maximum. Inner calls are serial, even with `Promise.all`. Selected images are limited to eight and 20 MiB total, with the normal configurable inline limit (5 MiB per image by default). See the [code contract](docs/TOOL_CONTRACT.md#agent_browser_code) for failure, cancellation, and image rules.
|
|
520
455
|
|
|
521
|
-
|
|
456
|
+
A handled browser failure remains visible in `failures` and `codeRun.failedCallCount`; successful source completion is not proof that every inner command succeeded. Rejected inner input shapes, source exceptions, cancellation, or deadline failure fail the code result. Uncertain mutations must be inspected before retry. Ordered Pi transition entries preserve inner page/ref/attachment/close state through resume; an interrupted intent remains unknown until inspection. A persisted Pi session is required.
|
|
522
457
|
|
|
523
|
-
###
|
|
458
|
+
### Advanced browser tools
|
|
524
459
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
For desktop Electron apps, use top-level `electron` to avoid hand-building the discover → launch with CDP → connect → inspect → cleanup sequence. The wrapper owns only apps it launched, uses an isolated temp profile and OS-chosen debug port, and reports exact cleanup/status next actions. It does **not** reuse the app's normal signed-in profile or attach to an already-running authenticated app, so launching Slack/Obsidian/VS Code this way may show first-run or sign-in UI instead of the user's live local state. When the explicit goal is signed-in local app state and host tools are available, launch the normal app with a debug port first (for example `open -a Slack --args --remote-debugging-port=9222 --remote-allow-origins='*'`), then attach with `{ "args": ["connect", "9222"], "sessionMode": "fresh" }`; if the app is already running without a debug port, ask before relaunching it. `electron.list` may annotate likely private apps (for example notes, chat, mail, developer workspaces, or password/auth tools) as `[likely sensitive: …]`; those are hints only, so use caller-owned `allow` / `deny` policy before launching sensitive apps.
|
|
460
|
+
List specialized capabilities with `agent_browser_tools {}`. Enable only what the task needs:
|
|
528
461
|
|
|
529
462
|
```json
|
|
530
|
-
{ "
|
|
531
|
-
{ "electron": { "action": "launch", "appName": "Visual Studio Code", "handoff": "snapshot" } }
|
|
532
|
-
{ "electron": { "action": "probe", "timeoutMs": 5000 } }
|
|
533
|
-
{ "electron": { "action": "cleanup", "launchId": "electron-…" } }
|
|
463
|
+
{ "enable": ["action", "qa", "electron", "source", "network"] }
|
|
534
464
|
```
|
|
535
465
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
Explicit-ID `electron.status` labels historical cleaned launch records; default and `all: true` selection exclude them. Current PID/port liveness stays independent of cleanup history. `details.electron.statuses[].userDataDirState` freshly measures only the tracked profile path: `present` (including dangling symlinks), `absent` (ENOENT), or `unknown` (other `lstat` errors), not whether all app residue is gone.
|
|
466
|
+
Activation adds tools without removing other active tools; Pi owns the selected-tool history. Omit CLI `--tools` for normal lazy activation, or include each desired advanced tool in that explicit selection. The loader cannot enable tools excluded by the host. Each specialized tool takes **flat fields**, not a nested object on `agent_browser`:
|
|
539
467
|
|
|
540
|
-
|
|
468
|
+
| Tool | Example input | Preserved capability |
|
|
469
|
+
| --- | --- | --- |
|
|
470
|
+
| `agent_browser_action` | `{ "action": "fill", "locator": "label", "value": "Email", "text": "user@example.com" }` | Stable locators, direct selectors/refs, and unique accessible native dropdown selection |
|
|
471
|
+
| `agent_browser_qa` | `{ "url": "https://example.com", "expectedText": "Example Domain" }` | Visible assertions, scoped diagnostics, actionable/benign error classification, and a real pass/fail verdict |
|
|
472
|
+
| `agent_browser_electron` | `{ "action": "launch", "appName": "Visual Studio Code", "handoff": "snapshot" }` | Host discovery, isolated app launch, CDP readiness, status/probe, and owned cleanup |
|
|
473
|
+
| `agent_browser_source` | `{ "selector": "#save", "componentName": "SaveButton" }` | Experimental DOM/React and bounded local workspace candidates |
|
|
474
|
+
| `agent_browser_network_source` | `{ "requestId": "req-1", "url": "/api/fail" }` | Experimental failed-request/initiator/local-source correlation |
|
|
541
475
|
|
|
542
|
-
|
|
476
|
+
Use `agent_browser_action` with `action: "select"` for a native dropdown: a direct `selector` plus `value`/`values`, or an exact role/name or label locator resolved to one visible combobox/listbox. For framework-controlled rich inputs, inspect returned recovery actions, focus a current ref, then use native `keyboard type`; verify application state before submitting.
|
|
543
477
|
|
|
544
|
-
|
|
545
|
-
{ "args": ["connect", "9222"], "sessionMode": "fresh" }
|
|
546
|
-
{ "args": ["tab", "list"] }
|
|
547
|
-
{ "args": ["tab", "t2"] }
|
|
548
|
-
{ "args": ["snapshot", "-i"] }
|
|
549
|
-
```
|
|
478
|
+
QA defaults to `domcontentloaded`. URL QA clears enabled network/console buffers and checks page-error residue before opening the URL. Matched residue makes that check unverified and non-pass; it is not proof of a new application error. Attached QA (`{ "attached": true }`) preserves existing buffers and defaults diagnostics off; opt into `checkNetwork`, `checkConsole`, or `checkErrors` deliberately. Native diagnostic-read success alone is not a QA verdict.
|
|
550
479
|
|
|
551
|
-
|
|
480
|
+
Electron launch uses a new temporary app profile and does not inherit the normal app's signed-in state. Use `agent_browser_electron` to list, launch, probe/status, then clean up its returned `launchId`. A manually launched debug-enabled app uses native `connect` and stays host-owned. Read [the Electron guide](docs/ELECTRON.md) for lifecycle and timeout details.
|
|
552
481
|
|
|
553
|
-
|
|
482
|
+
Source tools report candidates, never authoritative blame or automatic edits. Workspace scans default to 2,000 source files, cap at 5,000, and return at most ten workspace matches. They remain available even when unrelated Pi file tools are disabled; packaged app bundles are not unpacked.
|
|
554
483
|
|
|
555
|
-
###
|
|
484
|
+
### Fixed sequences and evidence
|
|
556
485
|
|
|
557
|
-
|
|
486
|
+
Use native `batch --bail` for known sequences. Add an explicit destination/text wait after a navigation-prone click; successful dispatch is not proof the application changed. Split when fresh refs or model judgment are needed.
|
|
558
487
|
|
|
559
488
|
```json
|
|
560
489
|
{
|
|
561
|
-
"
|
|
562
|
-
|
|
563
|
-
"expectedText": "Example Domain",
|
|
564
|
-
"screenshotPath": ".dogfood/qa-example.png"
|
|
565
|
-
}
|
|
490
|
+
"args": ["batch", "--bail"],
|
|
491
|
+
"stdin": "[[\"open\",\"https://shop.example/checkout\"],[\"fill\",\"#email\",\"user@example.com\"],[\"click\",\"#continue\"],[\"wait\",\"--url\",\"**/shipping\"],[\"wait\",\"--text\",\"Shipping address\"],[\"screenshot\",\"/tmp/shipping.png\"]]"
|
|
566
492
|
}
|
|
567
493
|
```
|
|
568
494
|
|
|
569
|
-
Use
|
|
570
|
-
|
|
571
|
-
### Experimental source lookup
|
|
572
|
-
|
|
573
|
-
For local app debugging, `sourceLookup` can gather candidate component/file locations for a visible UI element. It is explicit and evidence-based: pass a `selector`, `reactFiberId`, and/or `componentName`; the wrapper compiles those inputs to existing batch steps (`is visible`, `get html` when `includeDomHints` is not `false`, `react inspect`, `react tree`) and a bounded local workspace scan under the captured execution cwd (`maxWorkspaceFiles` defaults to 2000 and cannot exceed 5000; the scan records at most ten `workspace-search` candidates). Results appear in `details.sourceLookup` with `status`, `candidates`, `limitations`, and `summary`. Unlike `qa`, the wrapper does not mark the tool failed on an otherwise successful batch solely because `status` is `no-candidates` or because React metadata was missing; failed upstream steps (for example `react inspect` without DevTools) still fail the batch normally.
|
|
574
|
-
|
|
575
|
-
```json
|
|
576
|
-
{ "sourceLookup": { "selector": "#save", "reactFiberId": "2", "componentName": "SaveButton" } }
|
|
577
|
-
```
|
|
578
|
-
|
|
579
|
-
This is an experiment, not a guarantee. React hints require a session opened with `--enable react-devtools`, and many builds do not expose useful sourcemap/source metadata; `status: "no-candidates"` is common when nothing matched, and `status: "unsupported"` only when no candidates were found **and** a compiled `react` batch step failed (if DOM or workspace search still produced candidates, you get `candidates-found` instead). For wrapper-tracked packaged Electron apps, a no-candidate result includes `details.sourceLookup.workspaceRoot`, optional `details.sourceLookup.electronContext`, limitations explaining that the scan is limited to the captured execution cwd and does not unpack app bundles/`app.asar`, plus Electron snapshot/probe/tab next actions when a launch is known.
|
|
495
|
+
Use the exact returned recovery payload after errors. Timeout partial progress distinguishes observed results from planned or unknown steps; it never proves an unobserved mutation did not run. For paced typing, native batch can interleave `keyboard type` characters and positional `wait <ms>` rows; see [the migration map](docs/TOOL_CONTRACT.md#07-migration). Do not assume a native `--delay` option reproduces the removed job behavior.
|
|
580
496
|
|
|
581
|
-
|
|
497
|
+
Both JSON and prose results expose a bounded canonical observation with recovery actions and artifact receipts. Oversized observations name an `observationPath` for the complete redacted result; audit-only `details` is not the model's sole recovery channel. Inner code calls avoid full model rendering, spills, and image encoding until output is selected.
|
|
582
498
|
|
|
583
|
-
|
|
584
|
-
{ "networkSourceLookup": { "requestId": "req-1", "url": "/api/fail" } }
|
|
585
|
-
```
|
|
586
|
-
|
|
587
|
-
For asynchronous exports, use the export control's current snapshot ref (for example `@e5`), then wait for the download:
|
|
588
|
-
|
|
589
|
-
```json
|
|
590
|
-
{ "args": ["click", "@e5"] }
|
|
591
|
-
{ "args": ["wait", "--download", "/tmp/report.csv"] }
|
|
592
|
-
```
|
|
499
|
+
Screenshots expose measured image dimensions and capture geometry when supported by matching before/after samples. A full-page or element image is not a viewport screenshot. Native mouse coordinates are viewport CSS pixels; use the [geometry contract](docs/TOOL_CONTRACT.md#image-observations) and current scroll/frame state before converting image pixels. Unknown geometry stays unknown, including ambiguous or scrolled element captures and unmeasured batch captures. Pi image-resize notes only map sent pixels to original image pixels.
|
|
593
500
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
For evidence-only screenshots or QA captures, branch on `details.artifactVerification` and `details.artifacts` before reporting PASS/FAIL; a pre-existing path from an artifact-producing command that was not updated during the command fails as `status: "stale"` instead of being accepted as fresh evidence (`wait --download` remains observational). Inline image attachments are optional when size limits allow—do not require vision review unless the user asked for visual inspection. If the latest prompt names exact required artifact paths, browser close can be blocked with `details.promptGuard` until those artifacts are saved and verified.
|
|
597
|
-
|
|
598
|
-
Artifact cleanup is host-owned, not a browser command. Close commands (`close`, `quit`, or `exit`) shut down the browser session but do **not** delete explicit screenshots, downloads, PDFs, traces, HAR files, or recordings saved to paths you chose. When the session’s non-empty `details.artifactManifest` is in scope, a successful close command appends a compact `Artifact lifecycle` note and sets `details.artifactCleanup` with the same retention summary as `details.artifactRetentionSummary`, a fixed `note` about host-owned cleanup, and `explicitArtifactPaths`: up to ten distinct paths from manifest rows whose `storageScope` is `explicit-path` (this list can be empty if the recent window only holds spills or other non-explicit inventory). Remove any listed paths with normal file tools after inspection.
|
|
599
|
-
|
|
600
|
-
Start a fresh profiled browser after the implicit public-browsing session already exists:
|
|
601
|
-
|
|
602
|
-
```json
|
|
603
|
-
{ "args": ["--profile", "Profile 1", "open", "https://example.com/account"], "sessionMode": "fresh" }
|
|
604
|
-
```
|
|
605
|
-
|
|
606
|
-
Start a fresh launch with a different Chromium-compatible executable:
|
|
607
|
-
|
|
608
|
-
```json
|
|
609
|
-
{
|
|
610
|
-
"args": ["--executable-path", "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser", "open", "https://example.com/account"],
|
|
611
|
-
"sessionMode": "fresh"
|
|
612
|
-
}
|
|
613
|
-
```
|
|
501
|
+
Save artifacts to the user's exact paths and check `artifactVerification` before claiming they exist or are fresh. Conditional `changed: false` screenshots produce no new attachment. `outputPath` is a separate result-data destination and must not alias a screenshot, download, or recording. Close ends the browser session; explicit files remain host-owned. Recording starts remain pending until stop and receipt/file verification.
|
|
614
502
|
|
|
615
|
-
|
|
503
|
+
### Upgrading from 0.6
|
|
616
504
|
|
|
617
|
-
|
|
505
|
+
Version 0.7 replaces top-level `script`/`job` and nested advanced input modes. Move script bodies to `agent_browser_code.code`, replace `.ok` with `.success`, and account for the now-persistent browser. Move fixed jobs to native batch; enable and call the flat advanced tools above. There is no parallel legacy public execution route. See [the complete migration map](docs/TOOL_CONTRACT.md#07-migration) and [package rollback](docs/RELEASE.md#07-upgrade-and-rollback).
|
|
618
506
|
|
|
619
|
-
|
|
507
|
+
Restart every participating Pi process onto the same updated package before relying on cross-process coordination. Package rollback means reinstalling the previously used 0.6 release and restarting those processes, preserving saved authentication, artifacts, and Pi transcripts; it does not undo browser actions.
|
|
620
508
|
|
|
621
509
|
### Working-directory changes
|
|
622
510
|
|
|
623
|
-
With `pi-change-working-dir`, each browser call captures the selected execution directory once. New relative screenshots, downloads, recordings, file inputs, `outputPath`, and source/network-source scans use that directory, including queued
|
|
511
|
+
With `pi-change-working-dir`, each browser call captures the selected execution directory once. New relative screenshots, downloads, recordings, file inputs, `outputPath`, and source/network-source scans use that directory, including queued batches and code calls. Absolute paths remain unchanged. Existing browsers, tabs, profiles, restore identities, pending recording destinations, cached artifacts, and Pi package config/trust remain anchored to their original owners.
|
|
624
512
|
|
|
625
513
|
Ordinary native config discovery stays at the project or current managed browser's launch directory. `--session` selects a target for that call; it does not switch the config root. An unnamed `sessionMode: "fresh"` launch and explicit `--config` / `AGENT_BROWSER_CONFIG` resolve from the selected execution directory, preserving native session precedence. Managed fresh launches retain their launch directory across follow-ups and resume. If the old launch directory is deleted, ordinary browser calls stop with recovery guidance instead of selecting another project's config; restore it or explicitly choose fresh/config from the new directory. Shell/file operations can continue independently. Older directory extensions must be updated and Pi restarted; without a directory extension, native Pi cwd remains the default.
|
|
626
514
|
|
|
@@ -630,7 +518,7 @@ Ordinary native config discovery stays at the project or current managed browser
|
|
|
630
518
|
|
|
631
519
|
Ordinary browser calls use one native named browser per **root Pi session**. A parent and its subagents share that browser; unrelated roots get different names and can browse concurrently. `pi-subagents` supplies `PI_SUBAGENT_ROOT_SESSION_ID` through its existing launch records, including detached runs, delegated forks, grandchildren, and revived children. Ordinary Pi new/fork/clone sessions get their own root identity; resuming the same root or changing its cwd keeps its browser name.
|
|
632
520
|
|
|
633
|
-
|
|
521
|
+
Cooperating updated Pi processes share a cross-process lock keyed by the actual socket context, canonical namespace, and session. It covers a direct call's helpers and action, or an entire code call; different identities can run independently. Coordinate navigation across separate tool calls with existing subagent/intercom tools. This is ordering, not rollback or protection against human navigation, external CLI clients, or older extension versions. Parent or child exit does not close the group browser. Native idle policy applies; explicitly close only your group's browser when the group is finished.
|
|
634
522
|
|
|
635
523
|
To bootstrap new root browsers from an authenticated normal Chrome profile, set the existing **Pi package** config in `~/.pi/config/pi-agent-browser-native/config.json`:
|
|
636
524
|
|
|
@@ -643,7 +531,7 @@ To bootstrap new root browsers from an authenticated normal Chrome profile, set
|
|
|
643
531
|
}
|
|
644
532
|
```
|
|
645
533
|
|
|
646
|
-
For inactive automatic roots, global/override `always` profile **names** and the configured executable bootstrap native launch through a scoped subprocess environment shared with helpers. Active roots retain native launch settings instead of resending defaults that could replace an explicitly profiled browser; their existing restore key is preserved, including follow-ups naming the same root browser. Native Chrome profile names use independent temporary copies, not the source profile's lock. Profile paths and other profile policies remain advisory; project guidance does not change a root's launch settings when a child changes cwd. Explicit unrelated sessions
|
|
534
|
+
For inactive automatic roots, global/override `always` profile **names** and the configured executable bootstrap native launch through a scoped subprocess environment shared with helpers. Active roots retain native launch settings instead of resending defaults that could replace an explicitly profiled browser; their existing restore key is preserved, including follow-ups naming the same root browser. Native Chrome profile names use independent temporary copies, not the source profile's lock. Profile paths and other profile policies remain advisory; project guidance does not change a root's launch settings when a child changes cwd. Explicit unrelated sessions and Electron launches do not receive root bootstrap defaults. Code calls selecting the ordinary root browser use its normal configuration and authenticated state. Do not set a global native profile merely to enable this feature: it can change the launch configuration of existing unrelated browsers.
|
|
647
535
|
|
|
648
536
|
Each automatic root has its own stable native restore key. Native save/restore preserves cookies, localStorage, and sessionStorage across normal close/restart; it does not merge auth between roots or save new IndexedDB-only credentials, service workers, or page-memory grants. Named profile copies can bootstrap existing IndexedDB, but are discarded on close and never write back to the communal profile. Verify the actual application after restart, not just a successful restore receipt. If an application needs unsupported state, use a supported persistent **per-root** profile and collect required sign-ins together; never point concurrent roots at one writable profile directory. Sites can expire sessions or require a fresh human challenge.
|
|
649
537
|
|
|
@@ -655,7 +543,7 @@ Full live identity, browser-independent native reads/confirmations and detailed
|
|
|
655
543
|
|
|
656
544
|
### Native working-session checkpoints
|
|
657
545
|
|
|
658
|
-
On Pi hosts with `session_checkpoint`, an unused or cleanly closed browser integration can qualify for sleep. Live browsers, attachments,
|
|
546
|
+
On Pi hosts with `session_checkpoint`, an unused or cleanly closed browser integration can qualify for sleep. Live browsers, attachments, active code calls, unfinished recordings/legacy cleanup leases, and dirty recording persistence keep compute alive. Pi core owns native journal flush/repair and strict restore; an ongoing journal I/O failure rejects checkpoint acquisition. Checkpointing never closes browsers or changes cleanup ownership. Native save-on-close and per-root restore remain the persistence path; page JavaScript, unsaved forms, and live recordings are not serialized. See [checkpoint boundaries](docs/ARCHITECTURE.md#native-checkpoint-boundary).
|
|
659
547
|
|
|
660
548
|
### Profile selection
|
|
661
549
|
|
|
@@ -669,9 +557,9 @@ Use these rules:
|
|
|
669
557
|
- Use `sessionMode: "fresh"` when switching from public browsing to `--allowed-domains`, `--profile`, `--executable-path`, `--webgpu`, `--restore`, `--restore-save`, restore check flags, `--namespace`, `--session-name`, `--cdp`, `--state`, `--auto-connect`, `--init-script`, `--enable`, `-p` / `--provider`, or iOS `--device`.
|
|
670
558
|
- Use `--session` when you want to manage a live upstream session name yourself. For CDP, connect once, verify with `get url`, keep using that session without repeating `--cdp`, and close it explicitly when done. The wrapper preserves the established attachment across follow-ups instead of resending local-launch defaults, and live-checks the URL before later page reads or interactions because an attached browser can change tabs outside Pi.
|
|
671
559
|
- Do not treat an arbitrary `--session` name alone as persisted auth after `close`, `quit`, or `exit`. Wrapper-owned implicit sessions automatically use a Pi-transcript- and Git-checkout-generation-scoped `AGENT_BROWSER_RESTORE` key so cookies and web storage can survive relaunch, reload, and `/resume`; disable that convenience with `PI_AGENT_BROWSER_MANAGED_SESSION_RESTORE=0`. Caller-selected sessions, restore/state paths, profiles, upstream config, file access, launch arguments, environment variables, and close arguments pass through unchanged. `session list` and `state list` keep all upstream rows and restore identifiers visible. The wrapper does not reserve `piab-*` names or reject cross-checkout/local paths. Automatic restore still validates its own checkout/storage identity and coordinates same-daemon reuse so it cannot mix the wrapper's restore pools.
|
|
672
|
-
- Caller-owned explicit sessions are live-checked with `get url` before content-bearing reads or interactions. Missing or stale transcript page state is not treated as proof of a target; if the live URL cannot be verified, the requested content command does not run. Calls to the same effective canonical namespace/session are serialized
|
|
560
|
+
- Caller-owned explicit sessions are live-checked with `get url` before content-bearing reads or interactions. Missing or stale transcript page state is not treated as proof of a target; if the live URL cannot be verified, the requested content command does not run. Calls to the same actual socket context and effective canonical namespace/session are serialized across cooperating updated Pi processes; explicit namespace argv overrides `AGENT_BROWSER_NAMESPACE`, including an explicit empty default from that probe through any semantic-action snapshot and the requested command, while different caller-owned sessions remain independent. Raw non-bail batches are rejected when a failed navigation could leave an unverified target before later content; use exact `batch --bail` or split navigation from content. Nested `batch` steps are rejected, and raw batch command strings mirror upstream's ASCII-space tokenizer, including its single/double-quote and backslash handling, without splitting on other Unicode whitespace.
|
|
673
561
|
- Prefer page actions and storage checks over cookie dumps. `cookies get` can expose real profile cookies.
|
|
674
|
-
- Prefer `auth save --password-stdin` over putting passwords in `args`; the wrapper only accepts caller `stdin` for `batch`, `eval --stdin`, and `auth save --password-stdin` (
|
|
562
|
+
- Prefer `auth save --password-stdin` over putting passwords in `args`; the wrapper only accepts caller `stdin` for `batch`, `eval --stdin`, and `auth save --password-stdin` (advanced QA and source tools generate their own batch stdin).
|
|
675
563
|
- Use `state save <path>` / `state load <path>` for portable test state. `state save` is reported as a file artifact with verification metadata; if an upstream-successful artifact command reports a non-pending file path that the wrapper cannot find or did not update during this command, the tool fails with `failureCategory: "artifact-missing"` instead of treating missing/stale evidence as durable. `state load` may mention a path but is not treated as a newly saved artifact.
|
|
676
564
|
- Treat `cookies get`, `storage local|session`, `state show`, and `auth show` output as sensitive. `state show` is presented as saved-state metadata only, and cookie/localStorage/sessionStorage values are redacted from structured details. The native presentation summarizes and redacts credential-like values while allowing benign primitive storage values to aid local QA, but avoid requesting broad dumps unless the task needs them.
|
|
677
565
|
- Use `dialog status`, `dialog accept [text]`, `dialog dismiss`, and `frame <selector|main>` through native `args`; dialog commands use a shorter wrapper timeout and timed-out interactions add `inspect-dialog-after-timeout` / `dismiss-dialog-after-timeout` / fresh-session recovery actions so a blocking alert/prompt does not burn the full default watchdog. Use exact `confirm <id>` / `deny <id>` next actions for guarded-action confirmations.
|
|
@@ -786,7 +674,7 @@ A deterministic host-only live-browser wrapper smoke is available without an LLM
|
|
|
786
674
|
npm run verify -- dogfood
|
|
787
675
|
```
|
|
788
676
|
|
|
789
|
-
That mode clean-builds the package, then drives
|
|
677
|
+
That mode clean-builds the package, then drives persistent browser code, advanced QA/actions, native batch, screenshot artifact verification, and session close against a deterministic local fixture. It complements, but does not replace, the interactive Pi/tmux release dogfood in [`docs/RELEASE.md`](docs/RELEASE.md#pre-release-checks).
|
|
790
678
|
|
|
791
679
|
Cross-platform release coverage uses Crabbox to run macOS, Ubuntu Linux, and native Windows target suites; see [`docs/platform-smoke.md`](docs/platform-smoke.md) for the required matrix, standalone coverage (`npm run smoke:platform:all` and per-target `smoke:platform:macos` / `:ubuntu` / `:windows-native`), and artifact/lease inspection. The release gate is:
|
|
792
680
|
|
|
@@ -805,7 +693,7 @@ npm run verify -- release
|
|
|
805
693
|
`pi-agent-browser-native` is intentionally thin:
|
|
806
694
|
|
|
807
695
|
1. Pi loads the compiled `dist/extensions/agent-browser/index.js` entrypoint from the package manifest; TypeScript under `extensions/` remains the source of truth and `npm run build` regenerates `dist/` before packing.
|
|
808
|
-
2. The extension registers
|
|
696
|
+
2. The extension registers compact direct/code tools, an advanced-tool loader with five initially inactive specialized tools, and the optional credential-backed `agent_browser_web_search` companion.
|
|
809
697
|
3. Tool calls are translated into upstream `agent-browser` CLI invocations with controlled args, stdin, environment, timeout, and session planning.
|
|
810
698
|
4. Upstream JSON/plain-text output is parsed into model-friendly content and structured details.
|
|
811
699
|
5. Screenshots, downloads, recordings, traces, profiles, and spill files are normalized as Pi-visible artifacts where possible.
|
|
@@ -832,7 +720,7 @@ Install upstream `agent-browser`, then install dependencies:
|
|
|
832
720
|
npm install
|
|
833
721
|
```
|
|
834
722
|
|
|
835
|
-
Use the npm version declared in `package.json` `packageManager` when refreshing `package-lock.json` (for example `npx -y npm@11.14.0 install`) so optional-platform lockfile metadata does not drift. Use Pi 0.
|
|
723
|
+
Use the npm version declared in `package.json` `packageManager` when refreshing `package-lock.json` (for example `npx -y npm@11.14.0 install`) so optional-platform lockfile metadata does not drift. Use Pi 0.87.0 or newer for lifecycle and interactive browser smokes; the pinned Pi devDependencies are validation fixtures, not an exact-version requirement for the host CLI. See [Environment and automation pitfalls](docs/RELEASE.md#environment-and-automation-pitfalls) in `docs/RELEASE.md`.
|
|
836
724
|
|
|
837
725
|
Checkout-only extension smoke test:
|
|
838
726
|
|