pi-agent-browser-native 0.2.26 → 0.2.28
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 +22 -0
- package/README.md +18 -4
- package/docs/COMMAND_REFERENCE.md +13 -9
- package/docs/RELEASE.md +25 -2
- package/docs/SUPPORT_MATRIX.md +18 -10
- package/docs/TOOL_CONTRACT.md +14 -9
- package/extensions/agent-browser/index.ts +528 -22
- package/extensions/agent-browser/lib/playbook.ts +26 -6
- package/extensions/agent-browser/lib/results/presentation.ts +17 -2
- package/extensions/agent-browser/lib/results.ts +1 -0
- package/extensions/agent-browser/lib/runtime.ts +2 -2
- package/package.json +1 -1
|
@@ -13,11 +13,15 @@ export const TOOL_PROMPT_GUIDELINES_PREFIX = [
|
|
|
13
13
|
"Use agent_browser whenever the task requires a real browser or live web content.",
|
|
14
14
|
] as const;
|
|
15
15
|
|
|
16
|
+
export function buildInstalledDocsGuideline(paths: { readmePath: string; commandReferencePath: string; toolContractPath: string }): string {
|
|
17
|
+
return `For deeper guidance without bloating context, read installed package docs on demand: ${paths.readmePath} for setup/external dependencies, ${paths.commandReferencePath} for command workflows, and ${paths.toolContractPath} for result/details contracts. Do not load the full command reference unless needed; prefer targeted sections.`;
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
export const QUICK_START_GUIDELINES = [
|
|
17
21
|
"Quick start mental model: use exactly one of args (exact agent-browser CLI args after the binary), semanticAction (a thin find-locator shorthand compiled to find argv), job (a constrained short-workflow schema compiled to batch), qa (a lightweight QA preset built on job/batch), or the experimental sourceLookup / networkSourceLookup helpers (each compiled to batch); stdin is only for batch, eval --stdin, auth save --password-stdin, and wrapper-generated batch stdin from job, qa, sourceLookup, or networkSourceLookup, and other command/stdin combinations are rejected before launch; sessionMode=fresh switches the extension-managed pi-scoped session to a fresh upstream launch when you need new --profile, --session-name, --cdp, --state, --auto-connect, --init-script, --enable, -p/--provider, or iOS --device state.",
|
|
18
22
|
"There is no first-class reusable named browser recipe runtime above top-level job, the qa preset, and raw batch stdin; keep recurring flows in documentation examples or those inputs (closed RQ-0068; see docs/ARCHITECTURE.md#no-reusable-recipe-layer-yet).",
|
|
19
23
|
"Common first calls: { args: [\"open\", \"https://example.com\"] } then { args: [\"snapshot\", \"-i\"] }; after navigation, use { args: [\"click\", \"@e2\"] } then { args: [\"snapshot\", \"-i\"] }.",
|
|
20
|
-
"Locator-first clicks and fills without hand-building find argv: { semanticAction: { action: \"click\", locator: \"text\", value: \"Close\" } } or { semanticAction: { action: \"fill\", locator: \"label\", value: \"Email\", text: \"user@example.com\" } }; add semanticAction.session when targeting a named upstream browser session; details.compiledSemanticAction shows the
|
|
24
|
+
"Locator-first clicks and fills without hand-building find argv: { semanticAction: { action: \"click\", locator: \"text\", value: \"Close\" } } or { semanticAction: { action: \"fill\", locator: \"label\", value: \"Email\", text: \"user@example.com\" } }; 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/uncheck actions to avoid hidden duplicate matches; selector-not-found failures may append bounded try-*-candidate next actions (and an Agent-browser candidate fallbacks prose block) for specific placeholder/text/label shapes, and stale-ref failures can return retry-semantic-action-after-stale-ref when retry safety is provable.",
|
|
21
25
|
"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\" } }, { args: [\"eval\", \"--stdin\"], stdin: \"document.title\" }, { 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\" }.",
|
|
22
26
|
"High-value command reference: download <selector> <path> saves a file triggered by a click; get title/url/text/html/value/attr/count reads page state; screenshot [path] captures an image; pdf <path> saves a PDF; tab list and tab <tab-id-or-label> inspect or recover the active tab; react tree/inspect/renders/suspense introspect React after --enable react-devtools; vitals [url] measures Core Web Vitals; pushstate <url> performs SPA navigation.",
|
|
23
27
|
"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. 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. 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.",
|
|
@@ -47,9 +51,10 @@ export const SHARED_BROWSER_PLAYBOOK_GUIDELINES = [
|
|
|
47
51
|
"For feed, timeline, or inbox reading tasks, focus on the main timeline/list region and read the first item there rather than unrelated composer or sidebar content.",
|
|
48
52
|
"For read-only browsing tasks, prefer extracting the answer from the current snapshot, structured ref labels, or eval --stdin on the current page before navigating away. Only click into media viewers, detail routes, or new pages when the current view does not contain the needed information.",
|
|
49
53
|
"For downloads, prefer download <selector> <path> when an element click should save a file. Do not rely on click alone when you need the downloaded file on disk.",
|
|
54
|
+
"On dashboards with nested scroll containers, verify scroll with a screenshot or fresh snapshot -i; if the viewport did not move, prefer scrollintoview <@ref> or target the actual scrollable region. For comboboxes, a click/semanticAction may only focus the field; re-snapshot and fall back to type, press Enter/arrow keys, select, or visible option refs.",
|
|
50
55
|
"When using eval --stdin, scope checks and actions to the target element or route whenever possible instead of relying on broad page-wide text heuristics.",
|
|
51
56
|
"When using eval --stdin for extraction, return the value you want instead of relying on console.log as the primary result channel. Prefer plain expressions like ({ title: document.title }) or explicitly invoked functions like (() => ({ title: document.title }))(); if a function-shaped snippet returns {}, details.evalStdinHint may warn that the function was serialized instead of called. If get text on a CSS selector surfaces details.selectorTextVisibility or selectorTextVisibilityAll, prefer a visible @ref, a more specific selector, or the inspect-visible-text-candidates nextAction over hidden tab content.",
|
|
52
|
-
"When details.pageChangeSummary is present, use changeType and summary as a compact signal for navigation, DOM mutation, confirmations, or artifacts; when nextActionIds is set, match those ids to entries in details.nextActions (or per-step nextActions inside batch) for concrete follow-up payloads instead of inferring from prose alone. If a no-navigation click surfaces details.overlayBlockers, inspect the fresh snapshot evidence before using a close/dismiss candidate nextAction.",
|
|
57
|
+
"When details.pageChangeSummary is present, use changeType and summary as a compact signal for navigation, DOM mutation, confirmations, or artifacts; when nextActionIds is set, match those ids to entries in details.nextActions (or per-step nextActions inside batch) for concrete follow-up payloads instead of inferring from prose alone. If a no-navigation click surfaces details.overlayBlockers, inspect the fresh snapshot evidence before using a close/dismiss candidate nextAction; ordinary page chrome without dialog/alertdialog evidence should not trigger this diagnostic.",
|
|
53
58
|
"When commands save or spill files (screenshots, downloads, PDFs, traces, recordings, HAR, large snapshot spills), treat paths as provisional until details.artifactVerification shows every row verified: branch on missingCount, pendingCount, unverifiedCount, per-entry state, and optional limitation before downstream file use.",
|
|
54
59
|
"Do not call --help or other exploratory inspection commands unless the user explicitly asks for them or debugging the browser integration is necessary.",
|
|
55
60
|
] as const;
|
|
@@ -83,11 +88,26 @@ export function buildSharedBrowserPlaybookGuidelines(options: { includeBraveSear
|
|
|
83
88
|
];
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
|
|
91
|
+
const RUNTIME_PROMPT_GUIDELINES = [
|
|
92
|
+
"Use exactly one input mode: args, semanticAction, job, qa, sourceLookup, or networkSourceLookup. Use stdin only for batch, eval --stdin, auth save --password-stdin, or wrapper-generated batch modes.",
|
|
93
|
+
"Common flow: open, snapshot -i, interact with current @refs or semanticAction, then re-snapshot after navigation, scrolling, rerenders, or DOM changes.",
|
|
94
|
+
"Prefer stable locators for visible text/names: semanticAction or upstream find with role/text/label/placeholder/alt/title/testid. Use current @refs only from the latest same-page snapshot.",
|
|
95
|
+
"Use sessionMode=fresh for launch-scoped state such as --profile, --session-name, --cdp, --state, --auto-connect, --init-script, --enable, providers, or iOS devices; otherwise let the implicit session carry continuity.",
|
|
96
|
+
"For artifacts, read visible metadata and details.artifactVerification before using files. record stop needs ffmpeg on PATH. close does not delete saved files; cleanup is host-owned.",
|
|
97
|
+
"When details.nextActions is present, prefer those exact follow-up payloads over prose or guessed selectors.",
|
|
98
|
+
"For dense snapshots, check Omitted high-value controls and details.data.highValueControlRefIds before opening large spill files.",
|
|
99
|
+
"For dashboards, verify scroll with screenshot/snapshot; if nothing moved, use scrollintoview <@ref> or target the real scroll region. Combobox clicks may only focus; re-snapshot and fall back to type, Enter/arrows, select, or option refs.",
|
|
100
|
+
"For extraction, prefer get title/url/text/html/value/attr/count or eval --stdin that returns a value; do not rely on console.log. If selector visibility warnings appear, prefer visible @refs or nextActions.",
|
|
101
|
+
"For non-core debugging, pass upstream commands through args: network, diff, trace/profiler/record, console/errors, stream, dashboard, chat, react, vitals, pushstate, dialog, frame, tab.",
|
|
102
|
+
] as const;
|
|
103
|
+
|
|
104
|
+
export function buildToolPromptGuidelines(options: { includeBraveSearch: boolean; docs?: { readmePath: string; commandReferencePath: string; toolContractPath: string } }): string[] {
|
|
87
105
|
return [
|
|
88
106
|
...TOOL_PROMPT_GUIDELINES_PREFIX,
|
|
89
|
-
...
|
|
90
|
-
...
|
|
91
|
-
...
|
|
107
|
+
...(options.docs ? [buildInstalledDocsGuideline(options.docs)] : []),
|
|
108
|
+
...RUNTIME_PROMPT_GUIDELINES,
|
|
109
|
+
...(options.includeBraveSearch ? [BRAVE_SEARCH_PROMPT_GUIDELINE] : []),
|
|
110
|
+
TOOL_PROMPT_GUIDELINES_SUFFIX[0],
|
|
111
|
+
TOOL_PROMPT_GUIDELINES_SUFFIX[1],
|
|
92
112
|
];
|
|
93
113
|
}
|
|
@@ -609,12 +609,27 @@ function formatNetworkRequestsText(data: Record<string, unknown>): string | unde
|
|
|
609
609
|
const shown = networkFailureSummary.totalCount > 0
|
|
610
610
|
? [`Network failure summary: ${networkFailureSummary.actionableCount} actionable, ${networkFailureSummary.benignCount} benign low-impact (${networkFailureSummary.totalCount} total).`]
|
|
611
611
|
: [];
|
|
612
|
-
|
|
612
|
+
const indexedRequests = requests.map((item, index) => ({ index, item }));
|
|
613
|
+
const failedRequests: typeof indexedRequests = [];
|
|
614
|
+
const normalRequests: typeof indexedRequests = [];
|
|
615
|
+
for (const indexed of indexedRequests) {
|
|
616
|
+
if (isRecord(indexed.item) && classifyNetworkRequestFailure(indexed.item)) failedRequests.push(indexed);
|
|
617
|
+
else normalRequests.push(indexed);
|
|
618
|
+
}
|
|
619
|
+
failedRequests.sort((left, right) => {
|
|
620
|
+
const leftClassification = isRecord(left.item) ? classifyNetworkRequestFailure(left.item) : undefined;
|
|
621
|
+
const rightClassification = isRecord(right.item) ? classifyNetworkRequestFailure(right.item) : undefined;
|
|
622
|
+
const leftRank = leftClassification?.impact === "actionable" ? 0 : 1;
|
|
623
|
+
const rightRank = rightClassification?.impact === "actionable" ? 0 : 1;
|
|
624
|
+
return leftRank - rightRank || left.index - right.index;
|
|
625
|
+
});
|
|
626
|
+
const prioritizedRequests = [...failedRequests, ...normalRequests];
|
|
627
|
+
shown.push(...prioritizedRequests.slice(0, DIAGNOSTIC_REQUEST_PREVIEW_LIMIT).flatMap(({ item, index }) => {
|
|
613
628
|
if (!isRecord(item)) return [`${index + 1}. ${stringifyModelFacing(item)}`];
|
|
614
629
|
return formatNetworkRequestLine(item, index);
|
|
615
630
|
}));
|
|
616
631
|
if (requests.length > DIAGNOSTIC_REQUEST_PREVIEW_LIMIT) {
|
|
617
|
-
shown.push(`... (${requests.length - DIAGNOSTIC_REQUEST_PREVIEW_LIMIT} additional requests omitted from preview)`);
|
|
632
|
+
shown.push(`... (${requests.length - DIAGNOSTIC_REQUEST_PREVIEW_LIMIT} additional requests omitted from preview; failed requests are shown first when present)`);
|
|
618
633
|
}
|
|
619
634
|
return shown.join("\n");
|
|
620
635
|
}
|
|
@@ -123,9 +123,9 @@ const GLOBAL_BOOLEAN_FLAGS_WITH_OPTIONAL_VALUES = new Set([
|
|
|
123
123
|
"-v",
|
|
124
124
|
]);
|
|
125
125
|
const SENSITIVE_QUERY_PARAM_PATTERN =
|
|
126
|
-
/^(?:access(?:_|-)?token|api(?:_|-)?key|auth|authorization|bearer|client(?:_|-)?secret|code|cookie|id(?:_|-)?token|key|pass(?:word)?|refresh(?:_|-)?token|secret|session(?:_|-)?id|sig(?:nature)?|token)$/i;
|
|
126
|
+
/^(?:access(?:_|-)?token|api(?:_|-)?key|auth|authorization|bearer|client(?:_|-)?secret|code|cookie|id(?:_|-)?token|key|pass(?:word)?|refresh(?:_|-)?token|secret|sentry(?:_|-)?key|session(?:_|-)?id|sig(?:nature)?|token|write(?:_|-)?key)$/i;
|
|
127
127
|
const SENSITIVE_FIELD_NAME_PATTERN =
|
|
128
|
-
/^(?:access(?:_|-)?token|api(?:_|-)?key|auth(?:orization)?|bearer|client(?:_|-)?secret|cookie|id(?:_|-)?token|pass(?:word)?|proxy(?:_|-)?authorization|refresh(?:_|-)?token|secret|session(?:_|-)?id|set(?:_|-)?cookie|sig(?:nature)?|token|x(?:_|-)?api(?:_|-)?key)$/i;
|
|
128
|
+
/^(?:access(?:_|-)?token|api(?:_|-)?key|auth(?:orization)?|bearer|client(?:_|-)?secret|cookie|id(?:_|-)?token|pass(?:word)?|proxy(?:_|-)?authorization|refresh(?:_|-)?token|secret|sentry(?:_|-)?key|session(?:_|-)?id|set(?:_|-)?cookie|sig(?:nature)?|token|write(?:_|-)?key|x(?:_|-)?api(?:_|-)?key)$/i;
|
|
129
129
|
|
|
130
130
|
const VALUE_FLAGS = new Set([
|
|
131
131
|
"--session",
|
package/package.json
CHANGED