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
@@ -0,0 +1,443 @@
1
+ import { cleanupElectronLaunchResources } from "../../electron/cleanup.js";
2
+ import { getCompiledSemanticActionCommandIndex, getCompiledSemanticActionSessionPrefix, isCompiledSemanticActionFindCommand, redactNetworkSourceLookupSurface, } from "../../input-modes.js";
3
+ import { buildAgentBrowserNextActions, buildAgentBrowserResultCategoryDetails, } from "../../results.js";
4
+ import { formatSessionArtifactRetentionSummary } from "../../results/artifact-manifest.js";
5
+ import { AgentBrowserNextActionCollector, alignPageChangeSummaryNextActionIds, isStandaloneSnapshotNextAction, withOptionalSessionArgs, } from "../../results/next-actions.js";
6
+ import { buildConnectedSessionNextActions, buildNoActivePageNextActions, buildSessionAwareStaleRefNextActions, buildSessionTabRecoveryNextActions, } from "../../results/recovery-next-actions.js";
7
+ import { buildRichInputRecoveryDiagnostic, buildRichInputRecoveryNextActions, buildVisibleRefFallbackNextActions, formatRichInputRecoveryText, formatVisibleRefFallbackText, sanitizeVisibleRefFallbackDiagnostic, } from "../../results/selector-recovery.js";
8
+ import { buildNoActivePageRefSnapshotInvalidation, isNoActivePageSnapshotFailure, } from "../../session-page-state.js";
9
+ import { extractExplicitSessionName, redactInvocationArgs, redactSensitiveText, redactSensitiveValue } from "../../runtime.js";
10
+ import { isRecord } from "../../parsing.js";
11
+ import { buildClickDispatchNextActions, formatClickDispatchDiagnosticText } from "./click-dispatch.js";
12
+ import { buildComboboxFocusNextActions, buildElectronBroadGetTextScopeNextActions, buildFillVerificationNextActions, buildOverlayBlockerNextActions, buildScrollNoopNextActions, buildSelectorTextVisibilityNextActions, buildSourceLookupElectronNextActions, collectVisibleRefFallbackDiagnostic, formatArtifactCleanupGuidanceText, formatComboboxFocusDiagnosticText, formatElectronBroadGetTextScopeText, formatEvalResultWarningText, formatEvalStdinHintText, formatFillVerificationText, formatOverlayBlockerText, formatRecordingDependencyWarningText, formatScrollNoopDiagnosticText, formatSelectorTextVisibilityText, formatTimeoutPartialProgressText, } from "./diagnostics.js";
13
+ import { buildElectronIdentifiers, buildElectronLifecycleNextActions, buildElectronMismatchNextActions, buildElectronRefFreshnessNextActions, buildManagedSessionFreshFailureNextActions, buildManagedSessionOutcome, buildSessionDetailFields, formatElectronRefFreshnessText, formatManagedSessionOutcomeText, } from "./session-state.js";
14
+ export function buildMissingBinaryMessage() {
15
+ return [
16
+ "agent-browser is required but was not found on PATH.",
17
+ "This project does not bundle agent-browser.",
18
+ "Run `pi-agent-browser-doctor` for package/PATH diagnostics, then install agent-browser using the upstream docs:",
19
+ "- https://agent-browser.dev/",
20
+ "- https://github.com/vercel-labs/agent-browser",
21
+ ].join("\n");
22
+ }
23
+ const SEMANTIC_ACTION_CANDIDATE_ACTION_IDS = new Set(["try-button-name-candidate", "try-link-name-candidate"]);
24
+ export function formatSemanticActionCandidateText(actions) {
25
+ const candidateActions = actions.filter((action) => SEMANTIC_ACTION_CANDIDATE_ACTION_IDS.has(action.id) && action.params?.args);
26
+ if (candidateActions.length === 0)
27
+ return undefined;
28
+ return ["Agent-browser candidate fallbacks:", ...candidateActions.map((action) => `- ${action.id}: agent_browser ${JSON.stringify({ args: action.params?.args })} — ${action.reason}`)].join("\n");
29
+ }
30
+ export function buildSemanticActionCandidateActions(compiled) {
31
+ const commandIndex = getCompiledSemanticActionCommandIndex(compiled);
32
+ if (commandIndex < 0 || compiled.args[commandIndex] !== "find")
33
+ return [];
34
+ const locator = compiled.args[commandIndex + 1];
35
+ const value = compiled.args[commandIndex + 2];
36
+ if (!locator || !value)
37
+ return [];
38
+ const sessionPrefix = getCompiledSemanticActionSessionPrefix(compiled);
39
+ const buildRoleCandidate = (role, id, reason) => {
40
+ const args = [...sessionPrefix, "find", "role", role, compiled.action];
41
+ args.push("--name", value);
42
+ return { id, params: { args: redactInvocationArgs(args) }, reason, safety: "Candidate locator fallback only; inspect the page if multiple elements could match the same accessible name.", tool: "agent_browser" };
43
+ };
44
+ if (locator === "text" && compiled.action === "click") {
45
+ return [
46
+ buildRoleCandidate("button", "try-button-name-candidate", "Retry against a button with the same accessible name when text lookup misses."),
47
+ buildRoleCandidate("link", "try-link-name-candidate", "Retry against a link with the same accessible name when text lookup misses."),
48
+ ];
49
+ }
50
+ return [];
51
+ }
52
+ export function buildWrapperRecoveryHint(options) {
53
+ const wrapperManagedContexts = [options.sessionTabCorrection ? "session tab correction" : undefined, options.pinnedBatchUnwrapMode ? "pinned batch routing" : undefined].filter((item) => item !== undefined);
54
+ if (wrapperManagedContexts.length === 0)
55
+ return undefined;
56
+ return `Wrapper recovery hint: this call used ${wrapperManagedContexts.join(" and ")}. Inspect details.effectiveArgs and details.sessionTabCorrection; if the selected tab looks wrong, run tab list for the same session before retrying.`;
57
+ }
58
+ export function redactExactSensitiveText(text, sensitiveValues) {
59
+ let redacted = text;
60
+ for (const value of sensitiveValues)
61
+ redacted = redacted.split(value).join("[REDACTED]");
62
+ return redacted;
63
+ }
64
+ export function redactExactSensitiveValue(value, sensitiveValues) {
65
+ if (sensitiveValues.length === 0)
66
+ return value;
67
+ if (typeof value === "string")
68
+ return redactExactSensitiveText(value, sensitiveValues);
69
+ if (Array.isArray(value))
70
+ return value.map((item) => redactExactSensitiveValue(item, sensitiveValues));
71
+ if (!isRecord(value))
72
+ return value;
73
+ return Object.fromEntries(Object.entries(value).map(([key, entryValue]) => [key, redactExactSensitiveValue(entryValue, sensitiveValues)]));
74
+ }
75
+ export function redactToolDetails(details, sensitiveValues) {
76
+ return redactSensitiveValue(redactExactSensitiveValue(details, sensitiveValues));
77
+ }
78
+ export function redactRecoveryHint(recoveryHint) {
79
+ if (!recoveryHint)
80
+ return undefined;
81
+ const exampleArgs = redactInvocationArgs(recoveryHint.exampleArgs);
82
+ return { ...recoveryHint, exampleArgs, exampleParams: { ...recoveryHint.exampleParams, args: exampleArgs } };
83
+ }
84
+ export function buildJsonVisibleContent(options) {
85
+ const { error, presentation, succeeded, warnings } = options;
86
+ const payload = redactSensitiveValue({ artifacts: presentation.artifacts, data: presentation.data, error, success: succeeded, warnings: warnings && warnings.length > 0 ? warnings : undefined });
87
+ if (isRecord(payload) && isRecord(payload.data) && isRecord(presentation.data) && typeof presentation.data.wsUrl === "string")
88
+ payload.data.wsUrl = presentation.data.wsUrl;
89
+ const images = presentation.content.filter((item) => item.type === "image");
90
+ return [{ type: "text", text: JSON.stringify(payload, null, 2) }, ...images];
91
+ }
92
+ export function getElectronLaunchFailureCategory(failure) {
93
+ if (failure.reason === "policy-blocked")
94
+ return "policy-blocked";
95
+ if (failure.reason === "timeout")
96
+ return "timeout";
97
+ if (failure.reason === "non-electron-target")
98
+ return "validation-error";
99
+ return "upstream-error";
100
+ }
101
+ function formatElectronLaunchFailureDiagnostics(failure) {
102
+ const diagnostics = failure?.diagnostics;
103
+ if (!diagnostics)
104
+ return undefined;
105
+ const lines = ["Electron launch diagnostics:"];
106
+ if (diagnostics.pid !== undefined)
107
+ lines.push(`- PID: ${diagnostics.pid} (${diagnostics.pidAlive === undefined ? "state unknown" : diagnostics.pidAlive ? "alive before cleanup" : "not alive before cleanup"}).`);
108
+ if (diagnostics.exitCode !== undefined || diagnostics.exitSignal !== undefined) {
109
+ const exitParts = [diagnostics.exitCode !== undefined ? `code ${diagnostics.exitCode}` : undefined, diagnostics.exitSignal ? `signal ${diagnostics.exitSignal}` : undefined].filter(Boolean).join(", ");
110
+ lines.push(`- Process exit: ${exitParts || "not observed before cleanup"}.`);
111
+ }
112
+ if (diagnostics.userDataDir)
113
+ lines.push(`- Wrapper profile: ${diagnostics.userDataDir}`);
114
+ if (diagnostics.devToolsActivePort) {
115
+ const activePort = diagnostics.devToolsActivePort;
116
+ const state = activePort.port ? `found port ${activePort.port}` : activePort.found ? `found but invalid${activePort.error ? ` (${activePort.error})` : ""}` : `missing${activePort.error ? ` (${activePort.error})` : ""}`;
117
+ lines.push(`- DevToolsActivePort: ${state} at ${activePort.path}.`);
118
+ }
119
+ if (diagnostics.cdpVersionReached === false)
120
+ lines.push("- CDP /json/version: did not return a valid payload before timeout.");
121
+ if (diagnostics.timeoutMs !== undefined || diagnostics.elapsedMs !== undefined)
122
+ lines.push(`- Timing: ${diagnostics.elapsedMs ?? "unknown"}ms elapsed${diagnostics.timeoutMs !== undefined ? ` of ${diagnostics.timeoutMs}ms timeout` : ""}.`);
123
+ if (diagnostics.outputCaptured === false)
124
+ lines.push("- App stdout/stderr: not captured by this wrapper launch path.");
125
+ lines.push("Retry guidance: increase electron.timeoutMs, try targetType:'any', pass an explicit appPath/executablePath, quit any already-running singleton instance, then retry launch.");
126
+ return lines.join("\n");
127
+ }
128
+ export function buildElectronHostFailureResult(options) {
129
+ const text = [options.errorText, formatElectronLaunchFailureDiagnostics(options.launchFailure), options.launchFailure?.cleanupError ? `Electron launch cleanup warning: ${options.launchFailure.cleanupError}` : undefined].filter((item) => item !== undefined && item.length > 0).join("\n");
130
+ const details = { args: [], compiledElectron: options.compiledElectron, electron: { action: options.compiledElectron.action, error: options.errorText, failure: options.launchFailure, status: options.status ?? "failed" }, managedSessionOutcome: options.managedSessionOutcome, ...buildAgentBrowserResultCategoryDetails({ args: [], errorText: options.errorText, failureCategory: options.failureCategory, succeeded: false, timedOut: options.failureCategory === "timeout" }), summary: options.errorText };
131
+ return { content: [{ type: "text", text: redactSensitiveText(text) }], details: redactToolDetails(details, []), isError: true };
132
+ }
133
+ export function formatElectronTargetLines(targets, limit = 8) {
134
+ const shownTargets = targets.slice(0, limit);
135
+ const lines = shownTargets.map((target) => {
136
+ const label = [target.type, target.title].filter(Boolean).join(" ") || target.id || "target";
137
+ return `- ${label}${target.url ? ` — ${target.url}` : ""}`;
138
+ });
139
+ if (targets.length > shownTargets.length)
140
+ lines.push(`- ... ${targets.length - shownTargets.length} more target(s) omitted`);
141
+ return lines;
142
+ }
143
+ const ELECTRON_PROFILE_ISOLATION_NOTE = "Profile note: electron.launch starts an isolated temporary profile; it does not reuse the app's normal signed-in profile or attach to an already-running authenticated app.";
144
+ const ELECTRON_EXISTING_AUTH_GUIDANCE = "For already-authenticated desktop app content, do not stop here: if host tools are allowed and the app is not running, launch the normal app with --remote-debugging-port=<port>, verify the port, then run agent_browser connect <port>; if it is already running without a debug port, ask before relaunching it.";
145
+ export function formatElectronLaunchText(options) {
146
+ const lines = [`Electron launch: ${options.record.appName} attached as ${options.record.sessionName ?? "managed session"} (launchId ${options.record.launchId}, port ${options.record.port}).`, `Identifiers: launchId ${options.record.launchId} for electron.status/electron.cleanup/electron.probe; sessionName ${options.record.sessionName ?? "not attached"} for browser snapshot/tab commands.`, ELECTRON_PROFILE_ISOLATION_NOTE, ELECTRON_EXISTING_AUTH_GUIDANCE, ...formatElectronTargetLines(options.targets)];
147
+ if (options.handoff?.handoff === "snapshot")
148
+ lines.push(options.handoff.refSnapshot && options.handoff.refSnapshot.refIds.length > 0 ? `Snapshot handoff: ${options.handoff.refSnapshot.refIds.length} interactive ref(s)${options.handoff.snapshotRetryCount ? ` after ${options.handoff.snapshotRetryCount} retry attempt(s)` : ""}.` : "Snapshot handoff: no interactive refs returned after a short readiness retry; run snapshot -i once more before assuming the Electron UI is unusable.");
149
+ else if (options.handoff?.handoff === "tabs")
150
+ lines.push("Tabs handoff completed: safer diagnostic starting point; no interactive refs were captured.");
151
+ else if (options.handoff?.handoff === "connect")
152
+ lines.push("Connect handoff completed: run snapshot -i before using interactive refs.");
153
+ lines.push(`Cleanup: use details.nextActions cleanup-electron-launch or call electron.cleanup with launchId ${options.record.launchId} when finished.`);
154
+ if (options.handoff?.error)
155
+ lines.push(`Handoff warning: ${options.handoff.error}`);
156
+ if (options.upstreamText.trim().length > 0)
157
+ lines.push("", options.upstreamText.trim());
158
+ return lines.join("\n");
159
+ }
160
+ export function buildRedactedPresentationContent(options) {
161
+ const { exactSensitiveValues, plainTextInspection, presentation, presentationEnvelope, succeeded, userRequestedJson, warningText } = options;
162
+ const contentWithSessionWarnings = userRequestedJson && !plainTextInspection ? buildJsonVisibleContent({ error: presentationEnvelope?.error, presentation, succeeded, warnings: warningText ? [warningText] : undefined }) : warningText ? [...presentation.content] : presentation.content;
163
+ if (warningText && !userRequestedJson) {
164
+ if (contentWithSessionWarnings[0]?.type === "text")
165
+ contentWithSessionWarnings[0] = { ...contentWithSessionWarnings[0], text: `${warningText}\n\n${contentWithSessionWarnings[0].text}` };
166
+ else
167
+ contentWithSessionWarnings.unshift({ type: "text", text: warningText });
168
+ }
169
+ return contentWithSessionWarnings.map((item) => {
170
+ if (item.type !== "text")
171
+ return item;
172
+ const exactRedactedText = redactExactSensitiveText(item.text, exactSensitiveValues);
173
+ return userRequestedJson && !plainTextInspection ? { ...item, text: exactRedactedText } : { ...item, text: redactSensitiveText(exactRedactedText) };
174
+ });
175
+ }
176
+ export async function prepareFinalResultRecoveryState(options) {
177
+ let { currentRefSnapshot, currentRefSnapshotInvalidation } = options;
178
+ const categoryDetails = buildAgentBrowserResultCategoryDetails({ artifacts: options.presentation.artifacts, args: options.redactedProcessArgs, command: options.executionPlan.commandInfo.command, confirmationRequired: options.presentation.summary.startsWith("Confirmation required"), errorText: options.errorText ?? options.presentation.summary, failureCategory: options.presentation.failureCategory ?? options.presentation.batchFailure?.failedStep.failureCategory ?? (options.electronPostCommandHealth ? "tab-drift" : undefined), inspection: options.plainTextInspection, parseError: options.parseError, savedFile: options.presentation.savedFile, spawnError: options.processResult.spawnError?.message, succeeded: options.succeeded, tabDrift: !options.succeeded && (options.aboutBlankSessionMismatch !== undefined || options.electronPostCommandHealth !== undefined || options.sessionTabCorrection !== undefined), timedOut: options.processResult.timedOut, validationError: undefined });
179
+ let visibleRefFallbackDiagnostic;
180
+ const visibleRefFallbackSessionName = options.executionPlan.sessionName ?? extractExplicitSessionName(options.runtimeToolArgs);
181
+ if (categoryDetails.failureCategory === "selector-not-found") {
182
+ const selectorRecoveryCommandTokens = options.presentation.batchFailure?.failedStep.command ?? options.commandTokens;
183
+ visibleRefFallbackDiagnostic = await collectVisibleRefFallbackDiagnostic({ commandTokens: selectorRecoveryCommandTokens, compiledSemanticAction: options.compiledSemanticAction, cwd: options.cwd, sessionName: visibleRefFallbackSessionName, signal: options.signal });
184
+ if (visibleRefFallbackDiagnostic && visibleRefFallbackSessionName) {
185
+ const refUpdate = options.sessionPageState.applyRefSnapshot({ fallbackTarget: options.currentSessionTabTarget, sessionName: visibleRefFallbackSessionName, snapshot: visibleRefFallbackDiagnostic.snapshot, update: options.sessionPageStateUpdate });
186
+ currentRefSnapshot = refUpdate.refSnapshot;
187
+ currentRefSnapshotInvalidation = refUpdate.refSnapshotInvalidation;
188
+ }
189
+ }
190
+ const richInputRecoveryDiagnostic = buildRichInputRecoveryDiagnostic(visibleRefFallbackDiagnostic);
191
+ const noActivePageSnapshotFailure = categoryDetails.resultCategory === "failure" && (isNoActivePageSnapshotFailure(options.executionPlan.commandInfo.command, options.errorText ?? options.presentation.summary) || options.batchRefSnapshotState?.invalidation !== undefined);
192
+ if (noActivePageSnapshotFailure && options.executionPlan.sessionName) {
193
+ const refUpdate = options.sessionPageState.applyRefSnapshotInvalidation({ invalidation: buildNoActivePageRefSnapshotInvalidation(), sessionName: options.executionPlan.sessionName, update: options.sessionPageStateUpdate });
194
+ currentRefSnapshot = refUpdate.refSnapshot;
195
+ currentRefSnapshotInvalidation = refUpdate.refSnapshotInvalidation;
196
+ }
197
+ return { categoryDetails, currentRefSnapshot, currentRefSnapshotInvalidation, noActivePageSnapshotFailure, richInputRecoveryDiagnostic, visibleRefFallbackDiagnostic, visibleRefFallbackSessionName };
198
+ }
199
+ function buildTimeoutPartialProgressNextActions(options) {
200
+ const retryArgs = options.timeoutPartialProgress?.retryStep?.retry?.args;
201
+ const stepIndex = options.timeoutPartialProgress?.retryStep?.index;
202
+ const freshSessionAbandoned = options.sessionMode === "fresh" && options.timeoutPartialProgress?.liveUrlRecovered !== true;
203
+ if (retryArgs) {
204
+ return [{
205
+ id: "retry-timeout-step",
206
+ params: freshSessionAbandoned
207
+ ? { args: retryArgs, sessionMode: "fresh" }
208
+ : { args: withOptionalSessionArgs(options.executionPlan.sessionName, retryArgs) },
209
+ reason: freshSessionAbandoned
210
+ ? `Retry the first incomplete timed-out step${stepIndex === undefined ? "" : ` ${stepIndex}`} in a fresh browser session because the timed-out fresh session was not proven live.`
211
+ : `Retry the first incomplete timed-out step${stepIndex === undefined ? "" : ` ${stepIndex}`} against the current browser session.`,
212
+ safety: "Only read-only or idempotent timeout steps get executable retry args; inspect current page/artifact state before using the action.",
213
+ tool: "agent_browser",
214
+ }];
215
+ }
216
+ if (!options.timeoutPartialProgress || freshSessionAbandoned || !options.executionPlan.sessionName)
217
+ return [];
218
+ return [{
219
+ id: "inspect-current-page-after-timeout",
220
+ params: { args: withOptionalSessionArgs(options.executionPlan.sessionName, ["snapshot", "-i"]) },
221
+ reason: `Inspect the current page after timeout before deciding how to resume${stepIndex === undefined ? "" : ` from incomplete step ${stepIndex}`}.`,
222
+ safety: "Read details.timeoutPartialProgress first. Do not blindly retry mutating steps such as clicks, fills, key presses, selects, or checks; split the remaining flow into shorter batches around the next navigation or DOM mutation boundary.",
223
+ tool: "agent_browser",
224
+ }];
225
+ }
226
+ function buildDialogTimeoutNextActions(options) {
227
+ if (options.command !== "dialog" && options.command !== "click" && options.command !== "tap" && options.command !== "find" && options.command !== "eval")
228
+ return [];
229
+ return [
230
+ {
231
+ id: "inspect-dialog-after-timeout",
232
+ params: { args: withOptionalSessionArgs(options.sessionName, ["dialog", "status"]) },
233
+ reason: "Check whether a blocking JavaScript dialog is pending after the timed-out interaction.",
234
+ safety: "Read-only dialog status; this wrapper bounds dialog commands so recovery attempts do not wait for the full default watchdog.",
235
+ tool: "agent_browser",
236
+ },
237
+ {
238
+ id: "dismiss-dialog-after-timeout",
239
+ params: { args: withOptionalSessionArgs(options.sessionName, ["dialog", "dismiss"]) },
240
+ reason: "Dismiss a pending alert/confirm/prompt when the workflow can safely abandon the dialog.",
241
+ safety: "Only run when dismissing/canceling the dialog is acceptable for the user flow.",
242
+ tool: "agent_browser",
243
+ },
244
+ {
245
+ id: "recover-fresh-session-after-dialog-timeout",
246
+ params: { args: ["open", "about:blank"], sessionMode: "fresh" },
247
+ reason: "Start a clean browser session if the current session remains blocked behind a JavaScript dialog.",
248
+ safety: "Replace about:blank with the intended recovery URL; this abandons the blocked managed session.",
249
+ tool: "agent_browser",
250
+ },
251
+ ];
252
+ }
253
+ function buildResultNextActions(options) {
254
+ const nextActionCollector = new AgentBrowserNextActionCollector(options.presentation.nextActions);
255
+ if (options.categoryDetails.resultCategory === "success" && options.executionPlan.commandInfo.command === "connect" && !options.electronLaunchRecord)
256
+ nextActionCollector.appendUnique(buildConnectedSessionNextActions(options.executionPlan.sessionName));
257
+ if (options.noActivePageSnapshotFailure)
258
+ nextActionCollector.appendUnique(buildNoActivePageNextActions(options.executionPlan.sessionName));
259
+ if (options.aboutBlankSessionMismatch) {
260
+ nextActionCollector.appendUnique(buildSessionTabRecoveryNextActions({ kind: "about-blank", recoveryApplied: options.aboutBlankSessionMismatch.recoveryApplied, sessionName: options.executionPlan.sessionName, tabCorrection: options.aboutBlankSessionMismatch.recoveryApplied ? options.sessionTabCorrection : undefined, target: { title: options.aboutBlankSessionMismatch.targetTitle, url: options.aboutBlankSessionMismatch.targetUrl } }));
261
+ if (!options.aboutBlankSessionMismatch.recoveryApplied)
262
+ nextActionCollector.removeWhere(isStandaloneSnapshotNextAction);
263
+ }
264
+ else if (options.categoryDetails.resultCategory === "success" && (options.sessionTabCorrection || options.openResultTabCorrection))
265
+ nextActionCollector.appendUnique(buildSessionTabRecoveryNextActions({ kind: "tab-drift", recoveryApplied: true, sessionName: options.executionPlan.sessionName, tabCorrection: options.sessionTabCorrection ?? options.openResultTabCorrection, target: options.currentSessionTabTarget ?? options.priorSessionTabTarget }));
266
+ if (options.categoryDetails.failureCategory === "stale-ref")
267
+ nextActionCollector.replace(buildSessionAwareStaleRefNextActions(options.executionPlan.sessionName));
268
+ if (options.visibleRefFallbackDiagnostic)
269
+ nextActionCollector.append(buildVisibleRefFallbackNextActions({ diagnostic: options.visibleRefFallbackDiagnostic, sessionName: options.visibleRefFallbackSessionName }));
270
+ if (options.richInputRecoveryDiagnostic)
271
+ nextActionCollector.append(buildRichInputRecoveryNextActions({ diagnostic: options.richInputRecoveryDiagnostic, sessionName: options.visibleRefFallbackSessionName }));
272
+ if (options.electronPostCommandHealth) {
273
+ const electronRecord = options.electronLaunchRecords.get(options.electronPostCommandHealth.launchId);
274
+ if (electronRecord)
275
+ nextActionCollector.appendUnique(buildElectronLifecycleNextActions(electronRecord));
276
+ }
277
+ if (options.electronSessionMismatch) {
278
+ const electronRecord = options.electronLaunchRecords.get(options.electronSessionMismatch.launchId);
279
+ if (electronRecord)
280
+ nextActionCollector.appendUnique(buildElectronMismatchNextActions(electronRecord, options.electronSessionMismatch.liveTarget));
281
+ }
282
+ if (options.categoryDetails.failureCategory === "selector-not-found" && options.redactedCompiledSemanticAction) {
283
+ const candidateActions = buildSemanticActionCandidateActions(options.redactedCompiledSemanticAction);
284
+ if (candidateActions.length > 0)
285
+ nextActionCollector.append(candidateActions);
286
+ }
287
+ if (options.overlayBlockerDiagnostic)
288
+ nextActionCollector.append(buildOverlayBlockerNextActions({ diagnostic: options.overlayBlockerDiagnostic, sessionName: options.executionPlan.sessionName }));
289
+ if (options.fillVerificationDiagnostic)
290
+ nextActionCollector.appendUnique(buildFillVerificationNextActions(options.fillVerificationDiagnostic, options.executionPlan.sessionName));
291
+ if (options.electronRefFreshnessDiagnostic)
292
+ nextActionCollector.appendUnique(buildElectronRefFreshnessNextActions(options.executionPlan.sessionName));
293
+ if (options.selectorTextVisibilityDiagnostics.length > 0)
294
+ nextActionCollector.append(buildSelectorTextVisibilityNextActions({ diagnostics: options.selectorTextVisibilityDiagnostics, sessionName: options.executionPlan.sessionName }));
295
+ if (options.electronBroadGetTextScopeDiagnostics.length > 0)
296
+ nextActionCollector.append(buildElectronBroadGetTextScopeNextActions({ diagnostics: options.electronBroadGetTextScopeDiagnostics, sessionName: options.executionPlan.sessionName }));
297
+ if (options.sourceLookup?.electronContext)
298
+ nextActionCollector.appendUnique(buildSourceLookupElectronNextActions(options.sourceLookup));
299
+ if (options.clickDispatchDiagnostic)
300
+ nextActionCollector.append(buildClickDispatchNextActions({ commandTokens: options.commandTokens, diagnostic: options.clickDispatchDiagnostic, sessionName: options.executionPlan.sessionName }));
301
+ if (options.scrollNoopDiagnostic)
302
+ nextActionCollector.append(buildScrollNoopNextActions(options.executionPlan.sessionName));
303
+ if (options.comboboxFocusDiagnostic)
304
+ nextActionCollector.append(buildComboboxFocusNextActions(options.executionPlan.sessionName));
305
+ if (options.managedSessionOutcome)
306
+ nextActionCollector.appendUnique(buildManagedSessionFreshFailureNextActions(options.managedSessionOutcome));
307
+ if (options.categoryDetails.failureCategory === "timeout" && options.processResult.timedOut) {
308
+ nextActionCollector.appendUnique(buildTimeoutPartialProgressNextActions(options));
309
+ nextActionCollector.appendUnique(buildDialogTimeoutNextActions({ command: options.executionPlan.commandInfo.command, sessionName: options.executionPlan.sessionName }));
310
+ }
311
+ if (options.categoryDetails.failureCategory === "stale-ref" && options.redactedCompiledSemanticAction && isCompiledSemanticActionFindCommand(options.compiledSemanticAction))
312
+ nextActionCollector.append([{ id: "retry-semantic-action-after-stale-ref", params: { args: options.redactedCompiledSemanticAction.args }, reason: "Retry the same semantic target via its compiled find command after the upstream stale-ref failure proves the prior action did not execute.", safety: "Use only for the same intended target; direct stale @refs still require a fresh snapshot or stable locator before retrying.", tool: "agent_browser" }]);
313
+ if (options.electronLaunchRecord)
314
+ nextActionCollector.append(buildAgentBrowserNextActions({ electron: { launchId: options.electronLaunchRecord.launchId, sessionName: options.electronLaunchRecord.sessionName, status: options.electronLaunchRecord.cleanupState }, failureCategory: options.categoryDetails.failureCategory, resultCategory: options.categoryDetails.resultCategory, successCategory: options.categoryDetails.successCategory }));
315
+ return nextActionCollector.toArray();
316
+ }
317
+ function buildAgentBrowserResultDetails(options, nextActions) {
318
+ const publicVisibleRefFallbackDiagnostic = options.visibleRefFallbackDiagnostic ? sanitizeVisibleRefFallbackDiagnostic(options.visibleRefFallbackDiagnostic) : undefined;
319
+ const rawPageChangeSummary = (options.scrollNoopDiagnostic || options.comboboxFocusDiagnostic) && options.presentation.pageChangeSummary ? { ...options.presentation.pageChangeSummary, nextActionIds: nextActions?.map((action) => action.id) } : options.presentation.pageChangeSummary;
320
+ const pageChangeSummary = alignPageChangeSummaryNextActionIds(rawPageChangeSummary, nextActions);
321
+ return {
322
+ args: options.redactedArgs,
323
+ compiledElectron: options.redactedCompiledElectron,
324
+ compiledJob: options.redactedCompiledJob,
325
+ compiledQaPreset: options.redactedCompiledQaPreset,
326
+ compiledSourceLookup: options.redactedCompiledSourceLookup,
327
+ compiledNetworkSourceLookup: options.redactedCompiledNetworkSourceLookup,
328
+ artifactManifest: options.resultArtifactManifest,
329
+ artifactRetentionSummary: options.presentation.artifactRetentionSummary ?? (options.resultArtifactManifest ? formatSessionArtifactRetentionSummary(options.resultArtifactManifest) : undefined),
330
+ artifactCleanup: options.artifactCleanup,
331
+ artifactVerification: options.presentation.artifactVerification,
332
+ artifacts: options.presentation.artifacts,
333
+ batchFailure: options.presentation.batchFailure,
334
+ batchSteps: options.presentation.batchSteps,
335
+ command: options.executionPlan.commandInfo.command,
336
+ compiledSemanticAction: options.redactedCompiledSemanticAction,
337
+ compatibilityWorkaround: options.compatibilityWorkaround,
338
+ subcommand: options.executionPlan.commandInfo.subcommand,
339
+ data: options.presentation.data,
340
+ error: options.plainTextInspection ? undefined : options.presentationEnvelope?.error,
341
+ inspection: options.plainTextInspection || undefined,
342
+ navigationSummary: options.navigationSummary,
343
+ electron: options.electronLaunchRecord ? { action: "launch", cleanup: options.electronFailedConnectCleanup, handoff: options.electronHandoff, identifiers: buildElectronIdentifiers(options.electronLaunchRecord), launch: options.electronLaunchRecord, profileIsolation: options.electronProfileIsolationDetails, status: options.succeeded ? "succeeded" : "failed", targets: options.electronLaunch?.targets, version: options.electronLaunch?.version } : undefined,
344
+ ...options.categoryDetails,
345
+ aboutBlankSessionMismatch: options.aboutBlankSessionMismatch,
346
+ electronPostCommandHealth: options.electronPostCommandHealth,
347
+ electronRefFreshness: options.electronRefFreshnessDiagnostic,
348
+ electronSessionMismatch: options.electronSessionMismatch,
349
+ openResultTabCorrection: options.openResultTabCorrection,
350
+ effectiveArgs: options.redactedProcessArgs,
351
+ exitCode: options.processResult.exitCode,
352
+ fullOutputPath: options.parseFailureOutput.fullOutputPath ?? options.presentation.fullOutputPath,
353
+ fullOutputPaths: options.presentation.fullOutputPaths,
354
+ fullOutputUnavailable: options.parseFailureOutput.fullOutputUnavailable,
355
+ managedSessionOutcome: options.managedSessionOutcome,
356
+ imagePath: options.presentation.imagePath,
357
+ imagePaths: options.presentation.imagePaths,
358
+ nextActions,
359
+ pageChangeSummary,
360
+ clickDispatch: options.clickDispatchDiagnostic,
361
+ overlayBlockers: options.overlayBlockerDiagnostic,
362
+ fillVerification: options.fillVerificationDiagnostic,
363
+ visibleRefFallback: publicVisibleRefFallbackDiagnostic,
364
+ richInputRecovery: options.richInputRecoveryDiagnostic,
365
+ comboboxFocus: options.comboboxFocusDiagnostic,
366
+ recordingDependencyWarning: options.recordingDependencyWarning,
367
+ scrollNoop: options.scrollNoopDiagnostic,
368
+ qaPreset: options.qaPreset,
369
+ qaAttachedTarget: options.qaAttachedTarget,
370
+ electronGetTextScopeWarning: options.electronBroadGetTextScopeDiagnostics[0],
371
+ electronGetTextScopeWarnings: options.electronBroadGetTextScopeDiagnostics.length > 1 ? options.electronBroadGetTextScopeDiagnostics : undefined,
372
+ selectorTextVisibility: options.selectorTextVisibilityDiagnostics[0],
373
+ selectorTextVisibilityAll: options.selectorTextVisibilityDiagnostics.length > 1 ? options.selectorTextVisibilityDiagnostics : undefined,
374
+ evalStdinHint: options.evalStdinHint,
375
+ evalResultWarning: options.evalResultWarning,
376
+ timeoutPartialProgress: options.timeoutPartialProgress,
377
+ parseError: options.plainTextInspection ? undefined : options.parseError,
378
+ savedFile: options.presentation.savedFile,
379
+ savedFilePath: options.presentation.savedFilePath,
380
+ sourceLookup: options.sourceLookup,
381
+ networkSourceLookup: options.networkSourceLookup,
382
+ networkRouteDiagnostics: options.presentation.networkRouteDiagnostics,
383
+ sessionMode: options.sessionMode,
384
+ sessionTabCorrection: options.sessionTabCorrection,
385
+ sessionTabTarget: options.currentSessionTabTarget,
386
+ refSnapshot: options.currentRefSnapshot,
387
+ refSnapshotInvalidation: options.currentRefSnapshotInvalidation,
388
+ ...buildSessionDetailFields(options.executionPlan.sessionName, options.executionPlan.usedImplicitSession),
389
+ sessionRecoveryHint: options.redactedRecoveryHint,
390
+ startupScopedFlags: options.executionPlan.startupScopedFlags,
391
+ stderr: options.processResult.stderr,
392
+ stdout: options.plainTextInspection ? options.inspectionText ?? "" : options.parseSucceeded ? undefined : options.processResult.stdout,
393
+ summary: options.presentation.summary,
394
+ timedOut: options.processResult.timedOut || undefined,
395
+ timeoutMs: options.processResult.timeoutMs,
396
+ };
397
+ }
398
+ export function buildFinalAgentBrowserToolResult(options) {
399
+ const nextActions = buildResultNextActions(options);
400
+ const details = buildAgentBrowserResultDetails(options, nextActions);
401
+ const visibleRefFallbackText = formatVisibleRefFallbackText(options.visibleRefFallbackDiagnostic);
402
+ const richInputRecoveryText = formatRichInputRecoveryText(options.richInputRecoveryDiagnostic);
403
+ const semanticActionCandidateText = nextActions ? formatSemanticActionCandidateText(nextActions) : undefined;
404
+ const clickDispatchText = options.clickDispatchDiagnostic ? formatClickDispatchDiagnosticText(options.clickDispatchDiagnostic) : undefined;
405
+ const overlayBlockerText = options.overlayBlockerDiagnostic ? formatOverlayBlockerText(options.overlayBlockerDiagnostic) : undefined;
406
+ const fillVerificationText = formatFillVerificationText(options.fillVerificationDiagnostic);
407
+ const electronRefFreshnessText = formatElectronRefFreshnessText(options.electronRefFreshnessDiagnostic);
408
+ const selectorTextVisibilityText = formatSelectorTextVisibilityText(options.selectorTextVisibilityDiagnostics);
409
+ const electronBroadGetTextScopeText = formatElectronBroadGetTextScopeText(options.electronBroadGetTextScopeDiagnostics);
410
+ const scrollNoopDiagnosticText = formatScrollNoopDiagnosticText(options.scrollNoopDiagnostic);
411
+ const comboboxFocusDiagnosticText = formatComboboxFocusDiagnosticText(options.comboboxFocusDiagnostic);
412
+ const recordingDependencyWarningText = formatRecordingDependencyWarningText(options.recordingDependencyWarning);
413
+ const evalStdinHintText = formatEvalStdinHintText(options.evalStdinHint);
414
+ const evalResultWarningText = formatEvalResultWarningText(options.evalResultWarning);
415
+ const artifactCleanupText = formatArtifactCleanupGuidanceText(options.artifactCleanup);
416
+ const timeoutPartialProgressText = options.timeoutPartialProgress ? formatTimeoutPartialProgressText(options.timeoutPartialProgress) : undefined;
417
+ const managedSessionOutcomeText = formatManagedSessionOutcomeText(options.managedSessionOutcome);
418
+ const rawAppendedDiagnosticText = [visibleRefFallbackText, richInputRecoveryText, semanticActionCandidateText, clickDispatchText, overlayBlockerText, fillVerificationText, electronRefFreshnessText, selectorTextVisibilityText, electronBroadGetTextScopeText, scrollNoopDiagnosticText, comboboxFocusDiagnosticText, recordingDependencyWarningText, evalStdinHintText, evalResultWarningText, artifactCleanupText, timeoutPartialProgressText, managedSessionOutcomeText].filter((item) => item !== undefined).join("\n\n");
419
+ const appendedDiagnosticText = redactSensitiveText(redactExactSensitiveText(rawAppendedDiagnosticText, options.exactSensitiveValues));
420
+ const shouldAppendDiagnosticText = appendedDiagnosticText.length > 0 && (!options.userRequestedJson || options.plainTextInspection);
421
+ let content = shouldAppendDiagnosticText && options.redactedContent[0]?.type === "text" ? [{ ...options.redactedContent[0], text: `${options.redactedContent[0].text}\n\n${appendedDiagnosticText}` }, ...options.redactedContent.slice(1)] : options.redactedContent;
422
+ if (options.electronLaunchRecord && options.succeeded && content[0]?.type === "text") {
423
+ content = [{ ...content[0], text: redactSensitiveText(formatElectronLaunchText({ handoff: options.electronHandoff, record: options.electronLaunchRecord, targets: options.electronLaunch?.targets ?? [], upstreamText: content[0].text })) }, ...content.slice(1)];
424
+ }
425
+ const result = { content, details: redactToolDetails(details, options.exactSensitiveValues), isError: !options.succeeded };
426
+ return options.compiledNetworkSourceLookup ? redactNetworkSourceLookupSurface(result) : result;
427
+ }
428
+ export async function buildMissingBinaryFailureResult(options) {
429
+ if (!options.processResult.spawnError?.message.includes("ENOENT"))
430
+ return undefined;
431
+ const errorText = buildMissingBinaryMessage();
432
+ const managedSessionOutcome = buildManagedSessionOutcome({ activeAfter: options.managedSessionActive, activeBefore: options.managedSessionActive, attemptedSessionName: options.executionPlan.managedSessionName, command: options.executionPlan.commandInfo.command, currentSessionName: options.managedSessionName, previousSessionName: options.managedSessionName, sessionMode: options.sessionMode, succeeded: false });
433
+ const managedSessionOutcomeText = formatManagedSessionOutcomeText(managedSessionOutcome);
434
+ const managedSessionRecoveryNextActions = buildManagedSessionFreshFailureNextActions(managedSessionOutcome);
435
+ let missingBinaryElectronCleanup;
436
+ let missingBinaryElectronRecord;
437
+ if (options.electronLaunch) {
438
+ missingBinaryElectronCleanup = await cleanupElectronLaunchResources({ child: options.electronLaunch.child, record: options.electronLaunch.record, timeoutMs: options.implicitSessionCloseTimeoutMs });
439
+ missingBinaryElectronRecord = missingBinaryElectronCleanup.record;
440
+ }
441
+ const textParts = [errorText, managedSessionOutcomeText, missingBinaryElectronCleanup ? `Electron cleanup after failed attach: ${missingBinaryElectronCleanup.summary}` : undefined].filter((part) => part !== undefined && part.length > 0);
442
+ return { content: [{ type: "text", text: textParts.join("\n\n") }], details: { args: options.redactedArgs, compatibilityWorkaround: options.compatibilityWorkaround, effectiveArgs: options.redactedProcessArgs, electron: missingBinaryElectronRecord ? { action: "launch", cleanup: missingBinaryElectronCleanup, launch: missingBinaryElectronRecord, status: "failed", targets: options.electronLaunch?.targets, version: options.electronLaunch?.version } : undefined, managedSessionOutcome, nextActions: managedSessionRecoveryNextActions.length > 0 ? managedSessionRecoveryNextActions : undefined, sessionMode: options.sessionMode, sessionTabCorrection: options.sessionTabCorrection, ...buildAgentBrowserResultCategoryDetails({ args: options.redactedProcessArgs, command: options.executionPlan.commandInfo.command, errorText, failureCategory: "missing-binary", spawnError: options.processResult.spawnError.message, succeeded: false }), spawnError: options.processResult.spawnError.message }, isError: true };
443
+ }
@@ -0,0 +1,47 @@
1
+ import { runAgentBrowserProcess } from "../../process.js";
2
+ import { cleanupClickDispatchProbe } from "./click-dispatch.js";
3
+ import { applyBrowserRunStatePatch } from "./session-state.js";
4
+ import { buildMissingBinaryFailureResult } from "./final-result.js";
5
+ import { prepareBrowserRun } from "./prepare.js";
6
+ import { processBrowserOutput } from "./process-output.js";
7
+ export { closeManagedSession } from "./session-state.js";
8
+ export async function runAgentBrowserTool(options) {
9
+ const preparedResult = await prepareBrowserRun(options);
10
+ applyBrowserRunStatePatch(options.state, preparedResult.kind === "ready" ? preparedResult.prepared.statePatch : preparedResult.statePatch);
11
+ if (preparedResult.kind === "early-result") {
12
+ return preparedResult.result;
13
+ }
14
+ const { prepared } = preparedResult;
15
+ try {
16
+ const processResult = await runAgentBrowserProcess({
17
+ args: prepared.processArgs,
18
+ cwd: options.cwd,
19
+ env: prepared.executionPlan.managedSessionName ? { AGENT_BROWSER_IDLE_TIMEOUT_MS: options.implicitSessionIdleTimeoutMs } : undefined,
20
+ signal: options.signal,
21
+ stdin: prepared.processStdin,
22
+ timeoutMs: prepared.processTimeoutMs,
23
+ });
24
+ const missingBinaryResult = await buildMissingBinaryFailureResult({
25
+ compatibilityWorkaround: prepared.compatibilityWorkaround,
26
+ electronLaunch: prepared.electronLaunch,
27
+ executionPlan: prepared.executionPlan,
28
+ implicitSessionCloseTimeoutMs: options.implicitSessionCloseTimeoutMs,
29
+ managedSessionActive: options.state.managedSessionActive,
30
+ managedSessionName: options.state.managedSessionName,
31
+ processResult,
32
+ redactedArgs: prepared.redactedArgs,
33
+ redactedProcessArgs: prepared.redactedProcessArgs,
34
+ sessionMode: prepared.sessionMode,
35
+ sessionTabCorrection: prepared.sessionTabCorrection,
36
+ });
37
+ if (missingBinaryResult) {
38
+ return missingBinaryResult;
39
+ }
40
+ const output = await processBrowserOutput({ ...options, prepared, processResult });
41
+ applyBrowserRunStatePatch(options.state, output.statePatch);
42
+ return output.result;
43
+ }
44
+ finally {
45
+ await cleanupClickDispatchProbe({ cwd: options.cwd, probe: prepared.clickDispatchProbe, sessionName: prepared.executionPlan.sessionName });
46
+ }
47
+ }