pi-agent-browser-native 0.2.48 → 0.2.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +16 -6
  3. package/dist/extensions/agent-browser/index.js +785 -0
  4. package/dist/extensions/agent-browser/lib/argv-descriptor.js +71 -0
  5. package/dist/extensions/agent-browser/lib/argv-grammar.js +121 -0
  6. package/dist/extensions/agent-browser/lib/bash-guard.js +190 -0
  7. package/dist/extensions/agent-browser/lib/command-policy.js +85 -0
  8. package/dist/extensions/agent-browser/lib/command-taxonomy.js +302 -0
  9. package/dist/extensions/agent-browser/lib/config-policy.js +686 -0
  10. package/dist/extensions/agent-browser/lib/config.js +122 -0
  11. package/dist/extensions/agent-browser/lib/electron/cdp.js +51 -0
  12. package/dist/extensions/agent-browser/lib/electron/cleanup.js +212 -0
  13. package/dist/extensions/agent-browser/lib/electron/discovery.js +633 -0
  14. package/dist/extensions/agent-browser/lib/electron/launch.js +351 -0
  15. package/{extensions/agent-browser/lib/electron/text.ts → dist/extensions/agent-browser/lib/electron/text.js} +5 -5
  16. package/dist/extensions/agent-browser/lib/executable-path.js +20 -0
  17. package/dist/extensions/agent-browser/lib/fs-utils.js +18 -0
  18. package/dist/extensions/agent-browser/lib/input-modes/electron.js +165 -0
  19. package/dist/extensions/agent-browser/lib/input-modes/job.js +519 -0
  20. package/dist/extensions/agent-browser/lib/input-modes/lookups.js +440 -0
  21. package/dist/extensions/agent-browser/lib/input-modes/params.js +164 -0
  22. package/dist/extensions/agent-browser/lib/input-modes/semantic-action.js +119 -0
  23. package/dist/extensions/agent-browser/lib/input-modes/shared.js +42 -0
  24. package/dist/extensions/agent-browser/lib/input-modes/types.js +21 -0
  25. package/dist/extensions/agent-browser/lib/input-modes.js +10 -0
  26. package/dist/extensions/agent-browser/lib/json-schema.js +58 -0
  27. package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +59 -0
  28. package/dist/extensions/agent-browser/lib/navigation-policy.js +83 -0
  29. package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +62 -0
  30. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +39 -0
  31. package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +276 -0
  32. package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +909 -0
  33. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +443 -0
  34. package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +47 -0
  35. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/direct-anchor-download.js +141 -0
  36. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.js +108 -0
  37. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.js +112 -0
  38. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +158 -0
  39. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.js +54 -0
  40. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +762 -0
  41. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +491 -0
  42. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prompt-guards.js +40 -0
  43. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-artifacts.js +5 -0
  44. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +731 -0
  45. package/dist/extensions/agent-browser/lib/orchestration/browser-run/types.js +1 -0
  46. package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +718 -0
  47. package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +247 -0
  48. package/dist/extensions/agent-browser/lib/orchestration/output-file.js +68 -0
  49. package/{extensions/agent-browser/lib/parsing.ts → dist/extensions/agent-browser/lib/parsing.js} +12 -11
  50. package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +241 -0
  51. package/dist/extensions/agent-browser/lib/playbook.js +121 -0
  52. package/dist/extensions/agent-browser/lib/process.js +448 -0
  53. package/dist/extensions/agent-browser/lib/prompt-policy.js +91 -0
  54. package/dist/extensions/agent-browser/lib/results/action-recommendations.js +220 -0
  55. package/dist/extensions/agent-browser/lib/results/artifact-manifest.js +111 -0
  56. package/{extensions/agent-browser/lib/results/artifact-state.ts → dist/extensions/agent-browser/lib/results/artifact-state.js} +4 -8
  57. package/dist/extensions/agent-browser/lib/results/categories.js +76 -0
  58. package/dist/extensions/agent-browser/lib/results/confirmation.js +63 -0
  59. package/dist/extensions/agent-browser/lib/results/contracts.js +8 -0
  60. package/dist/extensions/agent-browser/lib/results/editable-ref-evidence.js +74 -0
  61. package/dist/extensions/agent-browser/lib/results/envelope.js +166 -0
  62. package/dist/extensions/agent-browser/lib/results/network-routes.js +92 -0
  63. package/dist/extensions/agent-browser/lib/results/network.js +73 -0
  64. package/dist/extensions/agent-browser/lib/results/next-actions.js +72 -0
  65. package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +515 -0
  66. package/dist/extensions/agent-browser/lib/results/presentation/batch.js +397 -0
  67. package/dist/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.js +55 -0
  68. package/dist/extensions/agent-browser/lib/results/presentation/common.js +46 -0
  69. package/dist/extensions/agent-browser/lib/results/presentation/content.js +24 -0
  70. package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +960 -0
  71. package/dist/extensions/agent-browser/lib/results/presentation/errors.js +205 -0
  72. package/dist/extensions/agent-browser/lib/results/presentation/large-output.js +134 -0
  73. package/dist/extensions/agent-browser/lib/results/presentation/navigation.js +159 -0
  74. package/dist/extensions/agent-browser/lib/results/presentation/registry.js +216 -0
  75. package/dist/extensions/agent-browser/lib/results/presentation/semantic-action.js +104 -0
  76. package/dist/extensions/agent-browser/lib/results/presentation/skills.js +152 -0
  77. package/dist/extensions/agent-browser/lib/results/presentation.js +177 -0
  78. package/dist/extensions/agent-browser/lib/results/recovery-actions.js +107 -0
  79. package/dist/extensions/agent-browser/lib/results/recovery-next-actions.js +50 -0
  80. package/dist/extensions/agent-browser/lib/results/selector-recovery.js +225 -0
  81. package/{extensions/agent-browser/lib/results/shared.ts → dist/extensions/agent-browser/lib/results/shared.js} +0 -1
  82. package/dist/extensions/agent-browser/lib/results/snapshot-high-value-controls.js +208 -0
  83. package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +78 -0
  84. package/dist/extensions/agent-browser/lib/results/snapshot-segments.js +331 -0
  85. package/dist/extensions/agent-browser/lib/results/snapshot-spill.js +40 -0
  86. package/dist/extensions/agent-browser/lib/results/snapshot.js +264 -0
  87. package/dist/extensions/agent-browser/lib/results/text.js +40 -0
  88. package/{extensions/agent-browser/lib/results.ts → dist/extensions/agent-browser/lib/results.js} +2 -32
  89. package/dist/extensions/agent-browser/lib/runtime.js +816 -0
  90. package/dist/extensions/agent-browser/lib/session-page-state.js +411 -0
  91. package/dist/extensions/agent-browser/lib/string-enum-schema.js +13 -0
  92. package/dist/extensions/agent-browser/lib/temp.js +498 -0
  93. package/dist/extensions/agent-browser/lib/web-search.js +562 -0
  94. package/docs/RELEASE.md +22 -11
  95. package/docs/SUPPORT_MATRIX.md +4 -3
  96. package/package.json +9 -5
  97. package/scripts/config.mjs +8 -2
  98. package/scripts/doctor.mjs +8 -7
  99. package/extensions/agent-browser/index.ts +0 -961
  100. package/extensions/agent-browser/lib/argv-descriptor.ts +0 -90
  101. package/extensions/agent-browser/lib/argv-grammar.ts +0 -128
  102. package/extensions/agent-browser/lib/bash-guard.ts +0 -205
  103. package/extensions/agent-browser/lib/command-policy.ts +0 -71
  104. package/extensions/agent-browser/lib/command-taxonomy.ts +0 -336
  105. package/extensions/agent-browser/lib/config-policy.js +0 -690
  106. package/extensions/agent-browser/lib/config.ts +0 -211
  107. package/extensions/agent-browser/lib/electron/cdp.ts +0 -69
  108. package/extensions/agent-browser/lib/electron/cleanup.ts +0 -235
  109. package/extensions/agent-browser/lib/electron/discovery.ts +0 -710
  110. package/extensions/agent-browser/lib/electron/launch.ts +0 -499
  111. package/extensions/agent-browser/lib/executable-path.ts +0 -19
  112. package/extensions/agent-browser/lib/fs-utils.ts +0 -18
  113. package/extensions/agent-browser/lib/input-modes/electron.ts +0 -170
  114. package/extensions/agent-browser/lib/input-modes/job.ts +0 -527
  115. package/extensions/agent-browser/lib/input-modes/lookups.ts +0 -447
  116. package/extensions/agent-browser/lib/input-modes/params.ts +0 -205
  117. package/extensions/agent-browser/lib/input-modes/semantic-action.ts +0 -127
  118. package/extensions/agent-browser/lib/input-modes/shared.ts +0 -46
  119. package/extensions/agent-browser/lib/input-modes/types.ts +0 -225
  120. package/extensions/agent-browser/lib/input-modes.ts +0 -45
  121. package/extensions/agent-browser/lib/json-schema.ts +0 -73
  122. package/extensions/agent-browser/lib/launch-scoped-flags.ts +0 -67
  123. package/extensions/agent-browser/lib/navigation-policy.ts +0 -95
  124. package/extensions/agent-browser/lib/orchestration/batch-stdin.ts +0 -65
  125. package/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.ts +0 -44
  126. package/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.ts +0 -280
  127. package/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.ts +0 -914
  128. package/extensions/agent-browser/lib/orchestration/browser-run/final-result.ts +0 -521
  129. package/extensions/agent-browser/lib/orchestration/browser-run/index.ts +0 -53
  130. package/extensions/agent-browser/lib/orchestration/browser-run/prepare/direct-anchor-download.ts +0 -158
  131. package/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.ts +0 -116
  132. package/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.ts +0 -147
  133. package/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.ts +0 -183
  134. package/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.ts +0 -58
  135. package/extensions/agent-browser/lib/orchestration/browser-run/prepare.ts +0 -847
  136. package/extensions/agent-browser/lib/orchestration/browser-run/process-output.ts +0 -559
  137. package/extensions/agent-browser/lib/orchestration/browser-run/prompt-guards.ts +0 -47
  138. package/extensions/agent-browser/lib/orchestration/browser-run/session-artifacts.ts +0 -8
  139. package/extensions/agent-browser/lib/orchestration/browser-run/session-state.ts +0 -868
  140. package/extensions/agent-browser/lib/orchestration/browser-run/types.ts +0 -565
  141. package/extensions/agent-browser/lib/orchestration/electron-host/index.ts +0 -855
  142. package/extensions/agent-browser/lib/orchestration/input-plan.ts +0 -375
  143. package/extensions/agent-browser/lib/orchestration/output-file.ts +0 -86
  144. package/extensions/agent-browser/lib/pi-tool-rendering.ts +0 -267
  145. package/extensions/agent-browser/lib/playbook.ts +0 -142
  146. package/extensions/agent-browser/lib/process.ts +0 -516
  147. package/extensions/agent-browser/lib/prompt-policy.ts +0 -105
  148. package/extensions/agent-browser/lib/results/action-recommendations.ts +0 -264
  149. package/extensions/agent-browser/lib/results/artifact-manifest.ts +0 -111
  150. package/extensions/agent-browser/lib/results/categories.ts +0 -106
  151. package/extensions/agent-browser/lib/results/confirmation.ts +0 -76
  152. package/extensions/agent-browser/lib/results/contracts.ts +0 -241
  153. package/extensions/agent-browser/lib/results/editable-ref-evidence.ts +0 -72
  154. package/extensions/agent-browser/lib/results/envelope.ts +0 -195
  155. package/extensions/agent-browser/lib/results/network-routes.ts +0 -83
  156. package/extensions/agent-browser/lib/results/network.ts +0 -78
  157. package/extensions/agent-browser/lib/results/next-actions.ts +0 -117
  158. package/extensions/agent-browser/lib/results/presentation/artifacts.ts +0 -588
  159. package/extensions/agent-browser/lib/results/presentation/batch.ts +0 -450
  160. package/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.ts +0 -67
  161. package/extensions/agent-browser/lib/results/presentation/common.ts +0 -53
  162. package/extensions/agent-browser/lib/results/presentation/content.ts +0 -36
  163. package/extensions/agent-browser/lib/results/presentation/diagnostics.ts +0 -923
  164. package/extensions/agent-browser/lib/results/presentation/errors.ts +0 -227
  165. package/extensions/agent-browser/lib/results/presentation/large-output.ts +0 -182
  166. package/extensions/agent-browser/lib/results/presentation/navigation.ts +0 -184
  167. package/extensions/agent-browser/lib/results/presentation/registry.ts +0 -242
  168. package/extensions/agent-browser/lib/results/presentation/semantic-action.ts +0 -131
  169. package/extensions/agent-browser/lib/results/presentation/skills.ts +0 -143
  170. package/extensions/agent-browser/lib/results/presentation.ts +0 -257
  171. package/extensions/agent-browser/lib/results/recovery-actions.ts +0 -139
  172. package/extensions/agent-browser/lib/results/recovery-next-actions.ts +0 -71
  173. package/extensions/agent-browser/lib/results/selector-recovery.ts +0 -320
  174. package/extensions/agent-browser/lib/results/snapshot-high-value-controls.ts +0 -273
  175. package/extensions/agent-browser/lib/results/snapshot-refs.ts +0 -100
  176. package/extensions/agent-browser/lib/results/snapshot-segments.ts +0 -366
  177. package/extensions/agent-browser/lib/results/snapshot-spill.ts +0 -63
  178. package/extensions/agent-browser/lib/results/snapshot.ts +0 -329
  179. package/extensions/agent-browser/lib/results/text.ts +0 -40
  180. package/extensions/agent-browser/lib/runtime.ts +0 -988
  181. package/extensions/agent-browser/lib/session-page-state.ts +0 -512
  182. package/extensions/agent-browser/lib/string-enum-schema.ts +0 -20
  183. package/extensions/agent-browser/lib/temp.ts +0 -577
  184. package/extensions/agent-browser/lib/web-search.ts +0 -728
  185. /package/{extensions/agent-browser/lib/orchestration/browser-run.ts → dist/extensions/agent-browser/lib/orchestration/browser-run.js} +0 -0
@@ -1,450 +0,0 @@
1
- import { isRecord } from "../../parsing.js";
2
- import { extractCommandTokens, parseCommandInfo, redactInvocationArgs, redactSensitiveText, redactSensitiveValue, type CommandInfo } from "../../runtime.js";
3
- import type { PersistentSessionArtifactStore } from "../../temp.js";
4
- import { buildAgentBrowserNextActions } from "../action-recommendations.js";
5
- import { formatSessionArtifactRetentionSummary } from "../artifact-manifest.js";
6
- import { classifyAgentBrowserFailureCategory } from "../categories.js";
7
- import { detectConfirmationRequired } from "../confirmation.js";
8
- import type {
9
- AgentBrowserBatchResult,
10
- AgentBrowserEnvelope,
11
- AgentBrowserNextAction,
12
- BatchFailurePresentationDetails,
13
- BatchStepPresentationDetails,
14
- NetworkRouteDiagnostic,
15
- NetworkRouteRecord,
16
- SessionArtifactManifest,
17
- ToolPresentation,
18
- } from "../contracts.js";
19
- import { applyNetworkRouteRecords, buildNetworkRouteDiagnostics } from "../network-routes.js";
20
- import { withOptionalSessionArgs } from "../next-actions.js";
21
- import { stringifyModelFacing } from "./common.js";
22
- import { buildArtifactVerificationSummary, classifyPresentationSuccessCategory, manifestHasNewNoticeWorthyEntries, type ArtifactRequestContext } from "./artifacts.js";
23
- import { formatBatchStepCommand, getPresentationImages, getPresentationPaths, getPresentationText, isStringArray } from "./content.js";
24
- import { buildPageChangeSummary } from "./navigation.js";
25
- import { appendSelectorRecoveryHint, getClipboardWritePayloadCandidates, redactClipboardPermissionErrorValue } from "./errors.js";
26
-
27
- export interface BuildNestedToolPresentationOptions {
28
- artifactManifest?: SessionArtifactManifest;
29
- artifactRequest?: ArtifactRequestContext;
30
- args?: string[];
31
- commandInfo: CommandInfo;
32
- cwd: string;
33
- envelope?: AgentBrowserEnvelope;
34
- networkRouteDiagnostics?: NetworkRouteDiagnostic[];
35
- persistentArtifactStore?: PersistentSessionArtifactStore;
36
- sessionName?: string;
37
- }
38
-
39
- type BuildNestedToolPresentation = (options: BuildNestedToolPresentationOptions) => Promise<ToolPresentation>;
40
-
41
- export function isAgentBrowserBatchResultArray(value: unknown): value is AgentBrowserBatchResult[] {
42
- return Array.isArray(value) && value.every(isRecord);
43
- }
44
-
45
- function isWaitTextAssertionCommand(command: string[] | undefined): boolean {
46
- return command?.[0] === "wait" && command.includes("--text");
47
- }
48
-
49
- function buildWaitTextAssertionFailureNextAction(sessionName: string | undefined): AgentBrowserNextAction {
50
- return {
51
- id: "inspect-after-text-assertion-failure",
52
- params: { args: withOptionalSessionArgs(sessionName, ["snapshot", "-i"]) },
53
- reason: "Inspect the current page after the text assertion failed before concluding the expected text is absent.",
54
- safety: "Read-only snapshot; use current refs or visible text from this page before retrying the assertion.",
55
- tool: "agent_browser",
56
- };
57
- }
58
-
59
- function mergePresentationNextActions(...groups: Array<AgentBrowserNextAction[] | undefined>): AgentBrowserNextAction[] | undefined {
60
- const actions: AgentBrowserNextAction[] = [];
61
- const seen = new Set<string>();
62
- for (const group of groups) {
63
- for (const action of group ?? []) {
64
- if (seen.has(action.id)) continue;
65
- actions.push(action);
66
- seen.add(action.id);
67
- }
68
- }
69
- return actions.length > 0 ? actions : undefined;
70
- }
71
-
72
- function formatBatchStepError(error: unknown): string {
73
- const errorText = stringifyModelFacing(error).trim();
74
- const formattedErrorText = errorText.length > 0 ? `Error: ${errorText}` : "Error: batch step failed.";
75
- return appendSelectorRecoveryHint(formattedErrorText);
76
- }
77
-
78
- function getBatchFailureDetails(steps: Array<{ details: BatchStepPresentationDetails }>): BatchFailurePresentationDetails | undefined {
79
- const failedSteps = steps.filter((step) => step.details.success === false);
80
- if (failedSteps.length === 0) return undefined;
81
- const successCount = steps.length - failedSteps.length;
82
- return {
83
- failedStep: failedSteps[0].details,
84
- failureCount: failedSteps.length,
85
- successCount,
86
- totalCount: steps.length,
87
- };
88
- }
89
-
90
- function hasModelFacingArgRedaction(args: string[] | undefined): boolean {
91
- return args?.some((arg) => arg === "[REDACTED]" || arg.includes("%5BREDACTED%5D") || arg.includes("[REDACTED]")) === true;
92
- }
93
-
94
- function getStatefulCommandSensitiveValues(command: string[] | undefined): string[] {
95
- if (!command) return [];
96
- const tokens = extractCommandTokens(command);
97
- const values: string[] = [];
98
- if (tokens[0] === "cookies" && tokens[1] === "set" && tokens[3]) values.push(tokens[3]);
99
- if (tokens[0] === "storage" && ["local", "session"].includes(tokens[1] ?? "") && tokens[2] === "set" && tokens[4]) values.push(tokens[4]);
100
- for (let index = 0; index < tokens.length; index += 1) {
101
- const token = tokens[index];
102
- if (token === "--password" && tokens[index + 1]) values.push(tokens[index + 1]);
103
- else if (token?.startsWith("--password=")) values.push(token.slice("--password=".length));
104
- }
105
- return values.filter((value) => value.length > 0);
106
- }
107
-
108
- function redactExactValues(value: unknown, sensitiveValues: string[]): unknown {
109
- if (sensitiveValues.length === 0) return redactSensitiveValue(value);
110
- if (typeof value === "string") {
111
- let redacted = value;
112
- for (const sensitiveValue of sensitiveValues) redacted = redacted.split(sensitiveValue).join("[REDACTED]");
113
- return redactSensitiveText(redacted);
114
- }
115
- if (Array.isArray(value)) return value.map((item) => redactExactValues(item, sensitiveValues));
116
- if (!isRecord(value)) return value;
117
- return redactSensitiveValue(Object.fromEntries(Object.entries(value).map(([key, entryValue]) => [key, redactExactValues(entryValue, sensitiveValues)])));
118
- }
119
-
120
- function getTypedTextLength(command: string[] | undefined): number | undefined {
121
- return command?.[0] === "keyboard" && command[1] === "type" && typeof command[2] === "string"
122
- ? Array.from(command[2]).length
123
- : undefined;
124
- }
125
-
126
- function getWaitDelayMs(command: string[] | undefined): string | undefined {
127
- return command?.[0] === "wait" && typeof command[1] === "string" && /^\d+$/.test(command[1]) ? command[1] : undefined;
128
- }
129
-
130
- function formatBatchStepDetails(details: BatchStepPresentationDetails, presentation: ToolPresentation): string {
131
- const inlineImageCount = getPresentationImages(presentation).length;
132
- const status = details.success ? "succeeded" : "failed";
133
- const lines = [`Step ${details.index + 1} — ${details.commandText} (${status})`];
134
- if (details.text.length > 0) lines.push(details.text);
135
- if (inlineImageCount > 0) lines.push(`(${inlineImageCount} inline image attachment${inlineImageCount === 1 ? "" : "s"} below)`);
136
- return lines.join("\n");
137
- }
138
-
139
- function formatTypedSequenceSummary(steps: Array<{ details: BatchStepPresentationDetails; presentation: ToolPresentation }>, startIndex: number): { nextIndex: number; text: string } | undefined {
140
- let index = startIndex;
141
- const firstDetails = steps[index]?.details;
142
- if (!firstDetails?.success) return undefined;
143
- let target: string | undefined;
144
- if (firstDetails.command?.[0] === "focus" && typeof firstDetails.command[1] === "string") {
145
- target = firstDetails.command[1];
146
- index += 1;
147
- }
148
- let typedCharCount = 0;
149
- let typedStepCount = 0;
150
- let delayMs: string | undefined;
151
- while (index < steps.length) {
152
- const details = steps[index]?.details;
153
- if (!details?.success) break;
154
- const typedLength = getTypedTextLength(details.command);
155
- if (typedLength === undefined) break;
156
- typedCharCount += typedLength;
157
- typedStepCount += 1;
158
- index += 1;
159
- const nextDelay = getWaitDelayMs(steps[index]?.details.command);
160
- const followingTypedLength = getTypedTextLength(steps[index + 1]?.details.command);
161
- if (nextDelay !== undefined && followingTypedLength !== undefined && steps[index]?.details.success && steps[index + 1]?.details.success) {
162
- if (delayMs !== undefined && delayMs !== nextDelay) return undefined;
163
- delayMs = nextDelay;
164
- index += 1;
165
- }
166
- }
167
- if (typedStepCount < 2) return undefined;
168
- let pressedKey: string | undefined;
169
- const pressDetails = steps[index]?.details;
170
- if (pressDetails?.success && pressDetails.command?.[0] === "press" && typeof pressDetails.command[1] === "string") {
171
- pressedKey = pressDetails.command[1];
172
- index += 1;
173
- }
174
- const firstStep = firstDetails.index + 1;
175
- const lastStep = steps[index - 1]?.details.index + 1;
176
- const stepRange = lastStep && lastStep > firstStep ? `${firstStep}-${lastStep}` : String(firstStep);
177
- const commandLabel = target ? `type ${target}` : "keyboard type";
178
- const lines = [
179
- `Step ${stepRange} — ${commandLabel} (succeeded)`,
180
- `Typed ${typedCharCount} char${typedCharCount === 1 ? "" : "s"}${delayMs ? ` with delayMs=${delayMs}` : ""}.`,
181
- ];
182
- if (pressedKey) lines.push(`Pressed ${pressedKey}.`);
183
- return { nextIndex: index, text: lines.join("\n") };
184
- }
185
-
186
- function formatBatchStepsText(steps: Array<{ details: BatchStepPresentationDetails; presentation: ToolPresentation }>): string {
187
- if (steps.length === 0) return "(no batch steps)";
188
- const lines: string[] = [];
189
- for (let index = 0; index < steps.length;) {
190
- const typedSequence = formatTypedSequenceSummary(steps, index);
191
- if (typedSequence) {
192
- lines.push(typedSequence.text);
193
- index = typedSequence.nextIndex;
194
- continue;
195
- }
196
- const step = steps[index];
197
- if (step) lines.push(formatBatchStepDetails(step.details, step.presentation));
198
- index += 1;
199
- }
200
- return lines.join("\n\n");
201
- }
202
-
203
- async function buildBatchStepPresentation(options: {
204
- artifactManifest?: SessionArtifactManifest;
205
- artifactRequest?: ArtifactRequestContext;
206
- buildNestedToolPresentation: BuildNestedToolPresentation;
207
- cwd: string;
208
- index: number;
209
- item: AgentBrowserBatchResult;
210
- networkRoutes?: NetworkRouteRecord[];
211
- persistentArtifactStore?: PersistentSessionArtifactStore;
212
- sessionName?: string;
213
- }): Promise<{ details: BatchStepPresentationDetails; presentation: ToolPresentation }> {
214
- const { artifactManifest, artifactRequest, buildNestedToolPresentation, cwd, index, item, networkRoutes, persistentArtifactStore, sessionName } = options;
215
- const command = isStringArray(item.command) ? item.command : undefined;
216
- const redactedCommand = command ? redactInvocationArgs(command) : undefined;
217
- const commandText = formatBatchStepCommand(hasModelFacingArgRedaction(redactedCommand) ? redactedCommand : command, index);
218
-
219
- if (item.success === false) {
220
- const redactedErrorData = command?.[0] === "clipboard"
221
- ? redactSensitiveValue(redactClipboardPermissionErrorValue({ command: "clipboard", subcommand: command[1] }, item.error, getClipboardWritePayloadCandidates(command)))
222
- : redactExactValues(item.error, getStatefulCommandSensitiveValues(command));
223
- const errorText = formatBatchStepError(redactedErrorData);
224
- const failureCategory = classifyAgentBrowserFailureCategory({
225
- args: command,
226
- command: command?.[0],
227
- errorText,
228
- });
229
- const confirmationRequired = detectConfirmationRequired(item.error);
230
- const nextActions = mergePresentationNextActions(
231
- buildAgentBrowserNextActions({
232
- args: command,
233
- command: command?.[0],
234
- confirmationId: confirmationRequired?.id,
235
- failureCategory,
236
- resultCategory: "failure",
237
- }),
238
- isWaitTextAssertionCommand(command) ? [buildWaitTextAssertionFailureNextAction(sessionName)] : undefined,
239
- );
240
- const presentation: ToolPresentation = {
241
- content: [{ type: "text", text: errorText }],
242
- failureCategory,
243
- nextActions,
244
- resultCategory: "failure",
245
- summary: errorText,
246
- };
247
- return {
248
- details: {
249
- artifactVerification: presentation.artifactVerification,
250
- artifacts: presentation.artifacts,
251
- command: redactedCommand,
252
- commandText,
253
- data: redactedErrorData,
254
- failureCategory,
255
- index,
256
- nextActions,
257
- resultCategory: "failure",
258
- success: false,
259
- summary: errorText,
260
- text: errorText,
261
- },
262
- presentation,
263
- };
264
- }
265
-
266
- const commandInfo = parseCommandInfo(command ?? []);
267
- const networkRouteDiagnostics = commandInfo.command === "network" && commandInfo.subcommand === "requests"
268
- ? buildNetworkRouteDiagnostics(item.result, networkRoutes)
269
- : undefined;
270
- const presentation = await buildNestedToolPresentation({
271
- artifactManifest,
272
- artifactRequest,
273
- commandInfo,
274
- cwd,
275
- args: command,
276
- envelope: { data: item.result, success: true },
277
- networkRouteDiagnostics,
278
- persistentArtifactStore,
279
- sessionName,
280
- });
281
- const fullOutputPaths = getPresentationPaths({
282
- primaryPath: presentation.fullOutputPath,
283
- secondaryPaths: presentation.fullOutputPaths,
284
- });
285
- const imagePaths = getPresentationPaths({
286
- primaryPath: presentation.imagePath,
287
- secondaryPaths: presentation.imagePaths,
288
- });
289
- const text = getPresentationText(presentation) || presentation.summary;
290
- const stepSucceeded = presentation.resultCategory !== "failure";
291
- const nextActions = presentation.nextActions ?? buildAgentBrowserNextActions({
292
- artifacts: presentation.artifacts,
293
- args: command,
294
- command: command?.[0],
295
- failureCategory: presentation.failureCategory,
296
- resultCategory: stepSucceeded ? "success" : "failure",
297
- savedFilePath: presentation.savedFilePath,
298
- successCategory: presentation.successCategory,
299
- });
300
- const pageChangeSummary = buildPageChangeSummary({
301
- artifacts: presentation.artifacts,
302
- commandInfo,
303
- data: presentation.data,
304
- nextActions,
305
- savedFilePath: presentation.savedFilePath,
306
- summary: presentation.summary,
307
- });
308
-
309
- return {
310
- details: {
311
- artifactVerification: presentation.artifactVerification,
312
- artifacts: presentation.artifacts,
313
- command: redactedCommand,
314
- commandText,
315
- data: presentation.data,
316
- failureCategory: stepSucceeded ? undefined : presentation.failureCategory,
317
- fullOutputPath: fullOutputPaths[0],
318
- fullOutputPaths: fullOutputPaths.length > 0 ? fullOutputPaths : undefined,
319
- imagePath: imagePaths[0],
320
- imagePaths: imagePaths.length > 0 ? imagePaths : undefined,
321
- index,
322
- networkRouteDiagnostics: presentation.networkRouteDiagnostics,
323
- nextActions,
324
- pageChangeSummary,
325
- resultCategory: stepSucceeded ? "success" : "failure",
326
- savedFile: presentation.savedFile,
327
- savedFilePath: presentation.savedFilePath,
328
- success: stepSucceeded,
329
- successCategory: stepSucceeded ? classifyPresentationSuccessCategory({ artifactVerification: presentation.artifactVerification, artifacts: presentation.artifacts, savedFile: presentation.savedFile }) : undefined,
330
- summary: presentation.summary,
331
- text,
332
- },
333
- presentation,
334
- };
335
- }
336
-
337
- export async function buildBatchPresentation(options: {
338
- artifactManifest?: SessionArtifactManifest;
339
- artifactRequests?: Array<ArtifactRequestContext | undefined>;
340
- buildNestedToolPresentation: BuildNestedToolPresentation;
341
- cwd: string;
342
- data: AgentBrowserBatchResult[];
343
- networkRoutes?: NetworkRouteRecord[];
344
- persistentArtifactStore?: PersistentSessionArtifactStore;
345
- sessionName?: string;
346
- summary: string;
347
- }): Promise<ToolPresentation> {
348
- const { artifactRequests, buildNestedToolPresentation, cwd, data, networkRoutes, persistentArtifactStore, sessionName, summary } = options;
349
- const steps: Array<{ details: BatchStepPresentationDetails; presentation: ToolPresentation }> = [];
350
- const protectedPersistentPaths: string[] = [];
351
- let currentArtifactManifest = options.artifactManifest;
352
- let currentNetworkRoutes = networkRoutes;
353
- for (const [index, item] of data.entries()) {
354
- const step = await buildBatchStepPresentation({
355
- artifactManifest: currentArtifactManifest,
356
- artifactRequest: artifactRequests?.[index],
357
- buildNestedToolPresentation,
358
- cwd,
359
- index,
360
- item,
361
- networkRoutes: currentNetworkRoutes,
362
- persistentArtifactStore: persistentArtifactStore ? { ...persistentArtifactStore, protectedPaths: protectedPersistentPaths } : undefined,
363
- sessionName,
364
- });
365
- steps.push(step);
366
- currentArtifactManifest = step.presentation.artifactManifest ?? currentArtifactManifest;
367
- currentNetworkRoutes = applyNetworkRouteRecords(currentNetworkRoutes, isStringArray(item.command) ? extractCommandTokens(item.command) : undefined, item.success !== false && step.details.success);
368
- protectedPersistentPaths.push(
369
- ...getPresentationPaths({
370
- primaryPath: step.presentation.fullOutputPath,
371
- secondaryPaths: step.presentation.fullOutputPaths,
372
- }),
373
- );
374
- }
375
-
376
- const batchFailure = getBatchFailureDetails(steps);
377
- const images = steps.flatMap((step) => getPresentationImages(step.presentation));
378
- const artifacts = steps.flatMap((step) => step.presentation.artifacts ?? []);
379
- const artifactVerification = buildArtifactVerificationSummary(artifacts);
380
- const fullOutputPaths = steps.flatMap((step) => getPresentationPaths({
381
- primaryPath: step.presentation.fullOutputPath,
382
- secondaryPaths: step.presentation.fullOutputPaths,
383
- }));
384
- const imagePaths = steps.flatMap((step) => getPresentationPaths({
385
- primaryPath: step.presentation.imagePath,
386
- secondaryPaths: step.presentation.imagePaths,
387
- }));
388
- const redactedBatchData = steps.map(({ details }) => (
389
- details.success
390
- ? { command: details.command, result: details.data, success: true }
391
- : { command: details.command, error: details.text, success: false }
392
- ));
393
- const stepText = formatBatchStepsText(steps);
394
- const batchSummary = batchFailure === undefined
395
- ? summary
396
- : `Batch failed: ${batchFailure.successCount}/${batchFailure.totalCount} succeeded`;
397
- const failureHeader = batchFailure === undefined
398
- ? undefined
399
- : [
400
- batchSummary,
401
- `First failing step: ${batchFailure.failedStep.index + 1} — ${batchFailure.failedStep.commandText}`,
402
- batchFailure.failureCount > 1 ? `${batchFailure.failureCount} steps failed. See the per-step results below.` : "See the per-step results below.",
403
- ].join("\n");
404
- const text = failureHeader ? `${failureHeader}\n\n${stepText}` : stepText;
405
- const artifactRetentionSummary = currentArtifactManifest ? formatSessionArtifactRetentionSummary(currentArtifactManifest) : undefined;
406
- const contentText = artifactRetentionSummary && manifestHasNewNoticeWorthyEntries(options.artifactManifest, currentArtifactManifest)
407
- ? `${text}\n\n${artifactRetentionSummary}`
408
- : text;
409
- const nextActions = batchFailure
410
- ? batchFailure.failedStep.nextActions
411
- : buildAgentBrowserNextActions({ artifacts, command: "batch", resultCategory: "success" });
412
- const changedSteps = steps.map((step) => step.details).filter((details) => details.pageChangeSummary !== undefined);
413
- const pageChangeSummary = artifacts.length > 0
414
- ? buildPageChangeSummary({
415
- artifacts,
416
- commandInfo: { command: "batch" },
417
- data,
418
- nextActions,
419
- summary: batchSummary,
420
- })
421
- : changedSteps.length > 0
422
- ? {
423
- changeType: "mutation" as const,
424
- command: "batch",
425
- nextActionIds: nextActions?.map((action) => action.id),
426
- summary: `batch → mutation → ${changedSteps.length} changed step${changedSteps.length === 1 ? "" : "s"}`,
427
- }
428
- : undefined;
429
-
430
- return {
431
- artifactManifest: currentArtifactManifest,
432
- artifactRetentionSummary,
433
- artifactVerification,
434
- artifacts: artifacts.length > 0 ? artifacts : undefined,
435
- batchFailure,
436
- batchSteps: steps.map((step) => step.details),
437
- content: [{ type: "text", text: contentText }, ...images],
438
- failureCategory: batchFailure?.failedStep.failureCategory,
439
- data: redactedBatchData,
440
- fullOutputPath: fullOutputPaths[0],
441
- fullOutputPaths: fullOutputPaths.length > 0 ? fullOutputPaths : undefined,
442
- imagePath: imagePaths[0],
443
- imagePaths: imagePaths.length > 0 ? imagePaths : undefined,
444
- nextActions,
445
- pageChangeSummary,
446
- resultCategory: batchFailure ? "failure" : "success",
447
- successCategory: batchFailure ? undefined : classifyPresentationSuccessCategory({ artifactVerification, artifacts }),
448
- summary: batchSummary,
449
- };
450
- }
@@ -1,67 +0,0 @@
1
- /**
2
- * Purpose: Build browser profile/config recovery hints for launch/setup failures.
3
- * Responsibilities: Recognize local Chrome/profile setup errors, avoid self-loop diagnostics, and emit canonical next actions.
4
- * Scope: Error presentation only; upstream profile discovery and doctor execution remain normal agent_browser commands.
5
- */
6
-
7
- import { isOpenNavigationCommand } from "../../command-taxonomy.js";
8
- import { getStartupScopedFlags, type CommandInfo } from "../../runtime.js";
9
- import type { AgentBrowserNextAction } from "../contracts.js";
10
- import { buildNextToolAction } from "../next-actions.js";
11
-
12
- const BROWSER_PROFILE_CONFIG_HINT = [
13
- "Agent-browser profile/config hint: this looks like a local browser profile or Chrome user-data-dir setup problem, not a page-specific failure.",
14
- "Do not keep retrying the same open/profile call. Run `profiles` and/or `doctor` through agent_browser, then tell the user whether Chrome/Chromium is installed, which Chrome profile directory names are available, or whether they need to configure a full profile/user-data directory path, a non-default Chromium-compatible `--executable-path`, or remove the profile requirement for public-page browsing.",
15
- "Use the top-level `sessionMode: \"fresh\"` field for launch-scoped profile/debug/provider flags; do not pass `--session-mode` inside args.",
16
- ].join(" ");
17
-
18
- function looksLikeBrowserProfileConfigError(errorText: string): boolean {
19
- return /\b(?:No Chrome user data directory found|Cannot resolve profile name|Chrome user data directory|Chrome profile\s+.+?\s+not found|Available profiles|If you meant a directory path)\b/i.test(errorText);
20
- }
21
-
22
- function isLaunchOrSetupContext(args: string[] | undefined, commandInfo: CommandInfo): boolean {
23
- const command = commandInfo.command;
24
- if (command === "profiles" || command === "doctor") return true;
25
- if (command && isOpenNavigationCommand(command)) return true;
26
- return (args ? getStartupScopedFlags(args) : []).length > 0;
27
- }
28
-
29
- function buildBrowserProfileConfigActions(commandInfo: CommandInfo): AgentBrowserNextAction[] {
30
- const actions: AgentBrowserNextAction[] = [];
31
- if (commandInfo.command !== "profiles") {
32
- actions.push(buildNextToolAction({
33
- args: ["profiles"],
34
- id: "inspect-browser-profiles",
35
- reason: "List browser profiles/user-data-dir candidates before retrying profile-based launch.",
36
- safety: "Read-only local setup inspection; does not open a page or mutate browser state.",
37
- }));
38
- }
39
- if (commandInfo.command !== "doctor") {
40
- actions.push(buildNextToolAction({
41
- args: ["doctor"],
42
- id: "run-agent-browser-doctor",
43
- reason: "Inspect local agent-browser browser installation/configuration before retrying.",
44
- safety: "Read-only local diagnostics; report findings to the user before changing setup.",
45
- }));
46
- }
47
- return actions;
48
- }
49
-
50
- export interface BrowserProfileConfigRecovery {
51
- actions?: AgentBrowserNextAction[];
52
- hint: string;
53
- }
54
-
55
- export function buildBrowserProfileConfigRecovery(options: {
56
- args?: string[];
57
- commandInfo: CommandInfo;
58
- errorText: string;
59
- }): BrowserProfileConfigRecovery | undefined {
60
- if (!looksLikeBrowserProfileConfigError(options.errorText)) return undefined;
61
- if (!isLaunchOrSetupContext(options.args, options.commandInfo)) return undefined;
62
- const actions = buildBrowserProfileConfigActions(options.commandInfo);
63
- return {
64
- actions: actions.length > 0 ? actions : undefined,
65
- hint: BROWSER_PROFILE_CONFIG_HINT,
66
- };
67
- }
@@ -1,53 +0,0 @@
1
- /**
2
- * Purpose: Share small presentation formatting and redaction helpers across result presentation modules.
3
- * Responsibilities: Normalize scalar fields, stringify model-facing values, and apply sensitive-text redaction.
4
- * Scope: Leaf helpers only; command-family formatting lives in sibling modules.
5
- */
6
-
7
- import { redactSensitiveText, redactSensitiveValue } from "../../runtime.js";
8
- import { stringifyUnknown, truncateText } from "../text.js";
9
-
10
- export function stringifyModelFacing(value: unknown): string {
11
- return stringifyUnknown(redactSensitiveValue(value));
12
- }
13
-
14
- export function parseJsonPreviewString(value: string): unknown {
15
- const trimmed = value.trim();
16
- if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return value;
17
- try {
18
- return JSON.parse(trimmed) as unknown;
19
- } catch {
20
- return value;
21
- }
22
- }
23
-
24
- export function redactModelFacingText(text: string): string {
25
- const parsed = parseJsonPreviewString(text);
26
- if (parsed !== text) {
27
- return stringifyModelFacing(parsed);
28
- }
29
- return redactSensitiveText(text);
30
- }
31
-
32
- export function redactModelFacingTextIfSensitive(text: string): string {
33
- return /(?:@|\b(?:api[_-]?key|auth|authorization|basic|bearer|cookie|pass(?:word)?|secret|session[_-]?id|token)\b)/i.test(text)
34
- ? redactModelFacingText(text)
35
- : text;
36
- }
37
-
38
- export function getArrayField(data: Record<string, unknown>, key: string): unknown[] | undefined {
39
- return Array.isArray(data[key]) ? data[key] : undefined;
40
- }
41
-
42
- export function getStringField(data: Record<string, unknown>, key: string): string | undefined {
43
- const value = data[key];
44
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
45
- }
46
-
47
- export function formatCount(count: number, singular: string, plural = `${singular}s`): string {
48
- return `${count} ${count === 1 ? singular : plural}`;
49
- }
50
-
51
- export function firstLine(value: string, maxChars = 160): string {
52
- return truncateText(value.split("\n", 1)[0] ?? value, maxChars);
53
- }
@@ -1,36 +0,0 @@
1
- /**
2
- * Purpose: Share small ToolPresentation content helpers used by batch and compaction code.
3
- * Responsibilities: Extract text/image/path fields and format batch step command labels.
4
- * Scope: Pure ToolPresentation content helpers only.
5
- */
6
-
7
- import type { ToolPresentation } from "../contracts.js";
8
-
9
- export function isStringArray(value: unknown): value is string[] {
10
- return Array.isArray(value) && value.every((item) => typeof item === "string");
11
- }
12
-
13
- export function getPresentationText(presentation: ToolPresentation): string {
14
- return presentation.content
15
- .filter((part): part is Extract<ToolPresentation["content"][number], { type: "text" }> => part.type === "text")
16
- .map((part) => part.text.trim())
17
- .filter((text) => text.length > 0)
18
- .join("\n\n");
19
- }
20
-
21
- export function getPresentationImages(presentation: ToolPresentation): Array<Extract<ToolPresentation["content"][number], { type: "image" }>> {
22
- return presentation.content.filter(
23
- (part): part is Extract<ToolPresentation["content"][number], { type: "image" }> => part.type === "image",
24
- );
25
- }
26
-
27
- export function getPresentationPaths(options: {
28
- primaryPath?: string;
29
- secondaryPaths?: string[];
30
- }): string[] {
31
- return options.secondaryPaths ?? (options.primaryPath ? [options.primaryPath] : []);
32
- }
33
-
34
- export function formatBatchStepCommand(command: string[] | undefined, index: number): string {
35
- return command && command.length > 0 ? command.join(" ") : `step-${index + 1}`;
36
- }