pi-agent-browser-native 0.2.69 → 0.2.71
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 +36 -0
- package/README.md +4 -4
- package/dist/extensions/agent-browser/index.js +3 -4
- package/dist/extensions/agent-browser/lib/config-policy.js +3 -24
- package/dist/extensions/agent-browser/lib/config.js +0 -14
- package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +4 -0
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.js +42 -10
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +46 -29
- package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +2 -1
- package/dist/extensions/agent-browser/lib/playbook.js +1 -8
- package/dist/extensions/agent-browser/lib/process.js +9 -3
- package/dist/extensions/agent-browser/lib/results/editable-ref-evidence.js +0 -3
- package/dist/extensions/agent-browser/lib/runtime.js +0 -1
- package/docs/ARCHITECTURE.md +4 -3
- package/docs/COMMAND_REFERENCE.md +2 -2
- package/docs/ELECTRON.md +2 -2
- package/docs/RELEASE.md +4 -4
- package/docs/REQUIREMENTS.md +2 -7
- package/docs/SUPPORT_MATRIX.md +21 -20
- package/docs/TOOL_CONTRACT.md +10 -9
- package/package.json +1 -2
- package/platform-smoke.config.mjs +2 -3
- package/scripts/platform-smoke.mjs +1 -2
- package/dist/extensions/agent-browser/lib/orchestration/browser-run.js +0 -1
- package/dist/extensions/agent-browser/lib/results/shared.js +0 -20
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.71 - 2026-07-18
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- Applied the same managed-session `AGENT_BROWSER_IDLE_TIMEOUT_MS` to top-level commands and every wrapper helper subprocess. With upstream 0.32.2, missing the value on hidden snapshots, tab lists, navigation summaries, and diagnostics could restart the background browser, replace the active page with `about:blank`, and make a freshly captured `@ref` fail on the next click or select.
|
|
8
|
+
- Refreshed the remaining active tab URL/title after `tab close` so subsequent snapshots, ref guards, and interactions no longer inherit the closed tab's target.
|
|
9
|
+
- Made ordinary document `scroll <direction> [amount]` deterministic before upstream wheel fallback, including pages such as Artificial Analysis whose smooth-scroll CSS previously left large scroll commands at offset zero.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Extended the real-upstream contract with snapshot-ref native selection and stable-id/label tab lifecycle coverage, and corrected fake/docs tab examples from unsupported positional `tab 0` to stable `tab t1`.
|
|
14
|
+
|
|
15
|
+
### Validation
|
|
16
|
+
|
|
17
|
+
- Passed `npm run verify` (590 tests passed, 2 opt-in skips), live command-reference verification, the expanded 2/2 real-upstream contract, deterministic dogfood, benchmark, packaged Pi smoke, and three-sample startup profiling (50.1 ms maximum against the 250 ms budget).
|
|
18
|
+
- Passed isolated checkout-loaded Pi dogfood on Artificial Analysis, React, GitHub, and a deterministic select/tab fixture. Artificial Analysis document scroll moved from offset 0 to 700; snapshot-ref select/click, stable-id/label tab switching, post-close target refresh, and post-close interaction completed with no background restarts, `about:blank` resets, or spurious stale-ref failures.
|
|
19
|
+
- Passed `npm run verify -- release`, including configured-source reload/relaunch lifecycle, packaged Pi smoke, and macOS/Ubuntu/native-Windows Crabbox `platform-build` plus `browser-dogfood-smoke`; all provider leases and browser sessions were cleaned.
|
|
20
|
+
|
|
21
|
+
## 0.2.70 - 2026-07-18
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Removed unused TypeScript imports, locals, exports, declaration sidecars, compatibility barrels, inert `browser.defaultLaunchArgs` config handling, and duplicated platform/build orchestration while preserving the browser runtime contract.
|
|
26
|
+
- Condensed completed plans and the historical support ledger into current ADR/decision indexes, removed obsolete archive material, and enabled `noUnusedLocals` for ongoing enforcement.
|
|
27
|
+
- Kept one guaranteed build owner before every `dist/` consumer; package verification now lets `prepare` create a missing `dist/` before expanding the publish contract and forbids internal `docs/plans/` content by prefix.
|
|
28
|
+
|
|
29
|
+
### Compatibility
|
|
30
|
+
|
|
31
|
+
- Undocumented deep imports through `lib/results/shared.js` or `lib/orchestration/browser-run.js`, the inert `browser.defaultLaunchArgs` config field, unused named platform-config exports, and the redundant default-export `supportedTargets` platform-smoke property are no longer supported. Native `agent_browser` behavior and documented package entrypoints are unchanged.
|
|
32
|
+
|
|
33
|
+
### Validation
|
|
34
|
+
|
|
35
|
+
- Passed `npm run verify -- release` (587 tests passed, 2 opt-in skips), configured-source lifecycle, packaged Pi smoke, live command-reference verification, and macOS/Ubuntu/native-Windows Crabbox `platform-build` plus `browser-dogfood-smoke` suites.
|
|
36
|
+
- Passed opt-in real-upstream, deterministic dogfood, benchmark, and startup-profile gates; the three-sample startup maximum was 51.9 ms against the 250 ms budget.
|
|
37
|
+
- Passed a checkout-loaded Pi 0.80.10 tmux smoke on `example.com` and `react.dev`, including QA, fresh-session snapshot/link navigation, verified screenshot evidence, recovery from stale selector attempts, and zero active browser sessions after cleanup.
|
|
38
|
+
|
|
3
39
|
## 0.2.69 - 2026-07-17
|
|
4
40
|
|
|
5
41
|
### Changed
|
package/README.md
CHANGED
|
@@ -74,13 +74,13 @@ The result is optimized for agent work:
|
|
|
74
74
|
| Agents build fragile shell commands | Exposes `agent_browser` with exact `args`, an optional `semanticAction` shorthand for common `find` flows and native `select`, constrained `job` / `qa` presets, experimental `sourceLookup` / `networkSourceLookup` that compile short workflows to `batch`, top-level `electron` for desktop lifecycle, plus controlled `stdin` and `sessionMode` | `extensions/agent-browser/index.ts`, `extensions/agent-browser/lib/input-modes/`, [`docs/TOOL_CONTRACT.md`](docs/TOOL_CONTRACT.md) |
|
|
75
75
|
| 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 raw 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` |
|
|
76
76
|
| Screenshots/downloads get lost in text | Normalizes artifact paths, creates missing parent directories, saves simple loopback anchor downloads to the requested path when possible, and reports existence, size, cwd, session, and repair status | [`docs/COMMAND_REFERENCE.md`](docs/COMMAND_REFERENCE.md#download-screenshot-and-pdf-files) |
|
|
77
|
-
| Profile restores and tab drift confuse agents | Tracks managed sessions, re-selects target tabs after observed drift, 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.
|
|
77
|
+
| 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, refreshes the active target after `tab close`, 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) |
|
|
78
78
|
| Auth/profile workflows can leak secrets | Supports `auth save --password-stdin` and redacts sensitive args, URLs, stdout/stderr, details, and parse-failure spills | `test/agent-browser.extension-security-redaction.test.ts` |
|
|
79
79
|
| 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` |
|
|
80
80
|
| 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` |
|
|
81
|
-
| 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/
|
|
81
|
+
| 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` |
|
|
82
82
|
| 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 use the latest snapshot role/name metadata, and duplicate-name refs use snapshot-order `duplicateIndex` rather than requiring a unique name. 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`, and 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` |
|
|
83
|
-
| Dashboard scroll commands can look successful while nothing moves |
|
|
83
|
+
| 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; unchanged positions produce `details.scrollNoop`, visible recovery guidance, and exact snapshot/screenshot checks | [`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` |
|
|
84
84
|
| Dropdown/combobox clicks can focus or hit native option box-model errors | Adds first-class `select <selector> <value...>` paths through raw `args`, `semanticAction`, and `job`; for custom combobox clicks, detects focused controls with explicit `aria-expanded` state but no visible options and returns `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` |
|
|
85
85
|
| Recording workflows fail late when `ffmpeg` is missing | After successful `record start` / `record restart`, warns when `ffmpeg` is not on `PATH` so agents can install or fix PATH before `record stop` | [`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` |
|
|
86
86
|
| Direct binary help may be blocked in agent sessions | Publishes a repo-readable command reference and verifies it against the target upstream version | `npm run verify` |
|
|
@@ -601,7 +601,7 @@ For larger local handoffs or PR-ready confidence before expensive release/lifecy
|
|
|
601
601
|
npm run verify -- pre-pr
|
|
602
602
|
```
|
|
603
603
|
|
|
604
|
-
That mode composes the full default gate with `npm run verify -- package`, so package contents and forbidden
|
|
604
|
+
That mode composes the full default gate with `npm run verify -- package`, so package contents and forbidden repo-only files are checked without launching Pi lifecycle, Crabbox, or live dogfood flows. Package modes build through npm `prepare`; lifecycle and startup-profile build in their focused scripts; default and platform-target build before consuming `dist/`, so clean checkouts do not validate stale or missing compiled output. The same `prepare` script owns GitHub/source installs; when Pi installs with `npm install --omit=dev`, it installs the source-build dev dependencies with lifecycle scripts disabled before building the ignored `dist/` entrypoint that Pi loads.
|
|
605
605
|
|
|
606
606
|
The deterministic agent-efficiency benchmark’s **standalone JSON/Markdown accounting run** is not part of default or pre-PR `npm run verify` (only `npm run verify -- benchmark` or `npm run benchmark:agent-browser` invokes the script). The full unit suite still exercises `test/agent-browser.efficiency-benchmark.test.ts`. Use the script before and after agent-facing abstractions to prove call-count, output-size, stale-ref, artifact, failure-category coverage, success-rate, and elapsed-time effects before changing the wrapper UX:
|
|
607
607
|
|
|
@@ -15,21 +15,20 @@ import { createEphemeralSessionSeed, createFreshSessionName, createImplicitSessi
|
|
|
15
15
|
import { isRecord } from "./lib/parsing.js";
|
|
16
16
|
import { buildPromptPolicy, getLatestUserPrompt, shouldAppendBrowserSystemPrompt } from "./lib/prompt-policy.js";
|
|
17
17
|
import { isCloseCommand } from "./lib/command-taxonomy.js";
|
|
18
|
-
import { cleanupSecureTempArtifacts
|
|
18
|
+
import { cleanupSecureTempArtifacts } from "./lib/temp.js";
|
|
19
19
|
import { AGENT_BROWSER_PARAMS, } from "./lib/input-modes.js";
|
|
20
20
|
import { parseAllowedDomainsPolicyFromArgs } from "./lib/navigation-policy.js";
|
|
21
|
-
import { closeManagedSession, getSessionContextKey, runAgentBrowserTool } from "./lib/orchestration/browser-run.js";
|
|
21
|
+
import { closeManagedSession, getSessionContextKey, runAgentBrowserTool } from "./lib/orchestration/browser-run/index.js";
|
|
22
22
|
import { findElectronLaunchRecordForSession, getActiveElectronRecords } from "./lib/orchestration/browser-run/session-state.js";
|
|
23
23
|
import { parseBatchStdinJsonArray } from "./lib/orchestration/batch-stdin.js";
|
|
24
24
|
import { ELECTRON_POST_COMMAND_STATUS_SETTLE_MS, ELECTRON_PROFILE_ISOLATION_DETAILS, cleanupActiveElectronHostLaunches, handleElectronHostInput, restoreElectronLaunchRecordsFromBranch, } from "./lib/orchestration/electron-host/index.js";
|
|
25
25
|
import { buildValidationFailureResult, resolveAgentBrowserInput } from "./lib/orchestration/input-plan.js";
|
|
26
26
|
import { applyAgentBrowserOutputPath } from "./lib/orchestration/output-file.js";
|
|
27
|
-
import { isSessionArtifactManifest
|
|
27
|
+
import { isSessionArtifactManifest } from "./lib/results/artifact-manifest.js";
|
|
28
28
|
import { canRegisterWebSearchTool, loadAgentBrowserConfigSync } from "./lib/config.js";
|
|
29
29
|
import { createAgentBrowserWebSearchTool } from "./lib/web-search.js";
|
|
30
30
|
import { isDirectAgentBrowserBashAllowed, isHarmlessAgentBrowserInspectionCommand, looksLikeDirectAgentBrowserBash, } from "./lib/bash-guard.js";
|
|
31
31
|
import { AgentBrowserResultComponent, buildAgentBrowserToolResultPatch, formatAgentBrowserRenderCall, formatAgentBrowserRenderResult, } from "./lib/pi-tool-rendering.js";
|
|
32
|
-
const DEFAULT_SESSION_MODE = "auto";
|
|
33
32
|
function isBashToolCallEvent(event) {
|
|
34
33
|
if (!isRecord(event) || event.toolName !== "bash" || !isRecord(event.input))
|
|
35
34
|
return false;
|
|
@@ -16,7 +16,7 @@ import { join, resolve } from "node:path";
|
|
|
16
16
|
/** @typedef {{ provider: WebSearchProvider; apiKeyEnv: string; configKey: WebSearchProviderConfigKey; label: string }} WebSearchProviderDescriptor */
|
|
17
17
|
/** @typedef {{ name: string; policy?: BrowserDefaultProfilePolicy }} BrowserDefaultProfileConfig */
|
|
18
18
|
/** @typedef {{ enabled?: boolean; preferredProvider?: WebSearchProvider; braveApiKey?: string; exaApiKey?: string }} WebSearchConfig */
|
|
19
|
-
/** @typedef {{ defaultProfile?: BrowserDefaultProfileConfig; executablePath?: string
|
|
19
|
+
/** @typedef {{ defaultProfile?: BrowserDefaultProfileConfig; executablePath?: string }} BrowserConfig */
|
|
20
20
|
/** @typedef {{ version?: 1; webSearch?: WebSearchConfig; browser?: BrowserConfig }} AgentBrowserConfig */
|
|
21
21
|
/** @typedef {{ config: AgentBrowserConfig; path: string; scope: ConfigLayerScope }} ConfigLayer */
|
|
22
22
|
/** @typedef {{ kind: CredentialSourceKind; provider?: WebSearchProvider; rawValue: string; scope: AgentBrowserConfigScope }} CredentialSource */
|
|
@@ -155,21 +155,6 @@ function validateString(value, path, errors) {
|
|
|
155
155
|
}
|
|
156
156
|
return value;
|
|
157
157
|
}
|
|
158
|
-
/**
|
|
159
|
-
* @param {unknown} value
|
|
160
|
-
* @param {string} path
|
|
161
|
-
* @param {string[]} errors
|
|
162
|
-
* @returns {string[] | undefined}
|
|
163
|
-
*/
|
|
164
|
-
function validateStringArray(value, path, errors) {
|
|
165
|
-
if (value === undefined)
|
|
166
|
-
return undefined;
|
|
167
|
-
if (!Array.isArray(value) || value.some((entry) => typeof entry !== "string")) {
|
|
168
|
-
errors.push(`${path} must be an array of strings.`);
|
|
169
|
-
return undefined;
|
|
170
|
-
}
|
|
171
|
-
return value;
|
|
172
|
-
}
|
|
173
158
|
/**
|
|
174
159
|
* @param {unknown} value
|
|
175
160
|
* @param {string} path
|
|
@@ -244,12 +229,11 @@ export function isProjectSafeCredentialValueForProvider(rawValue, provider) {
|
|
|
244
229
|
/**
|
|
245
230
|
* @param {unknown} value
|
|
246
231
|
* @param {string} path
|
|
247
|
-
* @param {ConfigLayerScope} scope
|
|
248
232
|
* @param {string[]} errors
|
|
249
233
|
* @param {string[]} warnings
|
|
250
234
|
* @returns {AgentBrowserConfig | undefined}
|
|
251
235
|
*/
|
|
252
|
-
export function validateAgentBrowserConfig(value, path,
|
|
236
|
+
export function validateAgentBrowserConfig(value, path, errors, warnings) {
|
|
253
237
|
if (!isRecord(value)) {
|
|
254
238
|
errors.push(`${path} must contain a JSON object.`);
|
|
255
239
|
return undefined;
|
|
@@ -297,11 +281,6 @@ export function validateAgentBrowserConfig(value, path, scope, errors, warnings)
|
|
|
297
281
|
if (executablePath) {
|
|
298
282
|
config.browser.executablePath = executablePath;
|
|
299
283
|
}
|
|
300
|
-
const defaultLaunchArgs = validateStringArray(value.browser.defaultLaunchArgs, `${path}.browser.defaultLaunchArgs`, errors);
|
|
301
|
-
if (defaultLaunchArgs) {
|
|
302
|
-
config.browser.defaultLaunchArgs = defaultLaunchArgs;
|
|
303
|
-
warnings.push(`${path}.browser.defaultLaunchArgs is recorded for future use; current releases do not auto-inject default launch args.`);
|
|
304
|
-
}
|
|
305
284
|
}
|
|
306
285
|
}
|
|
307
286
|
for (const key of Object.keys(value)) {
|
|
@@ -328,7 +307,7 @@ export function parseAgentBrowserConfigLayer(raw, path, scope, errors, warnings)
|
|
|
328
307
|
errors.push(`Could not parse ${scope} config ${path}: ${error instanceof Error ? error.message : String(error)}`);
|
|
329
308
|
return undefined;
|
|
330
309
|
}
|
|
331
|
-
const config = validateAgentBrowserConfig(parsed, path,
|
|
310
|
+
const config = validateAgentBrowserConfig(parsed, path, errors, warnings);
|
|
332
311
|
return config ? { config, path, scope } : undefined;
|
|
333
312
|
}
|
|
334
313
|
/**
|
|
@@ -106,17 +106,3 @@ export async function resolvePreferredWebSearchCredential(state, options = {}) {
|
|
|
106
106
|
}
|
|
107
107
|
return undefined;
|
|
108
108
|
}
|
|
109
|
-
export async function hasResolvableCredentialSource(state, options = {}) {
|
|
110
|
-
if (!state.webSearchEnabled || state.errors.length > 0)
|
|
111
|
-
return false;
|
|
112
|
-
for (const provider of getWebSearchProviderOrder(state)) {
|
|
113
|
-
const source = getWebSearchCredentialSource(state, provider);
|
|
114
|
-
if (!source)
|
|
115
|
-
continue;
|
|
116
|
-
if (source.kind === "command")
|
|
117
|
-
return true;
|
|
118
|
-
if ((await resolveCredentialSource(source, options))?.value)
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
@@ -36,6 +36,10 @@ export const LAUNCH_SCOPED_FLAG_DEFINITIONS = [
|
|
|
36
36
|
flag: "--init-script",
|
|
37
37
|
reason: "registers page init scripts before the upstream browser session is launched",
|
|
38
38
|
},
|
|
39
|
+
{
|
|
40
|
+
flag: "--idle-timeout",
|
|
41
|
+
reason: "configures background browser lifecycle for the launched session",
|
|
42
|
+
},
|
|
39
43
|
{
|
|
40
44
|
flag: "--device",
|
|
41
45
|
reason: "selects the provider device for the upstream launch",
|
|
@@ -53,6 +53,7 @@ function buildScrollResult(options) {
|
|
|
53
53
|
compatibilityWorkaround: options.compatibilityWorkaround,
|
|
54
54
|
data: options.result,
|
|
55
55
|
effectiveArgs: options.effectiveArgs,
|
|
56
|
+
exitCode: options.succeeded ? 0 : 1,
|
|
56
57
|
nextActions: options.succeeded ? undefined : applyNamespaceToNextActions(buildScrollNoopNextActions(options.sessionName), options.namespace),
|
|
57
58
|
[options.scrollField]: options.scrollValue,
|
|
58
59
|
sessionMode: options.sessionMode,
|
|
@@ -79,24 +80,52 @@ export async function tryContainerScroll(options) {
|
|
|
79
80
|
return buildScrollResult({ ...options, command: "scroll", message, result, scrollField: "scrollContainer", scrollValue: { request, result }, succeeded });
|
|
80
81
|
}
|
|
81
82
|
function getPageScrollToRequest(commandTokens) {
|
|
82
|
-
if (commandTokens[0] !== "scroll"
|
|
83
|
+
if (commandTokens[0] !== "scroll")
|
|
83
84
|
return undefined;
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
if (commandTokens[1]?.toLowerCase() === "to") {
|
|
86
|
+
const target = commandTokens[2]?.toLowerCase();
|
|
87
|
+
return target === "end" || target === "top" ? { target } : undefined;
|
|
88
|
+
}
|
|
89
|
+
const direction = commandTokens[1]?.toLowerCase();
|
|
90
|
+
if (!SCROLL_CONTAINER_DIRECTIONS.has(direction) || commandTokens.length > 3)
|
|
91
|
+
return undefined;
|
|
92
|
+
const amount = commandTokens[2];
|
|
93
|
+
if (amount && (!/^\d+(?:\.\d+)?(?:px|%)?$/.test(amount) || Number(amount.replace(/(?:px|%)$/, "")) <= 0))
|
|
94
|
+
return undefined;
|
|
95
|
+
return { amount, direction: direction };
|
|
86
96
|
}
|
|
87
97
|
function buildPageScrollToScript(request) {
|
|
88
98
|
return `(() => {
|
|
89
|
-
const target = ${JSON.stringify(request.target)};
|
|
99
|
+
const target = ${JSON.stringify("target" in request ? request.target : undefined)};
|
|
100
|
+
const direction = ${JSON.stringify("direction" in request ? request.direction : undefined)};
|
|
101
|
+
const amountToken = ${JSON.stringify("amount" in request ? request.amount ?? "" : "")};
|
|
102
|
+
const request = target ? { target } : { direction, amount: amountToken || undefined };
|
|
90
103
|
const scroller = document.scrollingElement || document.documentElement || document.body;
|
|
91
|
-
if (!scroller) return { status: "no-scroller",
|
|
104
|
+
if (!scroller) return { status: "no-scroller", ...request };
|
|
92
105
|
const before = { scrollLeft: scroller.scrollLeft, scrollTop: scroller.scrollTop, scrollHeight: scroller.scrollHeight, scrollWidth: scroller.scrollWidth, clientHeight: scroller.clientHeight, clientWidth: scroller.clientWidth };
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
|
|
106
|
+
const axis = direction === "left" || direction === "right" ? "x" : "y";
|
|
107
|
+
const extent = axis === "x" ? scroller.clientWidth : scroller.clientHeight;
|
|
108
|
+
const parseAmount = () => {
|
|
109
|
+
if (!amountToken) return Math.max(1, Math.floor(extent * 0.8));
|
|
110
|
+
if (amountToken.endsWith("%")) {
|
|
111
|
+
const value = Number(amountToken.slice(0, -1));
|
|
112
|
+
return Number.isFinite(value) ? Math.max(1, Math.floor(extent * value / 100)) : Math.max(1, Math.floor(extent * 0.8));
|
|
113
|
+
}
|
|
114
|
+
const pixels = Number(amountToken.replace(/px$/, ""));
|
|
115
|
+
return Number.isFinite(pixels) && pixels > 0 ? Math.floor(pixels) : Math.max(1, Math.floor(extent * 0.8));
|
|
116
|
+
};
|
|
117
|
+
const delta = parseAmount() * (direction === "up" || direction === "left" ? -1 : 1);
|
|
118
|
+
const nextTop = target === "top" ? 0 : target === "end" ? Math.max(0, scroller.scrollHeight - scroller.clientHeight) : axis === "y" ? scroller.scrollTop + delta : scroller.scrollTop;
|
|
119
|
+
const nextLeft = axis === "x" ? scroller.scrollLeft + delta : scroller.scrollLeft;
|
|
120
|
+
const priorBehavior = scroller.style.scrollBehavior;
|
|
121
|
+
scroller.style.scrollBehavior = "auto";
|
|
96
122
|
window.scrollTo(nextLeft, nextTop);
|
|
123
|
+
scroller.scrollLeft = nextLeft;
|
|
124
|
+
scroller.scrollTop = nextTop;
|
|
97
125
|
const after = { scrollLeft: scroller.scrollLeft, scrollTop: scroller.scrollTop, scrollHeight: scroller.scrollHeight, scrollWidth: scroller.scrollWidth, clientHeight: scroller.clientHeight, clientWidth: scroller.clientWidth };
|
|
126
|
+
scroller.style.scrollBehavior = priorBehavior;
|
|
98
127
|
const moved = before.scrollLeft !== after.scrollLeft || before.scrollTop !== after.scrollTop;
|
|
99
|
-
return { status: moved ? "scrolled" : "no-movement",
|
|
128
|
+
return { status: moved ? "scrolled" : "no-movement", ...request, before, after };
|
|
100
129
|
})()`;
|
|
101
130
|
}
|
|
102
131
|
export async function tryPageScrollTo(options) {
|
|
@@ -108,6 +137,9 @@ export async function tryPageScrollTo(options) {
|
|
|
108
137
|
if (!isRecord(result) || typeof result.status !== "string")
|
|
109
138
|
return undefined;
|
|
110
139
|
const succeeded = result.status === "scrolled";
|
|
111
|
-
|
|
140
|
+
if (!succeeded && "direction" in request)
|
|
141
|
+
return undefined;
|
|
142
|
+
const description = "target" in request ? `to ${request.target}` : `${request.direction}${request.amount ? ` by ${request.amount}` : ""}`;
|
|
143
|
+
const message = succeeded ? `Scrolled page ${description}.` : `Scroll ${description} completed with no observed movement (${result.status}).`;
|
|
112
144
|
return buildScrollResult({ ...options, command: "scroll", message, result, scrollField: "scrollPage", scrollValue: { request, result }, succeeded });
|
|
113
145
|
}
|
|
@@ -253,6 +253,18 @@ async function collectSamePageRefFreshnessPreflight(options) {
|
|
|
253
253
|
return undefined;
|
|
254
254
|
return { message: mismatch.message, refIds: mismatch.refIds, snapshot: snapshotWithTarget };
|
|
255
255
|
}
|
|
256
|
+
function getIdleTimeoutMismatch(args, configuredValue) {
|
|
257
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
258
|
+
const token = args[index];
|
|
259
|
+
if (token !== "--idle-timeout" && !token.startsWith("--idle-timeout="))
|
|
260
|
+
continue;
|
|
261
|
+
const requestedToken = token.includes("=") ? token.slice(token.indexOf("=") + 1) : args[++index];
|
|
262
|
+
if (!requestedToken || !/^\d+$/.test(requestedToken) || Number(requestedToken) === Number(configuredValue))
|
|
263
|
+
continue;
|
|
264
|
+
return `--idle-timeout ${requestedToken} conflicts with this Pi process's managed-session idle timeout (${configuredValue} ms). Restart Pi with PI_AGENT_BROWSER_IMPLICIT_SESSION_IDLE_TIMEOUT_MS=${requestedToken} and omit --idle-timeout; changing the launch value for one call can restart the upstream browser and discard the active tab.`;
|
|
265
|
+
}
|
|
266
|
+
return undefined;
|
|
267
|
+
}
|
|
256
268
|
function isPasswordStdinAuthSave(options) {
|
|
257
269
|
return options.command === "auth" && options.commandTokens[1] === "save" && options.commandTokens.includes("--password-stdin");
|
|
258
270
|
}
|
|
@@ -296,7 +308,7 @@ export async function resolveSemanticActionVisibleRefArgs(options) {
|
|
|
296
308
|
return resolveSemanticActionVisibleRefArgsFromSnapshot(options.compiled, snapshotData);
|
|
297
309
|
}
|
|
298
310
|
export async function prepareBrowserRun(options) {
|
|
299
|
-
const { cwd,
|
|
311
|
+
const { cwd, onUpdate, params, signal, state } = options;
|
|
300
312
|
const { sessionPageState, traceOwners, managedSessionBaseName, ephemeralSessionSeed } = state;
|
|
301
313
|
let freshSessionOrdinal = state.freshSessionOrdinal;
|
|
302
314
|
const { compiledElectron, compiledJob, compiledNetworkSourceLookup, compiledQaPreset, compiledSemanticAction, compiledSourceLookup, redactedArgs, redactedCompiledElectron, redactedCompiledJob, redactedCompiledNetworkSourceLookup, redactedCompiledQaPreset, redactedCompiledSemanticAction, redactedCompiledSourceLookup, toolArgs, toolStdin, } = normalizeRunInput(options.input);
|
|
@@ -340,6 +352,9 @@ export async function prepareBrowserRun(options) {
|
|
|
340
352
|
managedSessionNamespace: state.managedSessionNamespace,
|
|
341
353
|
sessionMode,
|
|
342
354
|
});
|
|
355
|
+
const idleTimeoutMismatch = getIdleTimeoutMismatch(preparedArgs.args, options.implicitSessionIdleTimeoutMs);
|
|
356
|
+
if (idleTimeoutMismatch)
|
|
357
|
+
executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: idleTimeoutMismatch };
|
|
343
358
|
const sessionStateKey = getSessionContextKey(executionPlan.sessionName, executionPlan.namespace);
|
|
344
359
|
const priorSessionPageState = sessionPageState.get(sessionStateKey);
|
|
345
360
|
const priorSessionTabTarget = priorSessionPageState.tabTarget;
|
|
@@ -581,34 +596,36 @@ export async function prepareBrowserRun(options) {
|
|
|
581
596
|
});
|
|
582
597
|
if (networkRequestsPageFilter)
|
|
583
598
|
return { kind: "early-result", statePatch, result: networkRequestsPageFilter };
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
599
|
+
if (executionPlan.startupScopedFlags.length === 0) {
|
|
600
|
+
const containerScroll = await tryContainerScroll({
|
|
601
|
+
commandTokens,
|
|
602
|
+
compatibilityWorkaround,
|
|
603
|
+
cwd,
|
|
604
|
+
effectiveArgs: redactedEffectiveArgs,
|
|
605
|
+
redactedArgs,
|
|
606
|
+
sessionMode,
|
|
607
|
+
namespace: executionPlan.namespace,
|
|
608
|
+
sessionName: executionPlan.sessionName,
|
|
609
|
+
signal,
|
|
610
|
+
usedImplicitSession: executionPlan.usedImplicitSession,
|
|
611
|
+
});
|
|
612
|
+
if (containerScroll)
|
|
613
|
+
return { kind: "early-result", statePatch, result: containerScroll };
|
|
614
|
+
const pageScrollTo = await tryPageScrollTo({
|
|
615
|
+
commandTokens,
|
|
616
|
+
compatibilityWorkaround,
|
|
617
|
+
cwd,
|
|
618
|
+
effectiveArgs: redactedEffectiveArgs,
|
|
619
|
+
redactedArgs,
|
|
620
|
+
sessionMode,
|
|
621
|
+
namespace: executionPlan.namespace,
|
|
622
|
+
sessionName: executionPlan.sessionName,
|
|
623
|
+
signal,
|
|
624
|
+
usedImplicitSession: executionPlan.usedImplicitSession,
|
|
625
|
+
});
|
|
626
|
+
if (pageScrollTo)
|
|
627
|
+
return { kind: "early-result", statePatch, result: pageScrollTo };
|
|
628
|
+
}
|
|
612
629
|
const directAnchorDownload = await tryDirectAnchorDownload({
|
|
613
630
|
artifactManifest: state.artifactManifest,
|
|
614
631
|
commandTokens,
|
|
@@ -188,7 +188,8 @@ export async function processBrowserOutput(input) {
|
|
|
188
188
|
!navigationSummary &&
|
|
189
189
|
(shouldCaptureNavigationSummary(prepared.executionPlan.commandInfo.command, presentationEnvelope?.data) ||
|
|
190
190
|
shouldCaptureSemanticActionNavigationSummary(prepared.compiledSemanticAction, presentationEnvelope?.data) ||
|
|
191
|
-
shouldCaptureAllowedDomainNavigationSummary
|
|
191
|
+
shouldCaptureAllowedDomainNavigationSummary ||
|
|
192
|
+
(prepared.executionPlan.commandInfo.command === "tab" && prepared.executionPlan.commandInfo.subcommand === "close"))) {
|
|
192
193
|
navigationSummary = await collectNavigationSummary({ cwd, namespace: prepared.executionPlan.namespace, sessionName: prepared.executionPlan.sessionName, signal });
|
|
193
194
|
}
|
|
194
195
|
if (navigationSummary && presentationEnvelope && !Array.isArray(presentationEnvelope.data))
|
|
@@ -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]
|
|
23
|
+
"High-value command reference: click <selector> --new-tab opens link-like targets in a new tab; select <selector> <value...> changes native dropdown values; wrapper-handled scroll <dir> [px|percent] and scroll to end/top target document scrolling before upstream fallback, while scroll <selector> <dir> [px|percent] targets nested scrollers; download <selector> <path> saves a file triggered by a click; read [url] returns agent-readable text (explicit URLs prefer markdown without launching Chrome; omit the URL for rendered active-tab DOM); 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
|
];
|
|
@@ -79,13 +79,6 @@ export const WRAPPER_TAB_RECOVERY_BEHAVIOR = [
|
|
|
79
79
|
"For sessions with observed tab-drift risk, after a successful command on a known target tab, agent_browser also best-effort restores that intended tab if a restored/background tab steals focus after the command completes. Routine same-session commands skip this post-command tab-list probe.",
|
|
80
80
|
"If a known session target unexpectedly reports about:blank, agent_browser best-effort re-selects the prior intended target when it still exists; if recovery fails, it records the observed about:blank target and reports exact recovery guidance instead of treating the prior page as active.",
|
|
81
81
|
];
|
|
82
|
-
export function buildSharedBrowserPlaybookGuidelines(options) {
|
|
83
|
-
return [
|
|
84
|
-
SHARED_BROWSER_PLAYBOOK_GUIDELINES[0],
|
|
85
|
-
...(options.includeWebSearch ? [WEB_SEARCH_PROMPT_GUIDELINE] : []),
|
|
86
|
-
...SHARED_BROWSER_PLAYBOOK_GUIDELINES.slice(1),
|
|
87
|
-
];
|
|
88
|
-
}
|
|
89
82
|
/** Tier A: always-on tool promptGuidelines (keep small; Tier B lives in SHARED_BROWSER_PLAYBOOK_GUIDELINES and docs). */
|
|
90
83
|
export const RUNTIME_PROMPT_GUIDELINES = [
|
|
91
84
|
"Use agent_browser with one input mode: args, semanticAction, job, qa, sourceLookup/networkSourceLookup, or electron. stdin only for batch/eval/auth/wrapper batch; electron rejects stdin; never pass --json.",
|
|
@@ -9,6 +9,7 @@ import { spawn } from "node:child_process";
|
|
|
9
9
|
import { chmod, mkdir } from "node:fs/promises";
|
|
10
10
|
import { env as processEnv, platform as processPlatform } from "node:process";
|
|
11
11
|
import { GLOBAL_BOOLEAN_FLAGS_WITH_OPTIONAL_VALUES, GLOBAL_VALUE_FLAGS, getFlagName } from "./argv-grammar.js";
|
|
12
|
+
import { getImplicitSessionIdleTimeoutMs } from "./runtime.js";
|
|
12
13
|
import { openSecureTempFile, writeSecureTempChunk } from "./temp.js";
|
|
13
14
|
const MAX_BUFFERED_STDOUT_BYTES = 512 * 1_024;
|
|
14
15
|
const MAX_BUFFERED_STDERR_CHARS = 32_000;
|
|
@@ -16,6 +17,7 @@ const MAX_BUFFERED_STDOUT_TAIL_CHARS = 32_000;
|
|
|
16
17
|
const PROCESS_STDOUT_SPILL_FILE_PREFIX = "process-stdout";
|
|
17
18
|
const AGENT_BROWSER_SOCKET_DIR_ENV = "AGENT_BROWSER_SOCKET_DIR";
|
|
18
19
|
const AGENT_BROWSER_DEFAULT_TIMEOUT_ENV = "AGENT_BROWSER_DEFAULT_TIMEOUT";
|
|
20
|
+
const AGENT_BROWSER_IDLE_TIMEOUT_ENV = "AGENT_BROWSER_IDLE_TIMEOUT_MS";
|
|
19
21
|
const PI_AGENT_BROWSER_PROCESS_TIMEOUT_ENV = "PI_AGENT_BROWSER_PROCESS_TIMEOUT_MS";
|
|
20
22
|
const DEFAULT_AGENT_BROWSER_SOCKET_DIR_PREFIX = "/tmp/piab";
|
|
21
23
|
export const SAFE_AGENT_BROWSER_OPERATION_TIMEOUT_MS = 25_000;
|
|
@@ -184,11 +186,15 @@ export function buildAgentBrowserProcessEnv(baseEnv = processEnv, overrides = un
|
|
|
184
186
|
export async function runAgentBrowserProcess(options) {
|
|
185
187
|
const { args, cwd, env, signal, stdin } = options;
|
|
186
188
|
const timeoutMs = options.timeoutMs ?? getAgentBrowserProcessTimeoutMs();
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
+
const processOverrides = {
|
|
190
|
+
[AGENT_BROWSER_IDLE_TIMEOUT_ENV]: String(getImplicitSessionIdleTimeoutMs()),
|
|
191
|
+
...env,
|
|
192
|
+
};
|
|
193
|
+
const explicitSocketDir = processOverrides[AGENT_BROWSER_SOCKET_DIR_ENV];
|
|
194
|
+
let effectiveEnv = explicitSocketDir === undefined ? { ...processOverrides, [AGENT_BROWSER_SOCKET_DIR_ENV]: undefined } : processOverrides;
|
|
189
195
|
const requestedSocketDir = explicitSocketDir ?? getAgentBrowserSocketDir();
|
|
190
196
|
if (requestedSocketDir && (await ensureAgentBrowserSocketDir(requestedSocketDir))) {
|
|
191
|
-
effectiveEnv = { ...
|
|
197
|
+
effectiveEnv = { ...effectiveEnv, [AGENT_BROWSER_SOCKET_DIR_ENV]: requestedSocketDir };
|
|
192
198
|
}
|
|
193
199
|
return await new Promise((resolve) => {
|
|
194
200
|
let aborted = false;
|
|
@@ -779,7 +779,6 @@ export function buildExecutionPlan(args, options) {
|
|
|
779
779
|
const startupScopedFlags = getStartupScopedFlags(args).filter((flag) => !(flag === "--namespace" && explicitNamespace === options.managedSessionNamespace));
|
|
780
780
|
const plainTextInspection = isPlainTextInspectionArgs(args);
|
|
781
781
|
const argvDescriptor = parseArgvDescriptor(args);
|
|
782
|
-
const commandTokens = argvDescriptor.commandTokens;
|
|
783
782
|
const commandInfo = argvDescriptor.commandInfo;
|
|
784
783
|
const commandNeedsManagedSession = !plainTextInspection && needsManagedSession(argvDescriptor);
|
|
785
784
|
const effectiveArgs = plainTextInspection ? [...args] : args.includes("--json") ? [] : ["--json"];
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -109,7 +109,7 @@ Why:
|
|
|
109
109
|
- keeps reload and exact-session relaunch validation tied to Pi's configured-source lifecycle instead of an isolated quick-test path, while `session_tree` state changes stay covered by focused extension harness tests
|
|
110
110
|
- keeps the published tarball focused on the package manifest, extension code, canonical docs, and license
|
|
111
111
|
|
|
112
|
-
The published package should exclude agent-only and
|
|
112
|
+
The published package should exclude agent-only and internal planning materials such as `AGENTS.md` and `docs/plans/`.
|
|
113
113
|
|
|
114
114
|
## Session model
|
|
115
115
|
|
|
@@ -139,7 +139,7 @@ V1 ownership rule:
|
|
|
139
139
|
Practical policy:
|
|
140
140
|
- preserve the current branch-visible extension-managed session across `/reload`, exact-session relaunch, `/resume`, and Pi 0.79 `session_tree` branch transitions so persisted sessions can keep following the live browser after lifecycle changes
|
|
141
141
|
- close the active extension-managed session when the originating `pi` process quits, while leaving explicit caller-provided sessions alone
|
|
142
|
-
- set an idle timeout on extension-managed sessions as a backstop for abnormal exits or cleanup failures
|
|
142
|
+
- set an idle timeout on extension-managed sessions as a backstop for abnormal exits or cleanup failures, and apply that same `AGENT_BROWSER_IDLE_TIMEOUT_MS` value to every upstream subprocess (including wrapper helper snapshots, tab lists, and navigation-summary reads) because changing the launch environment between calls can make upstream restart the background browser, discard the active tab, and invalidate fresh refs
|
|
143
143
|
- clean up process-private temp spill artifacts on shutdown, but keep persisted-session snapshot spill files in a private session-scoped artifact directory with a bounded per-session budget so `details.fullOutputPath` stays usable after reload/resume without unbounded growth
|
|
144
144
|
- keep explicit screenshots, downloads, PDFs, traces, HAR captures, and recordings written to caller-chosen paths on disk after a successful upstream close command (`close`, `quit`, or `exit`); before artifact-producing commands run, create missing parent directories for requested host paths, and for simple loopback HTML anchor downloads with resolvable HTTP(S) hrefs the wrapper may save directly to the requested path before upstream fallback. When the bounded `details.artifactManifest` has entries, successful close commands also surface `details.artifactCleanup` and a compact `Artifact lifecycle` note pointing to structured explicit paths so operators remove files with normal host tools—the native tool does not delete arbitrary user paths (`extensions/agent-browser/lib/orchestration/browser-run/diagnostics.ts`, `getArtifactCleanupGuidance`); contract in [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details), checklist `RQ-0079` in [`SUPPORT_MATRIX.md`](SUPPORT_MATRIX.md)
|
|
145
145
|
- reconstruct the current branch-visible extension-managed session, page-scoped refs, artifact manifest, and Electron launch records from the active transcript branch on `session_start` and `session_tree` so later default calls keep following the active managed browser after resume/reload or branch switching; restore also honors successful explicit `--session <wrapper-owned> close` rows and `electron.cleanup` managed-session steps so closed wrapper-owned sessions are not resurrected
|
|
@@ -152,6 +152,7 @@ Practical policy:
|
|
|
152
152
|
- after profiled `open` / `goto` / `navigate` calls, verify the active tab still matches the returned page URL and best-effort switch back when restored profile tabs steal focus
|
|
153
153
|
- once the wrapper observes tab-drift risk for a session (profile restore correction, overlapping stale opens, or restored session state), later active-tab commands may synthesize a tiny upstream `batch` that re-selects that tab and then runs the requested command in the same upstream invocation; routine same-session commands avoid `tab list` preflights to reduce probes that can perturb upstream click behavior
|
|
154
154
|
- for sessions with observed tab-drift risk, after a successful command on a known tab target, the wrapper may best-effort restore that same target again if restored/background tabs steal focus after the command returns; routine same-session commands skip this post-command `tab list` probe
|
|
155
|
+
- after successful `tab close`, read the now-active URL/title before updating per-session page state because upstream's close payload identifies the closed tab but does not report the remaining active tab; this keeps subsequent ref guards and interactions aligned without requiring a recovery snapshot solely to repair wrapper state
|
|
155
156
|
- keep a per-session `refSnapshot` aligned with the last successful `snapshot` (including refs merged from a successful `batch` by taking the last successful `snapshot` step in batch result order): restore it from persisted tool `details` when reloading, resuming, or moving to a different Pi session-tree branch, store bounded ref role/name metadata from the same snapshot for wrapper-side current-ref diagnostics, drop it on successful close commands (`close`, `quit`, or `exit`), and refuse mutation-prone `@e…` argv before spawn when the active tab URL no longer matches the snapshot URL, when a ref id was never in that snapshot, or when `batch` stdin would reuse `@e…` on a guarded step after an earlier invalidating step without a later `snapshot` step in the same stdin array. Same-snapshot `fill @e…` rows are guarded but do not themselves set that invalidation latch, so ordinary form fills can precede a click/submit row in one batch—see [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details) for the agent-visible contract and failure text; typed per-session tab/ref/pinning state lives in `extensions/agent-browser/lib/session-page-state.ts` and is updated from `extensions/agent-browser/index.ts` after each tool result
|
|
156
157
|
- for top-level non-Electron direct `click` commands with an eligible target, install a bounded in-page target-specific event probe before upstream runs; if upstream reports success but no trusted pointer/mouse/click event reached the resolved target, fail the tool and report `details.clickDispatch` with explicit retry/inspect next actions (the wrapper does not replay clicks in-page). The probe covers `xpath=` targets and current `@e…` / `ref=` refs whose latest stored `refSnapshot.refs` role is `button`, `checkbox`, `menuitem`, `radio`, `switch`, or `tab`; it uses that role/name metadata, including snapshot-order `duplicateIndex` for duplicate-name refs, instead of taking a fresh pre-click snapshot that could recycle upstream refs. The probe is intentionally skipped for CSS selector clicks, unresolved `find … click` locators, and `batch`/`job`/`qa` click steps
|
|
157
158
|
- derive narrow prompt guards only for concrete evidence invariants: exact required screenshot paths block browser close until the artifact manifest verifies those paths. The wrapper intentionally does not infer broad business/user intent from prompt text such as order/payment/post boundaries; agents must follow those instructions themselves. The artifact guard is bounded preflight policy (`details.promptGuard`, `failureCategory: "policy-blocked"`), not a reusable browser recipe layer
|
|
@@ -206,7 +207,7 @@ Upstream restore-state persistence remains upstream-owned. The wrapper passes `A
|
|
|
206
207
|
- subprocess execution and JSON parsing through `buildAgentBrowserProcessEnv` in `extensions/agent-browser/lib/process.ts`: copies the parent process environment so user-approved provider credentials and other runtime variables reach upstream, then applies wrapper overrides such as the managed socket directory and clamped default operation timeout
|
|
207
208
|
- clear missing-binary errors
|
|
208
209
|
- compact result summaries, including presentation-time redaction: stateful browser-context commands (`auth`, `cookies`, `storage`, `dialog`, `frame`, `state`) use field-aware value redaction and compact formatters, while other structured upstream JSON (for example `network`, `diff`, `trace` / `profiler` / `record`, `console` / `errors` / `highlight` / `inspect` / `clipboard`, `stream`, `dashboard`, and `chat`) is passed through `redactPresentationData` in `extensions/agent-browser/lib/results/presentation.ts` so model-facing `details.data` and batch roll-ups stay compact and do not echo bearer tokens, proxy passwords, or similar fields verbatim; `redactInvocationArgs` in `extensions/agent-browser/lib/runtime.ts` masks trailing values for sensitive global flags such as `--body`, `--headers`, `--password`, and `--proxy`, preserves positional rules for `cookies set` and `storage local|session set`, and nested `batch` steps use the same argv and error-body scrubbing before echoing commands or errors
|
|
209
|
-
- bounded machine-readable outcome metadata on tool `details` (`resultCategory`, `successCategory`, `failureCategory`, optional `nextActions`, optional `pageChangeSummary` with per-step summaries on `batch`, optional `artifactVerification` with the same shape on each successful `batchSteps[]` row) so agents can branch without parsing prose; enums, classifier precedence, and generic follow-up payloads are implemented under `extensions/agent-browser/lib/results/` in focused modules (`contracts.ts` for shared types, `categories.ts` for `classifyAgentBrowserSuccessCategory` / `classifyAgentBrowserFailureCategory` / `buildAgentBrowserResultCategoryDetails`, `action-recommendations.ts` for `buildAgentBrowserNextActions`, `next-actions.ts` for the `AgentBrowserNextAction` shape and merge helpers, `recovery-actions.ts` for recovery id registries and `buildRecoveryNextActions`, `network.ts` for `classifyNetworkRequestFailure` / `summarizeNetworkFailures`, and related helpers
|
|
210
|
+
- bounded machine-readable outcome metadata on tool `details` (`resultCategory`, `successCategory`, `failureCategory`, optional `nextActions`, optional `pageChangeSummary` with per-step summaries on `batch`, optional `artifactVerification` with the same shape on each successful `batchSteps[]` row) so agents can branch without parsing prose; enums, classifier precedence, and generic follow-up payloads are implemented under `extensions/agent-browser/lib/results/` in focused modules (`contracts.ts` for shared types, `categories.ts` for `classifyAgentBrowserSuccessCategory` / `classifyAgentBrowserFailureCategory` / `buildAgentBrowserResultCategoryDetails`, `action-recommendations.ts` for `buildAgentBrowserNextActions`, `next-actions.ts` for the `AgentBrowserNextAction` shape and merge helpers, `recovery-actions.ts` for recovery id registries and `buildRecoveryNextActions`, `network.ts` for `classifyNetworkRequestFailure` / `summarizeNetworkFailures`, and related helpers). Per-session tab target, `refSnapshot` alignment, invalidation, and tab pinning observations flow through `extensions/agent-browser/lib/session-page-state.ts` from `extensions/agent-browser/index.ts`. Compact page-change summaries and artifact verification rollups are built in `extensions/agent-browser/lib/results/presentation.ts` (`buildPageChangeSummary`, `buildArtifactVerificationSummary`), and the human contract lives in [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details). Real Pi custom tools otherwise only mark a row failed when `execute` throws, so the extension also registers `pi.on("tool_result", …)` and patches `agent_browser` results whose `details.resultCategory` is `failure` to set `isError: true`. Prose results also receive a short category notice, while caller-requested `--json` results with parseable JSON content keep that text unchanged so JSONL transcripts, UI affordances, and the machine-readable contract stay aligned for wrapper-side reclassifications such as `qa-failure` (`buildAgentBrowserToolResultPatch` in `extensions/agent-browser/lib/pi-tool-rendering.ts`; transcript semantics in the same contract doc)
|
|
210
211
|
- inline screenshots/images for the plain `screenshot` command; other image-like saves (for example `diff screenshot`) still appear in `details.artifacts` and summaries but are not auto-inlined as Pi image attachments (see [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details))
|
|
211
212
|
- lightweight session convenience
|
|
212
213
|
- docs, including a repo-readable command reference that mirrors the blocked direct-binary help path closely enough for normal agent work
|
|
@@ -610,7 +610,7 @@ Skill-source debugging note: upstream honors `AGENT_BROWSER_SKILLS_DIR` as an ov
|
|
|
610
610
|
| `tap <selector>` | Touch-oriented tap alias for iOS/provider workflows. |
|
|
611
611
|
| `swipe <direction> [distance]` | Touch-oriented swipe for iOS/provider workflows. |
|
|
612
612
|
|
|
613
|
-
On dashboards and other apps with nested scroll containers, `scroll <dir> [px]`
|
|
613
|
+
On dashboards and other apps with nested scroll containers, `scroll <dir> [px]` can miss because a page-level wheel does not move the document or the intended pane. Without startup-scoped launch flags, the wrapper first applies ordinary `scroll <up|down|left|right> [px|percent]` directly to `document.scrollingElement` with smooth scrolling temporarily disabled; successful movement reports `details.scrollPage`. If the document cannot move, it falls back to upstream wheel behavior. For large fallback calls on an existing or fresh managed session, the wrapper samples viewport and prominent scroll-container positions before and after the command; when nothing changes it prepends `Scroll completed with no observed movement`, appends `Scroll diagnostic: no observed scroll movement`, exposes `details.scrollNoop`, marks `details.data.scrolled: false`, and adds exact `details.nextActions` for a fresh `snapshot -i` and screenshot. Explicit CSS-container calls `scroll <selector> <up|down|left|right> [px|percent]` remain wrapper-handled and report `details.scrollContainer`; `scroll to end` / `scroll to top` report `details.scrollPage`. Calls with startup-scoped flags skip all helper shims so the requested launch configuration runs first. Use these paths before repeating page scrolls; when you need a specific element, prefer `scrollintoview <@ref>` or target the actual scrollable region.
|
|
614
614
|
|
|
615
615
|
Comboboxes vary by app. For native `<select>` controls, prefer raw `select <selector> <value...>`, `semanticAction: { action: "select", selector, value|values }`, or a `job` `select` step instead of clicking option refs; native option refs can be non-boxed in CDP and fail before a real selection. A `click` or `semanticAction` role/name click may focus a searchable custom combobox without opening its option list. For explicit combobox-targeted actions such as `semanticAction` role `combobox`, the wrapper checks whether a combobox-like element is focused, has explicit `aria-expanded` state, and has no visible listbox/options open; this still applies when the semantic action first resolves to a current visible `@ref` before execution. When that happens it appends `Combobox diagnostic: focused combobox did not expose visible options`, exposes `details.comboboxFocus`, and adds exact `details.nextActions` for a fresh `snapshot -i`, `press ArrowDown`, and `press Enter`. Use those instead of assuming click alone expanded the control; reserve visible option refs for custom comboboxes after a fresh snapshot shows the intended option.
|
|
616
616
|
|
|
@@ -890,7 +890,7 @@ Browser default config is conservative: it adds agent guidance for signed-in/acc
|
|
|
890
890
|
- `--download-path <path>`: default browser download directory. Environment: `AGENT_BROWSER_DOWNLOAD_PATH`.
|
|
891
891
|
- `--engine <name>`: browser engine, `chrome` by default or `lightpanda`. Environment: `AGENT_BROWSER_ENGINE`.
|
|
892
892
|
- `--no-auto-dialog`: disable automatic dismissal of alert/beforeunload dialogs. Environment: `AGENT_BROWSER_NO_AUTO_DIALOG`.
|
|
893
|
-
- `--idle-timeout <ms>`:
|
|
893
|
+
- `--idle-timeout <ms>`: launch-scoped background browser lifecycle setting. The wrapper already sets one stable `AGENT_BROWSER_IDLE_TIMEOUT_MS` for top-level and helper subprocesses. A per-call value must equal that configured value; otherwise the tool rejects it before launch and tells you to restart Pi with `PI_AGENT_BROWSER_IMPLICIT_SESSION_IDLE_TIMEOUT_MS=<ms>`. This prevents upstream from restarting the browser and discarding tabs/refs when later helper calls use a different launch environment.
|
|
894
894
|
|
|
895
895
|
### Output, provider, policy, and AI flags
|
|
896
896
|
|
package/docs/ELECTRON.md
CHANGED
|
@@ -364,8 +364,8 @@ Electron support is gated by the same release evidence as the rest of the wrappe
|
|
|
364
364
|
|
|
365
365
|
- `RQ-0096` in [`SUPPORT_MATRIX.md`](SUPPORT_MATRIX.md) records the contract, runtime, test, and verification coverage.
|
|
366
366
|
- `electron-lifecycle` and `electron-probe` scenarios in `scripts/agent-browser-efficiency-benchmark.mjs` track the token-efficiency claim deterministically (no real browser, no real launches).
|
|
367
|
-
- Fake-upstream coverage
|
|
368
|
-
- Real-app validation is a manual `tmux` smoke pass per the maintainer notes in `AGENTS.md`; the 2026-05-21 dogfood result
|
|
367
|
+
- Fake-upstream Electron discovery and lifecycle coverage lives in `test/agent-browser.extension-electron-discovery.test.ts` and `test/agent-browser.extension-electron-lifecycle.test.ts`; ref/session recovery coverage lives in `test/agent-browser.extension-ref-guards.test.ts`, with shared validation paths in `test/agent-browser.extension-validation.test.ts`.
|
|
368
|
+
- Real-app validation is a manual `tmux` smoke pass per the maintainer notes in `AGENTS.md`; the 2026-05-21 dogfood result and resulting decision are summarized in the repo-local [`Electron ADR`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/plans/electron-extension-2026-05-20.md).
|
|
369
369
|
|
|
370
370
|
Run the local gate the same way as the rest of the project:
|
|
371
371
|
|
package/docs/RELEASE.md
CHANGED
|
@@ -173,8 +173,8 @@ Maintainer constraints for evolving scenarios and version bumps are summarized u
|
|
|
173
173
|
- no repo-local `.pi/extensions/agent-browser.ts` autoload shim is present
|
|
174
174
|
- `LICENSE` exists in the repo and the packed tarball
|
|
175
175
|
- canonical published docs are present
|
|
176
|
-
- `npm pack --json --dry-run` runs the `
|
|
177
|
-
- GitHub/source installs
|
|
176
|
+
- `npm pack --json --dry-run` runs the package `prepare` build once and packs the compiled `dist/extensions/agent-browser/index.js` entrypoint
|
|
177
|
+
- GitHub/source installs use the same `prepare` build; when Pi installs with `npm install --omit=dev`, `scripts/prepare.mjs` installs source-build dev dependencies with lifecycle scripts disabled before building so Pi can load the ignored compiled entrypoint from a fresh clone
|
|
178
178
|
- the package-level doctor command and capability baseline are present
|
|
179
179
|
- compiled extension runtime files are present, including the split result-rendering modules required by the published facade
|
|
180
180
|
- source-only, agent-only, and superseded docs are absent from the tarball
|
|
@@ -192,7 +192,7 @@ The packaged execution smoke intentionally uses a temporary fake `agent-browser`
|
|
|
192
192
|
Current forbidden packed files include:
|
|
193
193
|
|
|
194
194
|
- `AGENTS.md`
|
|
195
|
-
-
|
|
195
|
+
- internal planning docs under `docs/plans/`
|
|
196
196
|
- `.pi/extensions/agent-browser.ts`
|
|
197
197
|
- TypeScript extension source and other test/repo-only maintenance files
|
|
198
198
|
|
|
@@ -281,7 +281,7 @@ This suite requires the installed `agent-browser --version` to exactly match `sc
|
|
|
281
281
|
- **Failure shape:** `react tree` on a page opened with `--enable react-devtools` but without a React app (expects a clear missing-renderer error with session-bound `details`).
|
|
282
282
|
- **Async download:** `open` on the `/download` fixture, anchor-triggered export, then `wait --download <path>` metadata and wrapper artifact reporting for the requested path.
|
|
283
283
|
|
|
284
|
-
The default unit suite also runs `agentBrowserExtension passes through core command coverage fallback matrix` in [`test/agent-browser.extension-validation.test.ts`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/test/agent-browser.extension-validation.test.ts): a fake upstream records argv so `connect 9222`, `download` with a selector and path, `get url`, `snapshot --compact`, and `tab new` / `tab
|
|
284
|
+
The default unit suite also runs `agentBrowserExtension passes through core command coverage fallback matrix` in [`test/agent-browser.extension-passthrough-validation.test.ts`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/test/agent-browser.extension-passthrough-validation.test.ts): a fake upstream records argv so `connect 9222`, `download` with a selector and path, `get url`, `snapshot --compact`, and `tab new` / `tab t1` / `tab close` still prove `--json` plus implicit `--session` ordering without a browser. A second fake-upstream matrix in that file (`agentBrowserExtension passes through non-core network debug diff stream dashboard and chat families`) pins representative `network`, `diff`, `trace` / `profiler` / `record`, `console` / `errors` / `highlight` / `inspect` / `clipboard`, `stream`, `dashboard`, and `chat` JSON shapes plus redacted `details.data` and argv echoes without a browser. A third matrix (`agentBrowserExtension passes through provider and specialized skill workflows`) asserts provider `open` argv shapes still receive `--json` plus implicit `--session` while read-only `skills get …` stays stateless (no managed session fields) and provider credential env vars are forwarded into the fake upstream log. Extend those matrices when adding passthrough coverage that should stay out of the slow real-upstream loop.
|
|
285
285
|
|
|
286
286
|
### Real upstream suite mechanics, isolation, and troubleshooting
|
|
287
287
|
|
package/docs/REQUIREMENTS.md
CHANGED
|
@@ -81,7 +81,7 @@ Define the product requirements and constraints for `pi-agent-browser-native`.
|
|
|
81
81
|
- Because direct-binary usage is commonly blocked in normal agent sessions, the repo must carry a local command reference for the effective `agent_browser` surface and keep it in sync with upstream changes.
|
|
82
82
|
- Repository verification must include a lightweight command-reference drift check against the targeted installed upstream `agent-browser` version.
|
|
83
83
|
- Published package contents should include the canonical user-facing docs plus `LICENSE`.
|
|
84
|
-
- Published package contents should exclude agent-only and
|
|
84
|
+
- Published package contents should exclude agent-only and internal planning docs such as `AGENTS.md` and `docs/plans/`.
|
|
85
85
|
|
|
86
86
|
### Testing guidance
|
|
87
87
|
|
|
@@ -114,7 +114,7 @@ The design should comfortably support workflows such as:
|
|
|
114
114
|
- Package-manifest behavior matters more than repo-local development wiring.
|
|
115
115
|
- The extension should use official `pi` hooks and package resources where possible.
|
|
116
116
|
- The wrapper should stay thin, with upstream `agent-browser` remaining the source of truth for command semantics.
|
|
117
|
-
- Successful and failed tool outcomes should surface bounded machine-readable fields on Pi-facing `details` (`resultCategory`, `successCategory`, `failureCategory`, optional structured `nextActions`, optional `pageChangeSummary` with per-step summaries on `batch`, optional `artifactVerification` with the same shape on successful `batchSteps[]` rows, optional `outputFile`, optional `timeoutPartialProgress`) so agents can branch without parsing prose; stateful commands (`auth`, `cookies`, `storage`, `dialog`, `frame`, `state`) plus other structured diagnostics (for example `network`, `diff`, `trace`, `stream`, `dashboard`, `chat`) and `batch` should redact secret-bearing payloads in model-facing `details.data`, including the compact per-step `batch` roll-up on the parent result (full per-step payloads live on `batchSteps[]`). Dialog/prompt-related timeouts should be bounded with recovery `nextActions`; non-dialog timeouts should prefer best-effort per-step progress and retry payloads when a plan is available; no-op scrolls should expose no-movement state instead of only an upstream success boolean; explicit page/container scroll helpers should expose before/after movement evidence. The contract lives in [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details), enums and classifier precedence live in `extensions/agent-browser/lib/results/categories.ts` and `contracts.ts
|
|
117
|
+
- Successful and failed tool outcomes should surface bounded machine-readable fields on Pi-facing `details` (`resultCategory`, `successCategory`, `failureCategory`, optional structured `nextActions`, optional `pageChangeSummary` with per-step summaries on `batch`, optional `artifactVerification` with the same shape on successful `batchSteps[]` rows, optional `outputFile`, optional `timeoutPartialProgress`) so agents can branch without parsing prose; stateful commands (`auth`, `cookies`, `storage`, `dialog`, `frame`, `state`) plus other structured diagnostics (for example `network`, `diff`, `trace`, `stream`, `dashboard`, `chat`) and `batch` should redact secret-bearing payloads in model-facing `details.data`, including the compact per-step `batch` roll-up on the parent result (full per-step payloads live on `batchSteps[]`). Dialog/prompt-related timeouts should be bounded with recovery `nextActions`; non-dialog timeouts should prefer best-effort per-step progress and retry payloads when a plan is available; no-op scrolls should expose no-movement state instead of only an upstream success boolean; explicit page/container scroll helpers should expose before/after movement evidence. The contract lives in [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details), enums and classifier precedence live in `extensions/agent-browser/lib/results/categories.ts` and `contracts.ts`, and presentation-time summaries, redaction, network request follow-ups, and artifact verification rollups are assembled in `extensions/agent-browser/lib/results/presentation.ts` (`buildPageChangeSummary`, command taxonomy predicates from `command-taxonomy.ts`, `redactPresentationData`, `buildArtifactVerificationSummary`, `buildBatchPresentation`).
|
|
118
118
|
- User-facing docs belong in `README.md` and the canonical published files under `docs/`.
|
|
119
119
|
- Agent workflow and deeper testing procedures can stay in `AGENTS.md`, but published docs must not depend on that file being present.
|
|
120
120
|
- When upstream `agent-browser` changes, refresh the local command reference, prompt guidance, and other extension-side docs so agents still have a repo-readable equivalent of the blocked direct-binary help path.
|
|
@@ -130,8 +130,3 @@ The design should comfortably support workflows such as:
|
|
|
130
130
|
- Upstream restore-state periodic autosave remains upstream-owned. Forward `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS` unchanged, document its 30-second default and `0` disable behavior, and do not duplicate its timer or claim its restore files as wrapper artifacts.
|
|
131
131
|
- Read-only upstream `skills list`, `skills get …`, and `skills path …` must stay free of implicit managed `--session` under default `sessionMode: "auto"` (still with `--json`), matching plain-text `--help` / `--version` inspection semantics so bundled skill text does not pin or rotate the active browser session; new `skills` subcommands pick up that behavior only after allowlisting in `extensions/agent-browser/lib/runtime.ts` with regression coverage.
|
|
132
132
|
- Optional `semanticAction.session` on native `agent_browser` must compile to a leading `--session <name>` pair before upstream `find` or `select` argv so the shorthand can target a named upstream browser without hand-built `args`, while `buildExecutionPlan` still skips double-injecting the extension-managed implicit session whenever planned argv already starts with `--session`; stale-ref retries for compiled `find` actions and bounded `try-*` candidate `nextActions` must preserve that same prefix. Contract in [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#semanticaction) / [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#sessionmode); implementation in `extensions/agent-browser/index.ts` and `extensions/agent-browser/lib/runtime.ts`.
|
|
133
|
-
|
|
134
|
-
## Open design questions
|
|
135
|
-
|
|
136
|
-
- How much session convenience should the extension add by default versus leaving explicit session naming entirely to upstream `agent-browser` semantics?
|
|
137
|
-
- Exactly which high-value result renderers belong in v1 beyond screenshots/images and a few compact summaries?
|
package/docs/SUPPORT_MATRIX.md
CHANGED
|
@@ -28,13 +28,13 @@ When upstream ships a new `agent-browser` or the inventory changes:
|
|
|
28
28
|
|
|
29
29
|
- Target upstream: `agent-browser 0.32.2` (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: source and wrapper adaptation are complete for the 2026-07-
|
|
31
|
+
- Status: source and wrapper adaptation are complete for the 2026-07-18 0.32.2 audit; the 0.32.1–0.32.2 changes stay isolated to the separate `@agent-browser/eve` package, while the wrapper now also keeps hidden helper subprocesses on the same idle-timeout launch configuration, refreshes the remaining active target after `tab close`, and performs deterministic document-direction scrolls before wheel fallback.
|
|
32
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. The 0.31.2 rebaseline adds the local-launch-only `--webgpu` preset and `doctor --webgpu`, plus periodic restore-state autosaves controlled by `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS`; the wrapper treats WebGPU as launch-scoped and leaves autosave ownership upstream. The 0.32.0 rebaseline hardens request/worker/popup/WebRTC containment behind `--allowed-domains`, fixes waits against already-complete documents, and adds a separate `@agent-browser/eve` package; the wrapper makes containment launch-scoped, retains its final-URL check as defense in depth, and adds no Eve-specific mode. The 0.32.1–0.32.2 rebaseline updates only eve compatibility/packaging, but the full current-surface audit also found the local reference had omitted upstream `read [url]` since 0.30.0; baseline/help sampling, content-first presentation, tab-target preservation, timeout budgeting, docs, and tests now cover it. 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
|
+
## UX/reliability decisions from 2026-05-29 agent feedback
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Closed feedback decisions map to their canonical contracts in [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md). Keep this active matrix limited to release-critical status and gates.
|
|
38
38
|
|
|
39
39
|
Current summary:
|
|
40
40
|
|
|
@@ -42,7 +42,7 @@ Current summary:
|
|
|
42
42
|
| --- | --- | --- |
|
|
43
43
|
| RQ-0110–RQ-0120 | Agent feedback triage resolved or documented; remaining unsupported areas are environment/upstream-owned. | [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md) |
|
|
44
44
|
| RQ-0123–RQ-0127 | Stress-report wrapper fixes shipped; prompt-derived business-action blocking remains intentionally out of scope. | [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md) |
|
|
45
|
-
|
|
|
45
|
+
| `agent-browser 0.27.2` baseline | Historical upstream rebaseline shipped; `RQ-0101` remains the compact-snapshot high-value-controls decision. | [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md) |
|
|
46
46
|
| RQ-0128 | Upstream `agent-browser 0.27.3` install-only rebaseline shipped; no new wrapper capability adopted. | [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md) |
|
|
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) |
|
|
@@ -51,25 +51,26 @@ Current summary:
|
|
|
51
51
|
| RQ-0133 | Upstream `agent-browser 0.31.2` rebaseline adds WebGPU launch/doctor/MCP surfaces and periodic restore-state autosaves; wrapper launch parsing/policy and docs now cover both. | [`docs/COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#upstream-0312-rebaseline) |
|
|
52
52
|
| RQ-0134 | Upstream `agent-browser 0.32.0` rebaseline hardens domain containment, fixes completed-page waits, and adds a separate eve extension package; wrapper launch policy and docs cover the relevant behavior. | [`docs/COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#upstream-0320-rebaseline) |
|
|
53
53
|
| RQ-0135 | Upstream `agent-browser 0.32.2` rebaseline updates eve packaging only and closes the wrapper's prior missing `read [url]` inventory/presentation contract. | [`docs/COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#upstream-0322-rebaseline) |
|
|
54
|
+
| RQ-0136 | Wrapper regression fix keeps helper subprocess launch environments stable, refreshes active tab state after `tab close`, and makes ordinary document-direction scrolling deterministic before upstream fallback. | [`docs/ARCHITECTURE.md`](ARCHITECTURE.md), [`docs/TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details) |
|
|
54
55
|
|
|
55
56
|
## Verification evidence
|
|
56
57
|
|
|
57
|
-
Re-run the gates below before each release; this table records what the closure audit exercised. The 0.32.2 / Pi 0.80.10 local rebaseline gates passed on 2026-07-
|
|
58
|
+
Re-run the gates below before each release; this table records what the closure audit exercised. The 0.32.2 / Pi 0.80.10 local rebaseline gates passed on 2026-07-18; the prior 0.32.0 / Pi 0.80.9 release-composition and platform rows remain explicitly historical evidence.
|
|
58
59
|
|
|
59
60
|
| Gate | Evidence | Status |
|
|
60
61
|
| --- | --- | --- |
|
|
61
|
-
| 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.32.2 / Pi 0.80.10:** pass on 2026-07-
|
|
62
|
+
| 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.32.2 / Pi 0.80.10:** pass on 2026-07-18 (590 passed, 2 opt-in skips; live command-reference verification passed). |
|
|
62
63
|
| 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. | **Current for 0.32.0:** covered by the stronger passing release composition on 2026-07-16; orchestration remains locked by `test/project-verify.test.ts`. |
|
|
63
|
-
| 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.32.2:** pass on 2026-07-
|
|
64
|
-
| 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
|
|
65
|
-
| 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-
|
|
66
|
-
| 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.32.
|
|
64
|
+
| 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.32.2:** pass on 2026-07-18 (2/2 real-upstream tests), including snapshot-ref native select, stable-id/label tab switching, active-target refresh after `tab close`, and visible `read` content against the localhost contract fixture. |
|
|
65
|
+
| 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 package 0.2.71 / Pi 0.80.10:** pass on 2026-07-18 (116 packed entries; exactly one packaged `agent_browser`; invocation passed). |
|
|
66
|
+
| 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-07-18 (`npm run verify -- startup-profile --samples 3`; median 49.1 ms, maximum 50.1 ms, below the 250 ms budget). Full-Pi startup numbers from the unsafe tmux profiler are not accepted as ongoing release evidence. |
|
|
67
|
+
| 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.32.2:** pass on 2026-07-18; checkout-loaded Artificial Analysis/React/GitHub dogfood also passed snapshot-ref interactions, document scroll, and multi-tab close/reuse without background restarts or tab resets. |
|
|
67
68
|
| WebGPU and restore autosave | Live 0.31.2 feature probes validate the new upstream paths independently from ordinary browser dogfood. | **macOS:** `doctor --webgpu` passed Apple Metal render/readback and headless red-pixel screenshot checks; the official Hello Triangle sample exposed the Metal adapter and produced a verified non-black screenshot. **Ubuntu image:** `doctor --webgpu --headed --json` passed SwiftShader render/readback and red-pixel screenshot checks with the baked Vulkan/Mesa/Xvfb dependencies. **Restore autosave:** an idle page timer changed localStorage and the namespaced restore file contained the new value before close; test state was removed. **Windows interactive desktop:** post-release validation on 2026-07-15 used a disposable clone of snapshot `57cc3c0d-7d7c-4a4c-9c57-8270d4174679`, a logged-in console session, `agent-browser 0.31.2`, and Edge 150. The headed doctor WebGPU render/readback subcheck passed in 0.99s and its decoded screenshot subcheck passed with `rgb(255,0,0)`; a separate `--webgpu --headed` launch opened the proof page and the Parallels console capture visibly recorded the red triangle (553,500 bright-red pixels; SHA-256 `f5a28f5336cbdfeb0ff557af9425458bddc6b266d3cc6b946de7b101a0b43288`). The full doctor remained nonzero only for the unrelated absence of a separately installed Chrome binary; the explicit Edge executable completed the launch and both WebGPU probes. Local evidence is under `.artifacts/windows-webgpu-interactive/20260715T150903Z/summary.json`; the disposable clone and temporary account were deleted afterward. |
|
|
68
|
-
| 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-
|
|
69
|
-
| 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.32.
|
|
70
|
-
| `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.32.
|
|
71
|
-
| 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.32.
|
|
72
|
-
| 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.32.2 / Pi 0.80.10:** pass on 2026-07-
|
|
69
|
+
| 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-07-18 (`npm run verify -- benchmark`; 13/13 deterministic scenarios passed). |
|
|
70
|
+
| 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.32.2 / Pi 0.80.10:** pass on 2026-07-18 inside `npm run verify -- release`; evidence roots are `run-1784406200583-yaojql` (macOS), `run-1784406200585-fyulk0` (Ubuntu), and `run-1784406200586-w1nkt1` (native Windows). All platform-build, browser-dogfood, and lease-cleanup summaries passed; no release-owned leases/clones remained. |
|
|
71
|
+
| `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.32.2 / package 0.2.71 / Pi 0.80.10:** pass on 2026-07-18, including 590 passing default tests, live command-reference sampling, lifecycle, packaged Pi smoke, and the required macOS/Ubuntu/native-Windows matrix. |
|
|
72
|
+
| 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.32.2 / Pi 0.80.10:** pass on 2026-07-18 inside `npm run verify -- release`; reload/relaunch continuity, persisted spill reachability, and failure-patch assertions passed. |
|
|
73
|
+
| 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.32.2 / Pi 0.80.10:** pass on 2026-07-18 across isolated tmux runs using Artificial Analysis, React, GitHub, and a deterministic select/tab fixture. Snapshot-ref select/click, document scroll (0→700), stable-id/label tab switching, `tab close` target refresh, and post-close interaction passed with zero background restarts, `about:blank` resets, or spurious stale-ref failures; all disposable sessions/tmux/temp files were removed. |
|
|
73
74
|
|
|
74
75
|
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.80.6 as a setup failure. `npm run doctor` passed against Pi 0.80.6 on 2026-07-11. This keeps package dependency shape aligned with Pi package loading while still making unsupported host Pi versions a release and first-run blocker.
|
|
75
76
|
|
|
@@ -78,17 +79,17 @@ Runtime floor note: package metadata keeps Pi core package peer ranges wildcard
|
|
|
78
79
|
| Baseline section | Baseline items | Documentation | Runtime handling | Test coverage | Validation status |
|
|
79
80
|
| --- | --- | --- | --- | --- | --- |
|
|
80
81
|
| Built-in skills | 15 canonical tokens from baseline section `skills`; see [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs) and generated [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#built-in-skills). | [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#built-in-skills), generated baseline block, README proof section, release docs. | `needsManagedSession` keeps read-only skills inspection sessionless while preserving thin upstream passthrough; upstream `@agent-browser/sandbox` remains external package guidance, not a bundled wrapper dependency. | Runtime and extension-validation skills/provider matrix; real-upstream inspection/skills group. | Supported. |
|
|
81
|
-
| Core page, element, navigation, and extraction commands | 81 canonical tokens from baseline section `core-commands`; see [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs) and generated [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#core-page-and-element-commands). | [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#core-page-and-element-commands), [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md), README quick start. | Thin passthrough with wrapper-owned JSON/session planning, ref guidance, artifact verification, page-change summaries, click-dispatch diagnostics, no-op
|
|
82
|
-
| Sessions, state, tabs, frames, dialogs, and windows | 24 canonical tokens from baseline section `state-tabs-frames-dialogs`; see [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs) and generated [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#session-state-frames-dialogs-windows-and-inspection-commands). | [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#session-state-frames-dialogs-windows-and-inspection-commands), stateful workflow notes, [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details). | Stateful summaries/redaction, state artifact handling, sessionless local command planning, managed-session restore, tab target pinning, and close alias cleanup. | Extension-
|
|
82
|
+
| Core page, element, navigation, and extraction commands | 81 canonical tokens from baseline section `core-commands`; see [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs) and generated [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#core-page-and-element-commands). | [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#core-page-and-element-commands), [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md), README quick start. | Thin passthrough with wrapper-owned JSON/session planning, ref guidance, artifact verification, page-change summaries, click-dispatch diagnostics, deterministic document scroll before wheel/no-op diagnostics, shorthand compilers, and redaction. | Real-upstream core matrix (including snapshot-ref select) plus fake core matrix for passthrough, ordering, diagnostics, and compiler validation. | Supported. Upstream semantics remain upstream-owned. |
|
|
83
|
+
| Sessions, state, tabs, frames, dialogs, and windows | 24 canonical tokens from baseline section `state-tabs-frames-dialogs`; see [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs) and generated [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#session-state-frames-dialogs-windows-and-inspection-commands). | [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#session-state-frames-dialogs-windows-and-inspection-commands), stateful workflow notes, [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details). | Stateful summaries/redaction, stable helper subprocess launch environment, state artifact handling, sessionless local command planning, managed-session restore, tab target pinning, active-target refresh after tab close, and close alias cleanup. | Extension tab/ref tests, real-upstream stable-id/label tab lifecycle, runtime session/resume tests, presentation redaction tests, lifecycle harness. | Supported. External profile/auth state remains operator-owned. |
|
|
83
84
|
| Network, storage, artifacts, diagnostics, and performance | 43 canonical tokens from baseline section `network-storage-artifacts-diagnostics`; see [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs) and generated [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#page-state-finding-mouse-settings-network-and-storage). | [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#page-state-finding-mouse-settings-network-and-storage), diagnostic sections, [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#details). | Thin passthrough plus compact diagnostics, route-mock warnings, useful-but-redacted storage output, stream idempotency normalization, artifact metadata, missing-ffmpeg warnings, sensitive-data redaction, timeout bounds, and cleanup-pair guidance. | Fake non-core matrix and safe real-upstream coverage for network/HAR, diff, trace/profiler, console/errors/highlight, stream, vitals, and React missing-renderer. | Supported. Environment-sensitive operations need suitable local/browser state. |
|
|
84
85
|
| Batch, auth, confirmations, setup, dashboard, devices, and AI commands | 33 canonical tokens from baseline section `batch-auth-setup-ai`; see [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs) and generated [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#batch-auth-confirmations-sessions-chat-dashboard-devices-and-setup). | [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#batch-auth-confirmations-sessions-chat-dashboard-devices-and-setup), README security notes, release docs. | Native-tool batch stdin, generated `job`/`qa`/lookup batch plans, auth/confirmation redaction, sessionless local auth/setup/dashboard/doctor/plugin planning, plugin list/show JSON envelope normalization, bare-`mcp` validation with `mcp --help` preserved, timeout/cleanup guidance. | Parser/runtime plugin and MCP unit coverage; fake-upstream plugin list/show and MCP help/blocking coverage; real-upstream plugin list shape probe; structured input-mode tests; efficiency benchmark scenarios. | Supported. Interactive side-effecting setup/auth/chat remains upstream-owned. `plugin` is local/sessionless; `mcp` is external-client-only except help; `auth login --credential-provider` resolves credentials via a plugin; `install --with-deps` failures remain upstream-owned. |
|
|
85
|
-
| Global flags, config, providers, policy, and environment | 138 canonical tokens from baseline section `options-and-env`; see [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs) and generated [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#important-global-flags-config-and-environment). | [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#important-global-flags-config-and-environment), README provider/setup notes, [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#sessionmode), architecture/runtime docs. | Runtime handles command discovery, value-flag prevalidation, launch-scoped flags, redacted echoes, fresh-session recovery hints, explicit sessions, provider/device launch-scoping, parent env forwarding with
|
|
86
|
+
| Global flags, config, providers, policy, and environment | 138 canonical tokens from baseline section `options-and-env`; see [`scripts/agent-browser-capability-baseline.mjs`](../scripts/agent-browser-capability-baseline.mjs) and generated [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#important-global-flags-config-and-environment). | [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#important-global-flags-config-and-environment), README provider/setup notes, [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#sessionmode), architecture/runtime docs. | Runtime handles command discovery, value-flag prevalidation, launch-scoped flags, redacted echoes, fresh-session recovery hints, explicit sessions, provider/device launch-scoping, parent env forwarding with consistent managed idle-timeout/socket/operation-timeout overrides on top-level and helper subprocesses, subprocess completion, and package-owned Pi-scoped config for optional companion features. | Runtime tests for flags/planning/redaction/session behavior; process/ref tests for env consistency and stdio-linger completion; config/web-search/CLI tests; fake provider/specialized-skill matrix; package doctor. | Supported. Provider clouds, iOS/Appium, proxies, profiles, and credentials require external setup. |
|
|
86
87
|
|
|
87
88
|
## Follow-up decision after closure
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
The compact decision index lives at [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md). Keep this section as the active index of shipped follow-up areas and their canonical contracts.
|
|
90
91
|
|
|
91
|
-
| Area | Active contract |
|
|
92
|
+
| Area | Active contract | Decision index |
|
|
92
93
|
| --- | --- | --- |
|
|
93
94
|
| Native structured input modes (`job`, `qa`, `sourceLookup`, `networkSourceLookup`, `semanticAction`) | [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md), [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md) | [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md) |
|
|
94
95
|
| Electron lifecycle, manual CDP attach, desktop readiness, and tab/surface recovery | [`ELECTRON.md`](ELECTRON.md), [`TOOL_CONTRACT.md`](TOOL_CONTRACT.md#electron), [`COMMAND_REFERENCE.md`](COMMAND_REFERENCE.md#electron-desktop-apps) | [`docs/support-notes.md`](https://github.com/fitchmultz/pi-agent-browser-native/blob/main/docs/support-notes.md) |
|
package/docs/TOOL_CONTRACT.md
CHANGED
|
@@ -150,8 +150,8 @@ The extension always plans normal browser commands with `--json` prepended in `e
|
|
|
150
150
|
- Do not assume Playwright selector dialects such as text=Close or button:has-text('Close') are supported wrapper syntax unless current upstream agent-browser behavior has been verified.
|
|
151
151
|
- For authenticated or user-specific content explicitly requested by the user, such as feeds, inboxes, account pages, or private dashboards, use a real profile only when the user/config asks for it or profiles have been inspected; do not assume --profile Default exists on every machine. Do not use a real profile for public pages just because they are dashboards. Treat visible page content from real profiles as model-visible transcript data; use --auto-connect only if profile-based reuse is unavailable or the task is specifically about attaching to a running debug-enabled browser. If profile/user-data-dir resolution fails, stop retrying opens, run profiles and/or doctor through agent_browser, then report what the user needs to configure.
|
|
152
152
|
- Do not invent fixed explicit session names for routine tasks. Use the implicit session unless you truly need multiple isolated browser sessions in the same conversation.
|
|
153
|
-
- When using launch-scoped flags (--auto-connect, --allowed-domains, --namespace, --cdp, --enable, --executable-path, --webgpu, --init-script, --device, --profile, --provider, -p, --session-name, --restore, --restore-save, --restore-check-url, --restore-check-text, --restore-check-fn, --state), put them on the first command for that session. If you intentionally use an explicit --session, keep using that same explicit session for follow-ups.
|
|
154
|
-
- If you already used the implicit session and now need launch-scoped flags (--auto-connect, --allowed-domains, --namespace, --cdp, --enable, --executable-path, --webgpu, --init-script, --device, --profile, --provider, -p, --session-name, --restore, --restore-save, --restore-check-url, --restore-check-text, --restore-check-fn, --state), retry with top-level sessionMode set to fresh or pass an explicit --session for the new launch; never pass --session-mode inside args. After a successful unnamed fresh launch, later auto calls follow that new session.
|
|
153
|
+
- When using launch-scoped flags (--auto-connect, --allowed-domains, --namespace, --cdp, --enable, --executable-path, --webgpu, --init-script, --idle-timeout, --device, --profile, --provider, -p, --session-name, --restore, --restore-save, --restore-check-url, --restore-check-text, --restore-check-fn, --state), put them on the first command for that session. If you intentionally use an explicit --session, keep using that same explicit session for follow-ups.
|
|
154
|
+
- If you already used the implicit session and now need launch-scoped flags (--auto-connect, --allowed-domains, --namespace, --cdp, --enable, --executable-path, --webgpu, --init-script, --idle-timeout, --device, --profile, --provider, -p, --session-name, --restore, --restore-save, --restore-check-url, --restore-check-text, --restore-check-fn, --state), retry with top-level sessionMode set to fresh or pass an explicit --session for the new launch; never pass --session-mode inside args. After a successful unnamed fresh launch, later auto calls follow that new session.
|
|
155
155
|
- For WebGPU pages, use args ["--webgpu", "open", "<url>"] on a fresh local browser launch; use doctor --webgpu (or --headed on Linux/Windows capture paths) to prove rendering before trusting a non-black screenshot. WebGPU cannot be combined with --cdp, --auto-connect, or provider launches unless --webgpu false overrides an enabled config/environment default.
|
|
156
156
|
- For --allowed-domains, use a fresh local Chrome context. Upstream rejects CDP/auto-connect, profiles, restore/state replay, direct-page providers, iOS/Safari, and startup/profile Chrome args because they cannot guarantee containment; Chromium also disables RTCPeerConnection while the allowlist is active.
|
|
157
157
|
- For React introspection, launch the page with --enable react-devtools before first navigation, then use react tree, react inspect <fiberId>, sourceLookup candidates for local UI source hints, react renders start/stop, or react suspense; sourceLookup is experimental and reports confidence/evidence instead of guaranteed DOM-to-file mappings. For failed fetches and APIs, networkSourceLookup (experimental) correlates failed network requests with initiator metadata and bounded workspace URL literals—candidates only, not definitive blame. Use vitals [url] for Core Web Vitals and hydration timing, and pushstate <url> for client-side SPA navigation.
|
|
@@ -252,7 +252,7 @@ If a raw `find` or compiled `semanticAction` fails with `failureCategory: "selec
|
|
|
252
252
|
|
|
253
253
|
If a compiled `semanticAction` fails with `failureCategory: "selector-not-found"`, visible content can also include an `Agent-browser candidate fallbacks` block when the wrapper has bounded role/name retries for that locator and action, and `details.nextActions` includes the normal `refresh-interactive-refs` snapshot step plus those entries. When `session` was provided, candidate retry args preserve the same `--session <session>` prefix. Today `buildSemanticActionCandidateActions` in `extensions/agent-browser/index.ts` only appends click candidates for `click` + `text` → `try-button-name-candidate` and `try-link-name-candidate`. Fill misses no longer emit `find … fill <text>` retry actions because those would repeat potentially sensitive text. Instead, when the same selector-miss snapshot finds exact current editable refs (`searchbox` or `textbox`), the wrapper emits `details.richInputRecovery`, visible `Rich input recovery`, and `focus-current-editable-ref` / `click-current-editable-ref` (numbered when ambiguous) next actions. Those actions carry only focus/click argv for the candidate ref; they do not copy fill text, press `Enter`, or submit. Use `keyboard inserttext` or `keyboard type` with the intended text only after focusing the right current ref, and submit only when the user flow explicitly calls for it. Candidate fallbacks are heuristics, not proof that an element exists; inspect the page when several controls could share the same name.
|
|
254
254
|
|
|
255
|
-
If a compiled `semanticAction` `find` action fails with `failureCategory: "stale-ref"`, `details.nextActions` includes `retry-semantic-action-after-stale-ref` with the same redacted compiled argv as `details.compiledSemanticAction` in `params.args` (any leading `--session` pair from `semanticAction.session`, then the `find` tokens). The wrapper appends that entry **after** any `refresh-interactive-refs` snapshot step from `buildAgentBrowserNextActions` in `extensions/agent-browser/lib/results/action-recommendations.ts` (
|
|
255
|
+
If a compiled `semanticAction` `find` action fails with `failureCategory: "stale-ref"`, `details.nextActions` includes `retry-semantic-action-after-stale-ref` with the same redacted compiled argv as `details.compiledSemanticAction` in `params.args` (any leading `--session` pair from `semanticAction.session`, then the `find` tokens). The wrapper appends that entry **after** any `refresh-interactive-refs` snapshot step from `buildAgentBrowserNextActions` in `extensions/agent-browser/lib/results/action-recommendations.ts` (see `extensions/agent-browser/index.ts` where `nextActions` is merged). That retry is only offered because the semantic target is stable and the stale-ref error proves the previous action did not execute; `select` shorthands with stale `@e…` selectors and direct stale `@e…` commands still return refresh guidance instead of an unsafe blind retry.
|
|
256
256
|
|
|
257
257
|
For direct page-scoped `@e…` refs, successful `snapshot` results record `details.refSnapshot` with the latest ref ids and page target for the session. A failed session `snapshot` whose upstream error says `No active page` clears that session’s prior ref snapshot and records `details.refSnapshotInvalidation.reason: "no-active-page"`; mutation-prone `@e…` preflight then fails with `failureCategory: "stale-ref"` until a later successful `snapshot -i` records fresh refs. Before mutation-prone ref commands such as `click`, `fill`, `check`, `select`, `download`, drag/upload/keyboard-style actions, or equivalent batch steps run, the wrapper rejects refs from an older page target, refs absent from the latest same-page snapshot, or refs from an invalidated snapshot state. This is a best-effort wrapper guard against upstream ref-number recycling after navigation; it does not prove the DOM stayed unchanged after the snapshot. Refresh with the session-aware `refresh-interactive-refs` next action before retrying.
|
|
258
258
|
|
|
@@ -609,7 +609,7 @@ Example:
|
|
|
609
609
|
Behavior:
|
|
610
610
|
- if `args` already include `--session` (including argv compiled from optional `semanticAction.session`), upstream session choice wins
|
|
611
611
|
- `"auto"` prepends the current extension-managed active session when appropriate
|
|
612
|
-
- `"fresh"` rotates that managed session to a fresh upstream launch so startup-scoped flags like `--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` apply and later default calls follow the new browser
|
|
612
|
+
- `"fresh"` rotates that managed session to a fresh upstream launch so startup-scoped flags like `--profile`, `--executable-path`, `--webgpu`, `--restore`, `--restore-save`, restore check flags, `--namespace`, `--session-name`, `--cdp`, `--state`, `--auto-connect`, `--init-script`, `--idle-timeout`, `--enable`, `-p` / `--provider`, or iOS `--device` apply and later default calls follow the new browser; `--idle-timeout` must equal the Pi process's configured managed idle timeout or the wrapper rejects it with restart guidance
|
|
613
613
|
- upstream `--webgpu` is a launch-scoped optional boolean: both enabled and explicit `false` values require a fresh managed launch once an implicit session exists; enabled WebGPU is local-launch-only and upstream rejects combinations with CDP, auto-connect, or providers
|
|
614
614
|
- upstream restore sessions may periodically save cookies/localStorage while open; `AGENT_BROWSER_AUTOSAVE_INTERVAL_MS` passes through unchanged (`30000` default, `0` disables periodic saves but keeps save-on-close), and those restore files remain upstream-owned rather than wrapper artifacts
|
|
615
615
|
- sessionless paths skip that injection even under `"auto"`: plain-text `--help` / `-h` / `--version` / `-V` (see the generated inspection playbook fragment below), read-only `skills list`, `skills get …`, and `skills path …`, local auth profile management (`auth save/list/show/delete/remove`), local/setup commands (`profiles`, `dashboard start/stop`, `device list`, `doctor`, `install`, `upgrade`, `session id`, `session info`, `session list`, `plugin add/list/show/run`, `mcp --help`), and targeted/all local saved-state maintenance (`state list/show`, `state clear --all`, `state clear -a`, `state clear <session-name>`, `state clean --older-than <days>`, `state rename`) keep `effectiveArgs` free of the implicit managed `--session` unless the caller supplied `--session` explicitly; successful results therefore omit `usedImplicitSession` and the extension-managed `sessionName` for those calls, while bare `mcp` server calls are rejected before spawn and root `session`, untargeted `state clear`, bare `state clean`, browser-backed `auth login`, and `state save/load` keep normal managed-session injection (`extensions/agent-browser/lib/command-policy.ts`, `needsManagedSession`; `extensions/agent-browser/lib/runtime.ts`, `buildExecutionPlan`)
|
|
@@ -713,7 +713,7 @@ Ref preflight details (command taxonomy in `extensions/agent-browser/lib/command
|
|
|
713
713
|
|
|
714
714
|
**Presentation redaction (implementation map):** Successful non-`batch` tool calls and each successful `batchSteps[]` row run upstream `data` through `redactPresentationData` in `extensions/agent-browser/lib/results/presentation/diagnostics.ts`: `cookies` still walk objects/arrays and replace case-insensitive `value` keys with `"[REDACTED]"`; `storage` redacts values when the key or value looks credential-like (token, cookie, auth, secret, JWT, bearer/basic credential, high-entropy token-like string, or nested sensitive JSON) but keeps low-risk primitive QA values such as booleans, numbers, and short strings visible. Redacted storage entries add `valueRedacted` plus `valueRedactionReason` in `details.data`; diagnostic formatters mirror the same decision. Every other command’s payload is recursively scrubbed with `redactStructuredPresentationValue`, which redacts known sensitive key names and applies string-level sensitivity heuristics so network, diff, trace/profiler, stream, dashboard, chat, and other structured results do not echo bearer tokens, proxy credentials, or similar fields verbatim into `details.data`. Echoed `command` arrays in `details` and in batch roll-ups use `redactInvocationArgs` from `extensions/agent-browser/lib/runtime.ts` to mask trailing values for sensitive global flags (including `--body`, `--headers`, `--password`, and `--proxy`), preserve the special positional rules for `cookies set`, `storage local|session set`, and `set credentials`, and scrub other argv tokens for URLs and inline secrets. Failed batch steps additionally run `redactExactValues` on structured step errors so literals taken from that step’s argv (cookie value, storage set value, `--password` / `--password=` tokens) cannot reappear inside formatted error blobs.
|
|
715
715
|
|
|
716
|
-
`nextActions` is an optional machine-readable list of exact native `agent_browser` follow-ups. Each entry includes `tool: "agent_browser"`, an `id`, a short `reason`, optional `safety`, and either `params` (`args`, optional `stdin`, optional `sessionMode`, optional `networkSourceLookup`, optional `electron`) or an `artifactPath` for saved-file workflows. Agents should prefer these payloads over prose when present. When a result ran under upstream `--namespace <name>`, follow-up `params.args` preserve that namespace so retries and diagnostics target the same daemon/restore-state space. Tab/session recovery id strings are centralized in `AGENT_BROWSER_RECOVERY_NEXT_ACTION_IDS`, while rich-input focus/click recovery ids are centralized in `AGENT_BROWSER_RICH_INPUT_RECOVERY_NEXT_ACTION_IDS` plus `getAgentBrowserRichInputRecoveryNextActionId(s)` in `extensions/agent-browser/lib/results/recovery-actions.ts
|
|
716
|
+
`nextActions` is an optional machine-readable list of exact native `agent_browser` follow-ups. Each entry includes `tool: "agent_browser"`, an `id`, a short `reason`, optional `safety`, and either `params` (`args`, optional `stdin`, optional `sessionMode`, optional `networkSourceLookup`, optional `electron`) or an `artifactPath` for saved-file workflows. Agents should prefer these payloads over prose when present. When a result ran under upstream `--namespace <name>`, follow-up `params.args` preserve that namespace so retries and diagnostics target the same daemon/restore-state space. Tab/session recovery id strings are centralized in `AGENT_BROWSER_RECOVERY_NEXT_ACTION_IDS`, while rich-input focus/click recovery ids are centralized in `AGENT_BROWSER_RICH_INPUT_RECOVERY_NEXT_ACTION_IDS` plus `getAgentBrowserRichInputRecoveryNextActionId(s)` in `extensions/agent-browser/lib/results/recovery-actions.ts`; docs and tests mirror those registries/helpers rather than inventing recovery ids in prose. Current recommendations include: timed-out jobs/batches with a retryable read-only/idempotent first incomplete step → `retry-timeout-step`, while timed-out flows whose first incomplete step may be mutating → `inspect-current-page-after-timeout` (`snapshot -i`) before splitting the remaining work into shorter batches; raw `connect` success → session-scoped `list-connected-session-tabs` only, then the agent should inspect/select a stable `tab t<N>` target and run `snapshot -i` explicitly; `snapshot` failures whose upstream error says `No active page` and whose wrapper result has a known session → `list-tabs-after-no-active-page` only, because this path has no wrapper-observed safe tab id to select atomically; browser profile/user-data-dir resolution failures → `inspect-browser-profiles` (`profiles`) and `run-agent-browser-doctor` (`doctor`) before retrying opens; Electron launches → wrapper-tracked `electron.status` / `electron.probe` / `electron.cleanup` actions plus session-scoped tab/snapshot inspection when attached; Electron status/probe mismatch diagnostics → `reattach-electron-launch` plus fresh tab/snapshot inspection; Electron post-command health failures → status/probe/cleanup for the same `launchId`; Electron or contenteditable fill verification mismatches → `inspect-after-fill-verification` and `verify-filled-value`; Electron same-URL ref freshness warnings → `refresh-electron-refs-after-rerender`; packaged-Electron `sourceLookup` no-candidate diagnostics → session snapshot, launch probe, and tab list; Electron cleanup partial failures → status plus retry-cleanup for the same wrapper-owned `launchId`; `open` success → `snapshot -i`; mutating/navigation commands (see `buildAgentBrowserNextActions` in source for the exact command set) → `snapshot -i`; stale refs and selector failures → `snapshot -i` via `refresh-interactive-refs` (prefixed with `--session <name>` when the failed call ran in a named or managed session); selector misses with exact current snapshot role/name matches → direct ref retries via `try-current-visible-ref` or bounded `try-current-visible-ref-N` for non-fill targets; semantic `fill` selector misses with exact current editable refs → `focus-current-editable-ref` / `click-current-editable-ref` or numbered variants that do not include fill text or submit; unknown getter shortcuts such as `title` / `url` → exact read-only retries like `get title` / `get url` with ids `use-get-title` / `use-get-url`; compact `network requests` results with safe request IDs → bounded read-only request detail, `networkSourceLookup`, path filter, or HAR-capture follow-ups; semantic `selector-not-found` failures that compiled from `semanticAction` may append `try-button-name-candidate` or `try-link-name-candidate` after presentation `nextActions` only for the bounded click pair enumerated under `semanticAction`; semantic `stale-ref` failures that compiled from `semanticAction` `find` argv may also include `retry-semantic-action-after-stale-ref` after that snapshot step; successful snapshots or qualifying same-URL non-Electron top-level clicks (see `overlayBlockers` below) with snapshot evidence of likely overlay/banner/dialog close controls may append `inspect-overlay-state` and bounded `try-overlay-blocker-candidate-*` entries; successful top-level `scroll` calls whose pre/post viewport and sampled scroll-container positions do not change may append `inspect-after-noop-scroll` and `verify-noop-scroll-visually`; explicit combobox-targeted actions that focus a combobox without visible options may append `inspect-focused-combobox`, `try-open-combobox-with-arrow`, and `try-open-combobox-with-enter`; `get text <selector>` calls with hidden/multiple CSS matches may append `inspect-visible-text-candidates` with a read-only `eval --stdin` probe (each prefixed with `--session <name>` when `details.sessionName` is set, same `sessionPrefixArgs` rule as other session-scoped follow-ups); confirmations → exact `confirm <id>` and `deny <id>` choices; generic tab drift → `list-tabs-for-recovery` with `tab list` first, then select or confirm the stable target before running `snapshot -i`; about:blank or tab-drift recovery with a wrapper-known target → `list-tabs-for-about-blank-recovery` or `list-tabs-for-tab-drift-recovery`, plus `select-intended-tab-after-drift` and `snapshot-after-tab-recovery` when the wrapper already observed the stable `t<N>` tab id; `wait --text` assertion failures → `inspect-after-text-assertion-failure` with a read-only snapshot; download verification failures or missing successful download artifacts → `wait --download [path]`; saved artifacts → the artifact path to inspect/consume after checking `artifactVerification`/metadata; missing non-download artifacts → `verify-artifact-path` so agents do not trust an absent file. When nothing applies, the field is omitted.
|
|
717
717
|
|
|
718
718
|
**Unknown-command getter hints (failure presentation):** `buildErrorPresentation` in `extensions/agent-browser/lib/results/presentation/errors.ts` only runs this path when upstream error text (after model-facing redaction) matches `unknown command`, `unknown subcommand`, or `unrecognized command` (case-insensitive) **and** the failed invocation’s primary command token is one of `attr`, `count`, `html`, `text`, `title`, `url`, or `value`. Visible text then includes a grouped-`get` hint line plus per-token guidance (`get text <selector>`, `get html …`, `get attr …`, `get count …`, `get value …`, `get title`, `get url`). Machine `nextActions` with ids `use-get-title` / `use-get-url` are emitted only for `title` / `url`, with `params.args` optionally prefixed by `--session <name>` when the failed call targeted a named session. If the error string already contains `Agent-browser hint:` from selector recovery (stale-ref or unsupported selector dialect appendages), the getter block is skipped so two stacked `Agent-browser hint:` headers are not emitted.
|
|
719
719
|
|
|
@@ -777,7 +777,7 @@ When `semanticAction` produced compiled `find` argv and the unified result is `f
|
|
|
777
777
|
|
|
778
778
|
Implementation and precedence:
|
|
779
779
|
|
|
780
|
-
- Shared machine-readable types are centralized in `extensions/agent-browser/lib/results/contracts.ts` (including re-exports such as `AgentBrowserNextAction` from `next-actions.ts`). Classifiers live in `categories.ts` (`classifyAgentBrowserSuccessCategory`, `classifyAgentBrowserFailureCategory`, `buildAgentBrowserResultCategoryDetails`—the last prefers an explicit `failureCategory` when the caller already knows the bucket, otherwise it runs the classifier). Generic follow-up assembly lives in `action-recommendations.ts` (`buildAgentBrowserNextActions`). Tab/session recovery ids live in `recovery-actions.ts` (`AGENT_BROWSER_RECOVERY_NEXT_ACTION_IDS`, `AGENT_BROWSER_RICH_INPUT_RECOVERY_NEXT_ACTION_IDS`, `getAgentBrowserRichInputRecoveryNextActionId`, `getAgentBrowserRichInputRecoveryNextActionIds`, `buildRecoveryNextActions`) and session-aware wrappers live in `recovery-next-actions.ts`. Selector miss and rich-input diagnostic shapes/actions live in `selector-recovery.ts`.
|
|
780
|
+
- Shared machine-readable types are centralized in `extensions/agent-browser/lib/results/contracts.ts` (including re-exports such as `AgentBrowserNextAction` from `next-actions.ts`). Classifiers live in `categories.ts` (`classifyAgentBrowserSuccessCategory`, `classifyAgentBrowserFailureCategory`, `buildAgentBrowserResultCategoryDetails`—the last prefers an explicit `failureCategory` when the caller already knows the bucket, otherwise it runs the classifier). Generic follow-up assembly lives in `action-recommendations.ts` (`buildAgentBrowserNextActions`). Tab/session recovery ids live in `recovery-actions.ts` (`AGENT_BROWSER_RECOVERY_NEXT_ACTION_IDS`, `AGENT_BROWSER_RICH_INPUT_RECOVERY_NEXT_ACTION_IDS`, `getAgentBrowserRichInputRecoveryNextActionId`, `getAgentBrowserRichInputRecoveryNextActionIds`, `buildRecoveryNextActions`) and session-aware wrappers live in `recovery-next-actions.ts`. Selector miss and rich-input diagnostic shapes/actions live in `selector-recovery.ts`. Failed upstream `network requests` rows flow through `classifyNetworkRequestFailure` / `summarizeNetworkFailures` in `network.ts` for QA analysis (`analyzeQaPresetResults` in `extensions/agent-browser/index.ts`) and for actionable-vs-benign lines plus request-specific nextActions in `network requests` presentation (`extensions/agent-browser/lib/results/presentation/diagnostics.ts`).
|
|
781
781
|
- Artifact verification: `ArtifactVerificationSummary` / `ArtifactVerificationEntry` types live in `contracts.ts`. `buildArtifactVerificationSummary`, `getArtifactVerificationEntry`, and `getManifestVerificationEntry` in `presentation/artifacts.ts` merge each resolved file artifact with manifest rows whose `storageScope` is not `explicit-path` (those rows duplicate file artifacts) and whose `path` is in the current result’s spill path set. Presentation then fails closed with `failureCategory: "artifact-missing"` when any resolved non-pending file artifact has `exists: false`; pending recording-start artifacts and non-explicit spill rows do not trigger this failure. If no hard-missing file artifact exists, successful presentation merges run `classifyPresentationSuccessCategory`, which can still force `successCategory: "artifact-unverified"` for unverified counts before delegating to `classifyAgentBrowserSuccessCategory`.
|
|
782
782
|
- Inner success categories (`classifyAgentBrowserSuccessCategory` in `categories.ts`, after verification counts are clear): if `inspection` is true → `"inspection"`; else if any non-pending artifact lacks confirmed on-disk presence (`exists !== true`) and was not upgraded to an `artifact-missing` failure → `"artifact-unverified"`; else if there is a `savedFile` or any `artifacts` → `"artifact-saved"`; else → `"completed"`.
|
|
783
783
|
- Failure: the classifier walks a single ordered chain (first match wins): `confirmation-required` → `timeout` → `missing-binary` → `parse-failure` → `aborted` → `policy-blocked` → `cleanup-failed` → `tab-drift` → `stale-ref` (including “unknown ref” text and a narrow `@eN` plus “element not found” heuristic) → `selector-unsupported` → `selector-not-found` → `download-not-verified` (download / wait-download style failures) → `validation-error` when a wrapper `validationError` is present → default `upstream-error`. Wrapper-known missing artifact checks pass an explicit `artifact-missing` category rather than relying on this text classifier.
|
|
@@ -807,7 +807,8 @@ Additional structured fields can appear when relevant:
|
|
|
807
807
|
- `snapshotDiff` after wrapper-side `snapshot --diff` (with or without `-i`, `--search`, `--filter`, or `--viewport`). Shape: `{ addedRefs, removedRefs, changedRefs, unchangedRefs, summary }`, comparing ref ids plus role/name metadata from the previous wrapper-tracked snapshot for the session with the newly returned full ref map. It is a quick ref-map delta, not a visual diff.
|
|
808
808
|
- `networkRequestsPageFilter` after wrapper-side `network requests --current-page`, `--current-origin`, or `--current-url`. Shape: `{ cleanArgs, currentUrl, mode, matchedRows, totalRows }`; the visible rows and `details.data.requests` / `items` / `entries` are filtered while the active session page target is read with `get url`.
|
|
809
809
|
- `richInputRecovery` after a raw `find` or compiled `semanticAction` `fill` fails with `selector-not-found` and the same current-ref diagnostic finds exact editable `searchbox` / `textbox` candidates. Shape follows `RichInputRecoveryDiagnostic` in `extensions/agent-browser/lib/results/selector-recovery.ts`: `{ candidates, inputMethodHint, nextActionIds, summary, target }`, where each candidate has `ref`, `role`, `name`, `focusArgs`, `clickArgs`, and `reason`. Visible text appends `Rich input recovery`, and `details.nextActions` gains ids from `getAgentBrowserRichInputRecoveryNextActionIds`: `focus-current-editable-ref` / `click-current-editable-ref` (or numbered variants). These actions are bounded to focus/click/inspect-style recovery: they do not include the fill text, do not press `Enter`, and do not submit. After the right current editable ref is focused, the agent should use `keyboard inserttext` or `keyboard type` with the intended text in a separate call and submit only when explicitly required by the flow.
|
|
810
|
-
- `
|
|
810
|
+
- `scrollPage` when the wrapper moves `document.scrollingElement` directly for `scroll <up|down|left|right> [px|percent]` or `scroll to end|top`; it temporarily disables smooth scrolling so immediate before/after offsets are reliable, returns `{ request, result }`, and includes `exitCode: 0` on success. Directional document no-movement falls through to upstream wheel behavior so nested panes still work. Explicit CSS-container calls `scroll <selector> <up|down|left|right> [px|percent]` remain wrapper-handled and report `details.scrollContainer`. All scroll helper shims are skipped when startup-scoped flags are present so the requested browser/profile launches before any helper command.
|
|
811
|
+
- `scrollNoop` after a successful large **top-level** upstream scroll fallback on an existing or fresh managed session when wrapper-side read-only probes before and after the command show no change in `window.scrollX` / `window.scrollY` and no change in the sampled prominent scrollable containers. To avoid pre-launching a session without caller startup state, this probe is skipped for small pixel scrolls, calls that would create a managed session only for the probe, and invocations with startup-scoped flags such as `--profile`, `--state`, `--restore`, `--namespace`, `--session-name`, `--cdp`, providers, init scripts, or similar launch settings. Shape: `{ reason: "no-observed-scroll-position-change", message, before, after, recommendations }`; `before` / `after` include viewport dimensions, document scroll dimensions, and up to ten sampled container descriptors plus scroll offsets. Container descriptors use only sample index, tag name, and ARIA role; DOM ids/classes are intentionally not stored. This diagnostic is conservative evidence that the page-level scroll likely missed a nested pane, not proof that every app-specific region is unchanged. Visible text starts with `Scroll completed with no observed movement`, appends `Scroll diagnostic: no observed scroll movement`, sets `details.data.scrolled` to `false` / `details.data.noMovement` to `true`, and `details.nextActions` gains `inspect-after-noop-scroll` (`snapshot -i`) plus `verify-noop-scroll-visually` (`screenshot`), session-prefixed when applicable.
|
|
811
812
|
- `comboboxFocus` after a successful explicit combobox-targeted `click` / `fill` / `find … click|fill` (for example `semanticAction` with role `combobox`, including when that semantic action resolves through a current visible `@ref` before execution) when a read-only probe sees the active element is combobox-like, `aria-expanded` is explicitly present (`false` or `true`), and no visible `listbox` / `option` / menu option elements are open. Shape: `{ reason: "focused-combobox-without-visible-options", message, activeElement, visibleListboxCount, visibleOptionCount, recommendations }`; `activeElement` includes bounded role/tag/expanded/hasPopup/name metadata with normal text redaction. Visible text appends `Combobox diagnostic: focused combobox did not expose visible options`, and `details.nextActions` gains `inspect-focused-combobox` (`snapshot -i`), `try-open-combobox-with-arrow` (`press ArrowDown`), and `try-open-combobox-with-enter` (`press Enter`), session-prefixed when applicable. The diagnostic is deliberately gated to explicit combobox-targeted calls to avoid extra probes or false positives on ordinary clicks/textboxes.
|
|
812
813
|
- `recordingDependencyWarning` after a successful `record start` or `record restart` when the wrapper cannot find an executable `ffmpeg` on the Pi process `PATH`. Shape: `{ reason: "ffmpeg-missing-for-recording", dependency: "ffmpeg", command, message, recommendations }`. Visible text appends `Recording dependency warning: ffmpeg not found on PATH`. This is a non-blocking preflight warning: upstream may start recording, but `record stop` needs `ffmpeg` to encode the WebM.
|
|
813
814
|
- `selectorTextVisibility` after a **successful** upstream `get text <selector>` (standalone or inside a successful `batch`) when the wrapper’s follow-up probe finds a hazard: more than one DOM match (upstream reads the first `querySelectorAll` hit, which may be the wrong tab/panel), or the first match is hidden while at least one other match is visible (requires multiple DOM nodes so a visible peer exists; a lone hidden match is not flagged). The probe is a read-only `eval --stdin` script (`buildVisibleTextProbeScript` in `extensions/agent-browser/lib/orchestration/browser-run/diagnostics.ts`) that counts matches, applies a small visibility heuristic (`display`/`visibility`/`opacity` plus non-zero client rects), may include a redacted `firstVisibleTextPreview`, and may include up to eight `visibleCandidates` entries (`index` in `querySelectorAll`, `tagName`, optional `role`, optional redacted `textPreview`). It is **not** run for simple id selectors, page-scoped `@e…` selectors, or when the selector string is withheld because `selectorMayExposeSensitiveLiteral` would risk echoing secrets in probe output. `details.selectorTextVisibility` mirrors the primary diagnostic (first sorted entry); when several selectors in one `batch` qualify, `selectorTextVisibilityAll` lists every diagnostic sorted so hidden-first cases precede generic multi-match ambiguity. Appended visible warning text names the matching `details.nextActions` id and may list visible candidate previews. Appended `details.nextActions` use ids `inspect-visible-text-candidates` and `inspect-visible-text-candidates-2`, … with the probe replayed via `eval --stdin` for each hazardous selector. If the probe still leaves more than one visible candidate, it is only ambiguity evidence; agents should narrow the selector, use a current visible `@ref`, or run a targeted visible-element `eval --stdin` rather than trusting the broad selector.
|
|
@@ -871,7 +872,7 @@ If `agent-browser` is not on `PATH`, fail with a message that:
|
|
|
871
872
|
- treat the extension-managed session as convenience state owned by the wrapper
|
|
872
873
|
- preserve the current branch-visible extension-managed session across `/reload`, exact-session relaunch, `/resume`, and Pi `session_tree` branch transitions so persisted sessions can keep following the live browser after lifecycle changes
|
|
873
874
|
- close the active extension-managed session when the originating `pi` process quits, while leaving explicit caller-provided sessions alone
|
|
874
|
-
- set
|
|
875
|
+
- set one idle timeout on extension-managed sessions as a backstop for abnormal exits or cleanup failures, and pass that same `AGENT_BROWSER_IDLE_TIMEOUT_MS` to top-level commands plus every wrapper helper subprocess so upstream does not restart the background browser, reset the active tab, or discard current refs between a snapshot and action
|
|
875
876
|
- clean up process-private temp spill artifacts on shutdown, while keeping persisted-session snapshot spill files in a private session-scoped artifact directory so `details.fullOutputPath` survives reload/restart and the oldest spill files are evicted if the per-session artifact budget is exceeded
|
|
876
877
|
- reconstruct the current branch-visible extension-managed session, latest page-scoped refs, latest `artifactManifest`, and wrapper-tracked Electron launch records from the active transcript branch on `session_start` and Pi `session_tree` so later default calls keep following the active managed browser and can continue reporting artifact retention state; successful explicit wrapper-owned close rows and `electron.cleanup` managed-session steps are restore-visible close events
|
|
877
878
|
- keep runtime cleanup ownership separate from branch-visible state: `session_tree` restore and wrapper-owned browser commands are serialized with managed-session work; independent caller-owned explicit-session commands can still run in parallel, but a branch-state generation guard prevents stale completions from overwriting a newer branch restore. Extension-managed sessions and wrapper-launched Electron records owned by the current process remain eligible for quit/cleanup, and fresh-session allocation stays monotonic across branch restores, including auto rows and close rows that reference wrapper-generated fresh names
|
|
@@ -893,7 +894,7 @@ If `agent-browser` is not on `PATH`, fail with a message that:
|
|
|
893
894
|
- keep wrapper-spawned commands bounded by clamping `AGENT_BROWSER_DEFAULT_TIMEOUT` to the upstream documented default of 25 seconds while the default wrapper child-process watchdog is 35 seconds (`PI_AGENT_BROWSER_PROCESS_TIMEOUT_MS` overrides it, and top-level `timeoutMs` overrides it per call for browser CLI subprocesses). Explicit `wait <ms>` or `wait --timeout <ms>` calls can exceed that default; when top-level `timeoutMs` is omitted, the wrapper derives a per-call subprocess watchdog from the requested wait duration plus a small grace window. Dialog commands use `PI_AGENT_BROWSER_DIALOG_PROCESS_TIMEOUT_MS` (default 5000 ms), and click/tap/find refs or tokens plus `eval --stdin` snippets whose text looks like alert/confirm/prompt/dialog triggers use `PI_AGENT_BROWSER_DIALOG_TRIGGER_PROCESS_TIMEOUT_MS` (default 8000 ms). Timed-out compiled `job` / `qa` or caller `batch` calls may add `details.timeoutPartialProgress` and visible `Timeout partial progress` evidence with per-step status, retry payloads, current page title/URL, and declared artifact path checks; timed-out dialog-like commands may add dialog status/dismiss/fresh-session recovery next actions
|
|
894
895
|
- interactive or long-running upstream families such as `chat` without a prompt, `dashboard start`, `stream enable`, `trace start`, `profiler start`, `record start`, `inspect`, `install`, `upgrade`, `doctor --fix`, and `confirm-interactive` are passed through thinly but remain bounded by the same wrapper timeout/session planning rules; prefer explicit arguments, single-shot `chat <message>`, non-interactive flags like `doctor --offline --quick` or `doctor --json`, and cleanup pairs such as `dashboard stop`, `stream disable`, `trace stop`, `profiler stop`, and `record stop`
|
|
895
896
|
- treat successful plain-text inspection commands like `--help` and `--version` as stateless: do not inject the implicit managed session and do not let those calls claim the managed-session slot
|
|
896
|
-
- if startup-scoped flags like `--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` are supplied after the implicit session is already active while `sessionMode` is `"auto"`, return a validation error with a structured recovery hint that recommends `sessionMode: "fresh"`
|
|
897
|
+
- if startup-scoped flags like `--profile`, `--executable-path`, `--webgpu`, `--restore`, `--restore-save`, restore check flags, `--namespace`, `--session-name`, `--cdp`, `--state`, `--auto-connect`, `--init-script`, `--idle-timeout`, `--enable`, `-p` / `--provider`, or iOS `--device` are supplied after the implicit session is already active while `sessionMode` is `"auto"`, return a validation error with a structured recovery hint that recommends `sessionMode: "fresh"`
|
|
897
898
|
- for direct headless local Chrome launches to `chat.com` / `chatgpt.com` / `chat.openai.com`, allow a narrow compatibility fallback that injects a normal Chrome `--user-agent` only when the caller did not explicitly provide one and did not choose `--headed`, `--cdp`, `--auto-connect`, or a provider-backed launch
|
|
898
899
|
|
|
899
900
|
## Non-goals
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-agent-browser-native",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.71",
|
|
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)",
|
|
@@ -94,7 +94,6 @@
|
|
|
94
94
|
"prepublishOnly": "npm run verify -- release && npm pack --dry-run",
|
|
95
95
|
"build": "node ./scripts/build.mjs",
|
|
96
96
|
"startup-profile": "node ./scripts/profile-startup.mjs",
|
|
97
|
-
"prepack": "npm run build",
|
|
98
97
|
"prepare": "node ./scripts/prepare.mjs"
|
|
99
98
|
},
|
|
100
99
|
"packageManager": "npm@11.14.0",
|
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
import { CAPABILITY_BASELINE } from "./scripts/agent-browser-capability-baseline.mjs";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const PLATFORM_SMOKE_AGENT_BROWSER_VERSION = CAPABILITY_BASELINE.targetVersion;
|
|
7
|
+
const PLATFORM_SMOKE_UBUNTU_IMAGE = `pi-agent-browser-native-platform:node24-agent-browser${PLATFORM_SMOKE_AGENT_BROWSER_VERSION}`;
|
|
8
8
|
|
|
9
9
|
export default {
|
|
10
10
|
packageName: "pi-agent-browser-native",
|
|
11
11
|
artifactRoot: ".artifacts/platform-smoke",
|
|
12
12
|
requiredTargets: ["macos", "ubuntu", "windows-native"],
|
|
13
13
|
requiredSuites: ["platform-build", "browser-dogfood-smoke"],
|
|
14
|
-
supportedTargets: ["macos", "ubuntu", "windows-native"],
|
|
15
14
|
requiredCrabbox: {
|
|
16
15
|
install: "Homebrew package or PLATFORM_SMOKE_CRABBOX override",
|
|
17
16
|
minVersion: "0.26.0",
|
|
@@ -126,8 +126,7 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
126
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
|
-
|
|
130
|
-
validateNames("target", targets, supportedTargets);
|
|
129
|
+
validateNames("target", targets, config.requiredTargets);
|
|
131
130
|
validateNames("suite", suites, config.requiredSuites);
|
|
132
131
|
const runs = targets.map(async (targetName) => {
|
|
133
132
|
console.log(`\n=== Target: ${targetName} ===`);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./browser-run/index.js";
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Purpose: Compatibility barrel for focused result modules.
|
|
3
|
-
* Responsibilities: Preserve the historical `./results/shared.js` import surface while delegating all logic to focused files.
|
|
4
|
-
* Scope: Re-exports only; do not add runtime policy here.
|
|
5
|
-
* Usage: Existing internal imports may keep using this path during migration, while new code should prefer focused modules.
|
|
6
|
-
* Invariants/Assumptions: This file intentionally contains no business logic so `shared` cannot grow back into a catch-all module.
|
|
7
|
-
*/
|
|
8
|
-
export * from "./contracts.js";
|
|
9
|
-
export * from "./categories.js";
|
|
10
|
-
export * from "./action-recommendations.js";
|
|
11
|
-
export * from "./artifact-manifest.js";
|
|
12
|
-
export * from "./artifact-state.js";
|
|
13
|
-
export * from "./editable-ref-evidence.js";
|
|
14
|
-
export * from "./network.js";
|
|
15
|
-
export * from "./network-routes.js";
|
|
16
|
-
export * from "./next-actions.js";
|
|
17
|
-
export * from "./recovery-actions.js";
|
|
18
|
-
export * from "./recovery-next-actions.js";
|
|
19
|
-
export * from "./selector-recovery.js";
|
|
20
|
-
export * from "./text.js";
|