pi-agent-browser-native 0.9.3 → 0.9.5

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 (394) hide show
  1. package/CHANGELOG.md +106 -5
  2. package/README.md +58 -791
  3. package/dist/extensions/agent-browser/index.js +43101 -2031
  4. package/dist/extensions/agent-browser/lib/argv-descriptor.js +49 -26
  5. package/dist/extensions/agent-browser/lib/argv-grammar.js +82 -93
  6. package/dist/extensions/agent-browser/lib/bash-guard.js +129 -126
  7. package/dist/extensions/agent-browser/lib/batch-lifecycle.js +112 -51
  8. package/dist/extensions/agent-browser/lib/browser-execution-claim-codec.js +61 -0
  9. package/dist/extensions/agent-browser/lib/browser-execution-claim-storage.js +232 -0
  10. package/dist/extensions/agent-browser/lib/browser-execution-claims.js +202 -0
  11. package/dist/extensions/agent-browser/lib/browser-execution-identity.js +77 -0
  12. package/dist/extensions/agent-browser/lib/browser-journal-branch.js +98 -0
  13. package/dist/extensions/agent-browser/lib/browser-journal-contracts.js +1 -0
  14. package/dist/extensions/agent-browser/lib/browser-journal-projection.js +221 -0
  15. package/dist/extensions/agent-browser/lib/browser-journal-reader.js +89 -0
  16. package/dist/extensions/agent-browser/lib/browser-journal-replay.js +246 -0
  17. package/dist/extensions/agent-browser/lib/browser-journal.js +103 -394
  18. package/dist/extensions/agent-browser/lib/browser-legacy-pages.js +220 -0
  19. package/dist/extensions/agent-browser/lib/browser-legacy-projection.js +282 -0
  20. package/dist/extensions/agent-browser/lib/browser-legacy-types.js +1 -0
  21. package/dist/extensions/agent-browser/lib/browser-session-conversion-stream.js +217 -0
  22. package/dist/extensions/agent-browser/lib/browser-session-conversion.js +80 -335
  23. package/dist/extensions/agent-browser/lib/browser-transcript-contracts.js +35 -0
  24. package/dist/extensions/agent-browser/lib/browser-transcript-validation.js +166 -0
  25. package/dist/extensions/agent-browser/lib/browser-transcript.js +137 -82
  26. package/dist/extensions/agent-browser/lib/browser-value-parsing.js +15 -0
  27. package/dist/extensions/agent-browser/lib/command-capabilities.js +340 -0
  28. package/dist/extensions/agent-browser/lib/command-policy.js +107 -88
  29. package/dist/extensions/agent-browser/lib/command-taxonomy.js +49 -322
  30. package/dist/extensions/agent-browser/lib/config-policy.js +138 -343
  31. package/dist/extensions/agent-browser/lib/config-providers.js +71 -0
  32. package/dist/extensions/agent-browser/lib/config-validation.js +231 -0
  33. package/dist/extensions/agent-browser/lib/config.js +20 -8
  34. package/dist/extensions/agent-browser/lib/electron/cdp.js +20 -8
  35. package/dist/extensions/agent-browser/lib/electron/cleanup.js +128 -83
  36. package/dist/extensions/agent-browser/lib/electron/discovery-darwin.js +109 -0
  37. package/dist/extensions/agent-browser/lib/electron/discovery-desktop.js +136 -0
  38. package/dist/extensions/agent-browser/lib/electron/discovery-evidence.js +90 -0
  39. package/dist/extensions/agent-browser/lib/electron/discovery-linux.js +93 -0
  40. package/dist/extensions/agent-browser/lib/electron/discovery-packages.js +162 -0
  41. package/dist/extensions/agent-browser/lib/electron/discovery-types.js +2 -0
  42. package/dist/extensions/agent-browser/lib/electron/discovery.js +140 -549
  43. package/dist/extensions/agent-browser/lib/electron/launch-monitor.js +102 -0
  44. package/dist/extensions/agent-browser/lib/electron/launch-process.js +209 -0
  45. package/dist/extensions/agent-browser/lib/electron/launch-types.js +2 -0
  46. package/dist/extensions/agent-browser/lib/electron/launch.js +261 -355
  47. package/dist/extensions/agent-browser/lib/executable-path.js +21 -12
  48. package/dist/extensions/agent-browser/lib/execution-cwd.js +35 -18
  49. package/dist/extensions/agent-browser/lib/fs-utils.js +1 -9
  50. package/dist/extensions/agent-browser/lib/input-modes/electron.js +162 -121
  51. package/dist/extensions/agent-browser/lib/input-modes/job.js +123 -317
  52. package/dist/extensions/agent-browser/lib/input-modes/lookup-network-evidence.js +116 -0
  53. package/dist/extensions/agent-browser/lib/input-modes/lookup-plan.js +132 -0
  54. package/dist/extensions/agent-browser/lib/input-modes/lookup-redaction.js +57 -0
  55. package/dist/extensions/agent-browser/lib/input-modes/lookup-source-evidence.js +151 -0
  56. package/dist/extensions/agent-browser/lib/input-modes/lookup-workspace.js +142 -0
  57. package/dist/extensions/agent-browser/lib/input-modes/lookups.js +58 -412
  58. package/dist/extensions/agent-browser/lib/input-modes/params.js +86 -40
  59. package/dist/extensions/agent-browser/lib/input-modes/qa-analysis.js +268 -0
  60. package/dist/extensions/agent-browser/lib/input-modes/qa-presentation.js +117 -0
  61. package/dist/extensions/agent-browser/lib/input-modes/script-child.js +396 -0
  62. package/dist/extensions/agent-browser/lib/input-modes/script-protocol.js +86 -0
  63. package/dist/extensions/agent-browser/lib/input-modes/script-types.js +1 -0
  64. package/dist/extensions/agent-browser/lib/input-modes/script-validation.js +60 -0
  65. package/dist/extensions/agent-browser/lib/input-modes/script.js +60 -409
  66. package/dist/extensions/agent-browser/lib/input-modes/semantic-action.js +218 -128
  67. package/dist/extensions/agent-browser/lib/input-modes/shared.js +15 -4
  68. package/dist/extensions/agent-browser/lib/input-modes/types.js +56 -7
  69. package/dist/extensions/agent-browser/lib/json-schema.js +22 -10
  70. package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +17 -5
  71. package/dist/extensions/agent-browser/lib/managed-session-policy-lock.js +92 -425
  72. package/dist/extensions/agent-browser/lib/managed-session-posix-storage.js +58 -0
  73. package/dist/extensions/agent-browser/lib/managed-session-project-identity.js +244 -0
  74. package/dist/extensions/agent-browser/lib/managed-session-restore-context.js +84 -0
  75. package/dist/extensions/agent-browser/lib/managed-session-restore-policy.js +119 -0
  76. package/dist/extensions/agent-browser/lib/managed-session-restore-state.js +83 -0
  77. package/dist/extensions/agent-browser/lib/managed-session-restore.js +168 -300
  78. package/dist/extensions/agent-browser/lib/managed-session-snapshot-records.js +277 -0
  79. package/dist/extensions/agent-browser/lib/managed-session-snapshots.js +128 -305
  80. package/dist/extensions/agent-browser/lib/managed-session-storage.js +56 -253
  81. package/dist/extensions/agent-browser/lib/native-confirmation.js +140 -0
  82. package/dist/extensions/agent-browser/lib/native-output.js +43 -9
  83. package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +106 -59
  84. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-merge.js +14 -6
  85. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +109 -57
  86. package/dist/extensions/agent-browser/lib/orchestration/browser-run/browser-observation-result.js +82 -0
  87. package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +164 -60
  88. package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostic-values.js +31 -0
  89. package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +152 -781
  90. package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-observation.js +203 -0
  91. package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-text-diagnostics.js +109 -0
  92. package/dist/extensions/agent-browser/lib/orchestration/browser-run/fill-diagnostics.js +119 -0
  93. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-action-recovery.js +147 -0
  94. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-actions.js +144 -0
  95. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-content.js +123 -0
  96. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-contracts.js +1 -0
  97. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-details.js +156 -0
  98. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-electron.js +187 -0
  99. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-evidence.js +39 -0
  100. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-missing-binary.js +89 -0
  101. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-recovery.js +97 -0
  102. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-redaction.js +106 -0
  103. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-timeout.js +110 -0
  104. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +41 -538
  105. package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +199 -154
  106. package/dist/extensions/agent-browser/lib/orchestration/browser-run/interaction-diagnostics.js +290 -0
  107. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-close.js +167 -0
  108. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-inspection.js +108 -0
  109. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +127 -205
  110. package/dist/extensions/agent-browser/lib/orchestration/browser-run/native-helper-observation.js +65 -0
  111. package/dist/extensions/agent-browser/lib/orchestration/browser-run/observation-types.js +1 -0
  112. package/dist/extensions/agent-browser/lib/orchestration/browser-run/overlay-diagnostics.js +120 -0
  113. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.js +113 -30
  114. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.js +109 -28
  115. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter-data.js +150 -0
  116. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +147 -253
  117. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-rendered-text.js +147 -0
  118. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.js +59 -24
  119. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-artifacts.js +159 -0
  120. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-command.js +131 -0
  121. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-contracts.js +1 -0
  122. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-daemon.js +93 -0
  123. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-failure.js +42 -0
  124. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-guards.js +242 -0
  125. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-input.js +75 -0
  126. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-observations.js +92 -0
  127. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-selection.js +254 -0
  128. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-state.js +121 -0
  129. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-refs.js +130 -0
  130. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-resources.js +114 -0
  131. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-semantic.js +121 -0
  132. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-session-plan.js +222 -0
  133. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-timeouts.js +68 -0
  134. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +176 -1123
  135. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-analysis.js +191 -0
  136. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-confirmation.js +152 -0
  137. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-diagnostics.js +182 -0
  138. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-electron.js +150 -0
  139. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-contracts.js +1 -0
  140. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase-contracts.js +1 -0
  141. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase.js +115 -0
  142. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle.js +256 -0
  143. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed-contracts.js +1 -0
  144. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed.js +256 -0
  145. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase-contracts.js +1 -0
  146. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase.js +93 -0
  147. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native.js +113 -0
  148. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation-contracts.js +1 -0
  149. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation.js +316 -0
  150. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-ownership.js +28 -0
  151. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase-contracts.js +1 -0
  152. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase.js +142 -0
  153. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation-contracts.js +1 -0
  154. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation.js +333 -0
  155. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase-contracts.js +1 -0
  156. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase.js +71 -0
  157. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication.js +201 -0
  158. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-receipts.js +183 -0
  159. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-refs.js +200 -0
  160. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-tabs.js +142 -0
  161. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +18 -968
  162. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prompt-guards.js +23 -13
  163. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-receipt-reconciliation.js +198 -0
  164. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-contracts.js +1 -0
  165. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-presentation.js +154 -0
  166. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery.js +68 -151
  167. package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-capture.js +14 -0
  168. package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-observation.js +169 -46
  169. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-commands.js +130 -0
  170. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-electron.js +212 -0
  171. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-observations.js +61 -0
  172. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-outcomes.js +187 -0
  173. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-refs.js +169 -0
  174. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-tabs.js +228 -0
  175. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +77 -765
  176. package/dist/extensions/agent-browser/lib/orchestration/browser-run/text-visibility-diagnostics.js +182 -0
  177. package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-diagnostics.js +256 -0
  178. package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-progress.js +108 -0
  179. package/dist/extensions/agent-browser/lib/orchestration/code-artifact-observation.js +39 -0
  180. package/dist/extensions/agent-browser/lib/orchestration/code-image-observation.js +119 -0
  181. package/dist/extensions/agent-browser/lib/orchestration/electron-host/branch.js +93 -0
  182. package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup-result.js +58 -0
  183. package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup.js +78 -0
  184. package/dist/extensions/agent-browser/lib/orchestration/electron-host/contracts.js +1 -0
  185. package/dist/extensions/agent-browser/lib/orchestration/electron-host/discovery.js +106 -0
  186. package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +48 -821
  187. package/dist/extensions/agent-browser/lib/orchestration/electron-host/policy.js +86 -0
  188. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-collection.js +68 -0
  189. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-data.js +169 -0
  190. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-presentation.js +182 -0
  191. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe.js +161 -0
  192. package/dist/extensions/agent-browser/lib/orchestration/electron-host/status.js +167 -0
  193. package/dist/extensions/agent-browser/lib/orchestration/execution-queue.js +22 -10
  194. package/dist/extensions/agent-browser/lib/orchestration/extension-artifact-preflight.js +211 -0
  195. package/dist/extensions/agent-browser/lib/orchestration/extension-artifacts.js +23 -0
  196. package/dist/extensions/agent-browser/lib/orchestration/extension-attachment-replay.js +99 -0
  197. package/dist/extensions/agent-browser/lib/orchestration/extension-branch-restore.js +275 -0
  198. package/dist/extensions/agent-browser/lib/orchestration/extension-code.js +280 -0
  199. package/dist/extensions/agent-browser/lib/orchestration/extension-command-admission.js +303 -0
  200. package/dist/extensions/agent-browser/lib/orchestration/extension-command-output.js +36 -0
  201. package/dist/extensions/agent-browser/lib/orchestration/extension-command-result.js +335 -0
  202. package/dist/extensions/agent-browser/lib/orchestration/extension-command-run.js +227 -0
  203. package/dist/extensions/agent-browser/lib/orchestration/extension-command-state.js +1 -0
  204. package/dist/extensions/agent-browser/lib/orchestration/extension-electron-ownership.js +204 -0
  205. package/dist/extensions/agent-browser/lib/orchestration/extension-execution-locks.js +139 -0
  206. package/dist/extensions/agent-browser/lib/orchestration/extension-execution-queue.js +24 -0
  207. package/dist/extensions/agent-browser/lib/orchestration/extension-host-coordination.js +98 -0
  208. package/dist/extensions/agent-browser/lib/orchestration/extension-host-run.js +295 -0
  209. package/dist/extensions/agent-browser/lib/orchestration/extension-intent-replay.js +41 -0
  210. package/dist/extensions/agent-browser/lib/orchestration/extension-invocation.js +7 -0
  211. package/dist/extensions/agent-browser/lib/orchestration/extension-lifecycle.js +102 -0
  212. package/dist/extensions/agent-browser/lib/orchestration/extension-managed-ownership.js +133 -0
  213. package/dist/extensions/agent-browser/lib/orchestration/extension-observation.js +120 -0
  214. package/dist/extensions/agent-browser/lib/orchestration/extension-prompt.js +180 -0
  215. package/dist/extensions/agent-browser/lib/orchestration/extension-recording.js +290 -0
  216. package/dist/extensions/agent-browser/lib/orchestration/extension-resource-contracts.js +1 -0
  217. package/dist/extensions/agent-browser/lib/orchestration/extension-resource-replay.js +269 -0
  218. package/dist/extensions/agent-browser/lib/orchestration/extension-result-state.js +113 -0
  219. package/dist/extensions/agent-browser/lib/orchestration/extension-runtime.js +146 -0
  220. package/dist/extensions/agent-browser/lib/orchestration/extension-script-leases.js +58 -0
  221. package/dist/extensions/agent-browser/lib/orchestration/extension-tool-boundary.js +62 -0
  222. package/dist/extensions/agent-browser/lib/orchestration/extension-version-check.js +54 -0
  223. package/dist/extensions/agent-browser/lib/orchestration/input-plan-types.js +1 -0
  224. package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +261 -185
  225. package/dist/extensions/agent-browser/lib/orchestration/input-redaction.js +62 -0
  226. package/dist/extensions/agent-browser/lib/orchestration/native-config.js +144 -0
  227. package/dist/extensions/agent-browser/lib/orchestration/native-root-launch.js +77 -0
  228. package/dist/extensions/agent-browser/lib/orchestration/native-session-defaults.js +210 -157
  229. package/dist/extensions/agent-browser/lib/orchestration/operation-paths.js +124 -58
  230. package/dist/extensions/agent-browser/lib/orchestration/output-file.js +197 -99
  231. package/dist/extensions/agent-browser/lib/orchestration/script-mode.js +199 -96
  232. package/dist/extensions/agent-browser/lib/owned-managed-session-context.js +55 -0
  233. package/dist/extensions/agent-browser/lib/page-target-batch.js +118 -0
  234. package/dist/extensions/agent-browser/lib/page-target-guards.js +50 -0
  235. package/dist/extensions/agent-browser/lib/page-target-navigation.js +104 -0
  236. package/dist/extensions/agent-browser/lib/page-target-validation.js +55 -246
  237. package/dist/extensions/agent-browser/lib/parsing.js +13 -4
  238. package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +133 -68
  239. package/dist/extensions/agent-browser/lib/playbook.js +16 -12
  240. package/dist/extensions/agent-browser/lib/process-child.js +284 -0
  241. package/dist/extensions/agent-browser/lib/process-environment.js +13 -6
  242. package/dist/extensions/agent-browser/lib/process-errors.js +23 -0
  243. package/dist/extensions/agent-browser/lib/process-identity.js +47 -15
  244. package/dist/extensions/agent-browser/lib/process-socket-storage.js +256 -0
  245. package/dist/extensions/agent-browser/lib/process-stdout.js +74 -0
  246. package/dist/extensions/agent-browser/lib/process.js +145 -536
  247. package/dist/extensions/agent-browser/lib/prompt-artifacts.js +287 -0
  248. package/dist/extensions/agent-browser/lib/prompt-policy.js +15 -194
  249. package/dist/extensions/agent-browser/lib/read-command.js +41 -0
  250. package/dist/extensions/agent-browser/lib/read-confirmation.js +131 -68
  251. package/dist/extensions/agent-browser/lib/recording-reservations.js +118 -45
  252. package/dist/extensions/agent-browser/lib/redaction-fields.js +75 -0
  253. package/dist/extensions/agent-browser/lib/redaction-json.js +149 -0
  254. package/dist/extensions/agent-browser/lib/redaction-url.js +88 -0
  255. package/dist/extensions/agent-browser/lib/results/action-contracts.js +1 -0
  256. package/dist/extensions/agent-browser/lib/results/action-recommendations.js +28 -271
  257. package/dist/extensions/agent-browser/lib/results/artifact-contracts.js +1 -0
  258. package/dist/extensions/agent-browser/lib/results/artifact-manifest-validation.js +133 -0
  259. package/dist/extensions/agent-browser/lib/results/artifact-manifest.js +96 -94
  260. package/dist/extensions/agent-browser/lib/results/artifact-recommendations.js +73 -0
  261. package/dist/extensions/agent-browser/lib/results/categories.js +111 -54
  262. package/dist/extensions/agent-browser/lib/results/confirmation.js +29 -13
  263. package/dist/extensions/agent-browser/lib/results/editable-ref-evidence.js +62 -27
  264. package/dist/extensions/agent-browser/lib/results/electron-recommendations.js +83 -0
  265. package/dist/extensions/agent-browser/lib/results/envelope-decoding.js +48 -0
  266. package/dist/extensions/agent-browser/lib/results/envelope.js +90 -67
  267. package/dist/extensions/agent-browser/lib/results/evidence-contracts.js +1 -0
  268. package/dist/extensions/agent-browser/lib/results/failure-recommendations.js +180 -0
  269. package/dist/extensions/agent-browser/lib/results/network-routes.js +86 -45
  270. package/dist/extensions/agent-browser/lib/results/network.js +35 -12
  271. package/dist/extensions/agent-browser/lib/results/next-actions.js +49 -19
  272. package/dist/extensions/agent-browser/lib/results/presentation/artifact-files.js +320 -0
  273. package/dist/extensions/agent-browser/lib/results/presentation/artifact-format.js +138 -0
  274. package/dist/extensions/agent-browser/lib/results/presentation/artifact-images.js +113 -0
  275. package/dist/extensions/agent-browser/lib/results/presentation/artifact-verification.js +145 -0
  276. package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +99 -555
  277. package/dist/extensions/agent-browser/lib/results/presentation/batch-contracts.js +1 -0
  278. package/dist/extensions/agent-browser/lib/results/presentation/batch-recording.js +118 -0
  279. package/dist/extensions/agent-browser/lib/results/presentation/batch-redaction.js +68 -0
  280. package/dist/extensions/agent-browser/lib/results/presentation/batch-rendering.js +135 -0
  281. package/dist/extensions/agent-browser/lib/results/presentation/batch-step.js +227 -0
  282. package/dist/extensions/agent-browser/lib/results/presentation/batch-summary.js +91 -0
  283. package/dist/extensions/agent-browser/lib/results/presentation/batch.js +91 -460
  284. package/dist/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.js +9 -5
  285. package/dist/extensions/agent-browser/lib/results/presentation/command-presenters.js +216 -0
  286. package/dist/extensions/agent-browser/lib/results/presentation/common.js +26 -9
  287. package/dist/extensions/agent-browser/lib/results/presentation/content.js +86 -29
  288. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-a11y.js +67 -0
  289. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-health.js +79 -0
  290. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-identity.js +199 -0
  291. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-logs.js +75 -0
  292. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network-actions.js +216 -0
  293. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network.js +124 -0
  294. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-redaction.js +64 -0
  295. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-storage.js +209 -0
  296. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-stream.js +69 -0
  297. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-summary.js +222 -0
  298. package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +103 -1052
  299. package/dist/extensions/agent-browser/lib/results/presentation/early-result.js +70 -0
  300. package/dist/extensions/agent-browser/lib/results/presentation/errors.js +130 -60
  301. package/dist/extensions/agent-browser/lib/results/presentation/input-contracts.js +1 -0
  302. package/dist/extensions/agent-browser/lib/results/presentation/large-output.js +60 -145
  303. package/dist/extensions/agent-browser/lib/results/presentation/navigation.js +147 -88
  304. package/dist/extensions/agent-browser/lib/results/presentation/notices.js +75 -0
  305. package/dist/extensions/agent-browser/lib/results/presentation/observation-contracts.js +1 -0
  306. package/dist/extensions/agent-browser/lib/results/presentation/observation-rendering.js +127 -0
  307. package/dist/extensions/agent-browser/lib/results/presentation/outcomes.js +120 -0
  308. package/dist/extensions/agent-browser/lib/results/presentation/output-completion.js +77 -0
  309. package/dist/extensions/agent-browser/lib/results/presentation/output-spill.js +51 -0
  310. package/dist/extensions/agent-browser/lib/results/presentation/registry.js +116 -240
  311. package/dist/extensions/agent-browser/lib/results/presentation/semantic-action.js +35 -21
  312. package/dist/extensions/agent-browser/lib/results/presentation/skills.js +109 -73
  313. package/dist/extensions/agent-browser/lib/results/presentation/source.js +109 -0
  314. package/dist/extensions/agent-browser/lib/results/presentation.js +17 -261
  315. package/dist/extensions/agent-browser/lib/results/recommendation-contracts.js +1 -0
  316. package/dist/extensions/agent-browser/lib/results/recording.js +52 -14
  317. package/dist/extensions/agent-browser/lib/results/recovery-actions.js +14 -5
  318. package/dist/extensions/agent-browser/lib/results/recovery-next-actions.js +30 -22
  319. package/dist/extensions/agent-browser/lib/results/selector-recovery-target.js +83 -0
  320. package/dist/extensions/agent-browser/lib/results/selector-recovery.js +119 -119
  321. package/dist/extensions/agent-browser/lib/results/snapshot-compact.js +266 -0
  322. package/dist/extensions/agent-browser/lib/results/snapshot-content.js +32 -0
  323. package/dist/extensions/agent-browser/lib/results/snapshot-high-value-controls.js +104 -71
  324. package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +31 -11
  325. package/dist/extensions/agent-browser/lib/results/snapshot-segments.js +125 -66
  326. package/dist/extensions/agent-browser/lib/results/snapshot-spill.js +26 -7
  327. package/dist/extensions/agent-browser/lib/results/snapshot.js +28 -248
  328. package/dist/extensions/agent-browser/lib/results/text.js +16 -5
  329. package/dist/extensions/agent-browser/lib/runtime-args-validation.js +133 -0
  330. package/dist/extensions/agent-browser/lib/runtime-compatibility.js +81 -0
  331. package/dist/extensions/agent-browser/lib/runtime-contracts.js +1 -0
  332. package/dist/extensions/agent-browser/lib/runtime-redaction.js +118 -0
  333. package/dist/extensions/agent-browser/lib/runtime-replay-events.js +144 -0
  334. package/dist/extensions/agent-browser/lib/runtime-session-identity.js +76 -0
  335. package/dist/extensions/agent-browser/lib/runtime-session-plan.js +114 -0
  336. package/dist/extensions/agent-browser/lib/runtime-session-replay.js +123 -0
  337. package/dist/extensions/agent-browser/lib/runtime-tab-correction.js +65 -0
  338. package/dist/extensions/agent-browser/lib/runtime-timeouts.js +28 -0
  339. package/dist/extensions/agent-browser/lib/runtime.js +137 -1041
  340. package/dist/extensions/agent-browser/lib/session-identity.js +51 -0
  341. package/dist/extensions/agent-browser/lib/session-page-observation.js +357 -0
  342. package/dist/extensions/agent-browser/lib/session-page-state.js +178 -333
  343. package/dist/extensions/agent-browser/lib/session-page-types.js +1 -0
  344. package/dist/extensions/agent-browser/lib/temp-artifact-budget.js +81 -0
  345. package/dist/extensions/agent-browser/lib/temp-mutation-queue.js +7 -0
  346. package/dist/extensions/agent-browser/lib/temp-root-ownership.js +234 -0
  347. package/dist/extensions/agent-browser/lib/temp-root.js +211 -0
  348. package/dist/extensions/agent-browser/lib/temp.js +33 -446
  349. package/dist/extensions/agent-browser/lib/tool-surface.js +94 -24
  350. package/dist/extensions/agent-browser/lib/upstream-version.js +3 -2
  351. package/dist/extensions/agent-browser/lib/web-search-providers.js +193 -0
  352. package/dist/extensions/agent-browser/lib/web-search-request.js +102 -0
  353. package/dist/extensions/agent-browser/lib/web-search-results.js +281 -0
  354. package/dist/extensions/agent-browser/lib/web-search-schema.js +82 -0
  355. package/dist/extensions/agent-browser/lib/web-search.js +124 -614
  356. package/dist/extensions/agent-browser/lib/webmcp-observation.js +13 -6
  357. package/dist/extensions/agent-browser/lib/windows-stock-launcher.js +63 -37
  358. package/dist/extensions/agent-browser/script-worker.js +80 -43
  359. package/dist/scripts/agent-browser-target.mjs +4 -2
  360. package/docs/ARCHITECTURE.md +19 -6
  361. package/docs/CODE_QUALITY.md +267 -0
  362. package/docs/COMMAND_REFERENCE.md +272 -241
  363. package/docs/ELECTRON.md +77 -46
  364. package/docs/REFERENCE.md +869 -0
  365. package/docs/RELEASE.md +25 -22
  366. package/docs/REQUIREMENTS.md +2 -1
  367. package/docs/SUPPORT_MATRIX.md +81 -79
  368. package/docs/TOOL_CONTRACT.md +158 -125
  369. package/docs/platform-smoke.md +8 -8
  370. package/package.json +144 -120
  371. package/scripts/agent-browser-capability-baseline.mjs +361 -957
  372. package/scripts/agent-browser-target.mjs +6 -2
  373. package/scripts/build.mjs +37 -8
  374. package/scripts/capability-core-commands.mjs +193 -0
  375. package/scripts/capability-options.mjs +283 -0
  376. package/scripts/capability-samples.mjs +133 -0
  377. package/scripts/capability-section.mjs +11 -0
  378. package/scripts/config.mjs +235 -132
  379. package/scripts/convert-browser-session.mjs +30 -9
  380. package/scripts/doctor-sources.mjs +195 -0
  381. package/scripts/doctor.mjs +94 -249
  382. package/scripts/platform-smoke/artifacts.mjs +38 -11
  383. package/scripts/platform-smoke/commands.mjs +104 -0
  384. package/scripts/platform-smoke/crabbox-runner.mjs +167 -80
  385. package/scripts/platform-smoke/doctor-support.mjs +157 -0
  386. package/scripts/platform-smoke/doctor-windows.mjs +230 -0
  387. package/scripts/platform-smoke/doctor.mjs +212 -320
  388. package/scripts/platform-smoke/lease-evidence.mjs +132 -0
  389. package/scripts/platform-smoke/linux-image/Dockerfile +8 -2
  390. package/scripts/platform-smoke/suite-checks.mjs +98 -0
  391. package/scripts/platform-smoke/suite-evidence.mjs +281 -0
  392. package/scripts/platform-smoke/targets.mjs +154 -472
  393. package/scripts/platform-smoke.mjs +55 -40
  394. package/scripts/prepare.mjs +16 -7
@@ -1,1149 +1,202 @@
1
- import { copyFile, mkdir } from "node:fs/promises";
2
- import { dirname, resolve } from "node:path";
3
- import { extractExplicitSessionName, getBooleanFlagValue, isUpstreamEnvFlagEnabled, projectUpstreamGlobalFlags, resolveAgentBrowserNamespace } from "../../argv-grammar.js";
4
- import { isCloseCommand } from "../../command-taxonomy.js";
5
- import { isBrowserIndependentRead, needsManagedSession } from "../../command-policy.js";
6
- import { parseArgvDescriptor } from "../../argv-descriptor.js";
7
- import { prepareAgentBrowserSpawnArgs, withChromeStartupArgs } from "../../process.js";
8
- import { cleanupElectronLaunchResources } from "../../electron/cleanup.js";
9
- import { launchElectronApp } from "../../electron/launch.js";
10
- import { pathExists } from "../../fs-utils.js";
11
- import { isRecord } from "../../parsing.js";
12
- import { getCompiledSemanticActionSessionPrefix } from "../../input-modes/semantic-action.js";
13
- import { tryNetworkRequestsPageFilter } from "./prepare/network-page-filter.js";
14
- import { tryContainerScroll, tryPageScrollTo } from "./prepare/scroll-shims.js";
15
- import { trySnapshotFilter } from "./prepare/snapshot-filter.js";
16
- import { commandTimeoutNeedsActivePageUrl, getCommandAwareProcessTimeoutMs } from "./prepare/wait-timeouts.js";
17
- import { getPersistentSessionArtifactStore } from "./session-state.js";
18
- import { isBrowserIndependentConfirmation, suppressConfirmationPageHelpers } from "../../read-confirmation.js";
1
+ import { createFreshSessionName } from "../../runtime.js";
2
+ import { getPageTargetValidationError } from "../../page-target-validation.js";
19
3
  import { buildAgentBrowserResultCategoryDetails } from "../../results/categories.js";
20
- import { applyNamespaceToNextActions } from "../../results/next-actions.js";
21
- import { buildSessionAwareStaleRefNextActions, buildSessionTabRecoveryNextActions } from "../../results/recovery-next-actions.js";
22
- import { resolveVisibleRefActionFromSnapshot } from "../../results/selector-recovery.js";
23
- import { buildPageTransitionRefSnapshotInvalidation, extractRefSnapshotFromData, normalizeComparableUrl } from "../../session-page-state.js";
24
- import { buildExecutionPlan, canUseHeadlessCompatibilityUserAgent, createFreshSessionName, extractCommandTokens, extractUpstreamCommandTokens, getDefaultHeadlessCompatUserAgent, parseWaitCommandTokens, redactInvocationArgs, redactSensitiveText, } from "../../runtime.js";
25
- import { buildOwnedManagedSessionRestoreContext, resolveExplicitAutosaveInterval, withOwnedManagedSessionContext, } from "../../managed-session-restore.js";
26
- import { getAgentBrowserProcessEnvironment } from "../../process-environment.js";
27
- import { getExplicitSessionPageVerificationRequirement, getPageTargetValidationError, } from "../../page-target-validation.js";
28
- import { acquireOwnedManagedSessionDaemonPolicy, getRunningHeadedAutosavePolicyChangeError, inspectManagedSessionDaemon } from "./managed-session-daemon-policy.js";
29
- import { buildManagedSessionOutcome, buildSessionDetailFields, buildStaleRefPreflight, getSessionContextKey, findElectronLaunchRecordForSession, extractStringResultField, ensureSessionTabTarget, getGuardedRefUsage, getTraceOwnerGuardMessage, runSessionCommandData, shouldPinSessionTabForCommand, } from "./session-state.js";
30
- import { getUpstreamEffectiveBatchSteps, parseBatchStdinJsonArray } from "../batch-stdin.js";
31
- import { buildElectronHostFailureResult, formatAgentBrowserNextActionsText, getElectronLaunchFailureCategory, redactRecoveryHint } from "./final-result.js";
32
- import { prepareClickDispatchProbe } from "./click-dispatch.js";
33
- import { buildUnsupportedScrollIntoViewRecovery, collectScrollPositionSnapshot, validateQaAttachedPrecondition } from "./diagnostics.js";
34
- import { getScreenshotPathTokenIndex } from "./artifact-paths.js";
35
- import { findRequestedArtifactCloseViolation } from "./prompt-guards.js";
36
- export function normalizeRunInput(input) {
37
- const base = { redactedArgs: input.redactedArgs, toolArgs: input.toolArgs, toolStdin: input.toolStdin };
38
- switch (input.kind) {
39
- case "electron":
40
- return { ...base, compiledElectron: input.compiledElectron, redactedCompiledElectron: input.redactedCompiledElectron };
41
- case "networkSourceLookup":
42
- return { ...base, compiledNetworkSourceLookup: input.compiledNetworkSourceLookup, redactedCompiledNetworkSourceLookup: input.redactedCompiledNetworkSourceLookup };
43
- case "qa":
44
- return { ...base, compiledJob: input.compiledJob, compiledQaPreset: input.compiledQaPreset, redactedCompiledJob: input.redactedCompiledJob, redactedCompiledQaPreset: input.redactedCompiledQaPreset };
45
- case "semanticAction":
46
- return { ...base, compiledSemanticAction: input.compiledSemanticAction, redactedCompiledSemanticAction: input.redactedCompiledSemanticAction };
47
- case "sourceLookup":
48
- return { ...base, compiledSourceLookup: input.compiledSourceLookup, redactedCompiledSourceLookup: input.redactedCompiledSourceLookup };
49
- case "args":
50
- return base;
4
+ import { withChromeStartupArgs } from "../../process.js";
5
+ import { withOwnedManagedSessionContext } from "../../managed-session-restore.js";
6
+ import { findElectronLaunchRecordForSession, getPersistentSessionArtifactStore, } from "./session-state.js";
7
+ import { normalizeRunInput } from "./prepare-input.js";
8
+ import { preparationFailure } from "./prepare-failure.js";
9
+ import { cleanupPreparationResources, prepareArtifactArguments, prepareElectronLaunch, } from "./prepare-resources.js";
10
+ import { prepareSessionPlan } from "./prepare-session-plan.js";
11
+ import { prepareDaemonPolicy, prepareChromeStartupArgs, } from "./prepare-daemon.js";
12
+ import { preparePageState } from "./prepare-page-state.js";
13
+ import { preparePageSelection } from "./prepare-page-selection.js";
14
+ import { prepareSemanticAction } from "./prepare-semantic.js";
15
+ import { prepareGuardEvidence, validatePreparationGuards } from "./prepare-guards.js";
16
+ import { prepareObservations } from "./prepare-observations.js";
17
+ import { prepareNativeCommand } from "./prepare-command.js";
18
+ export { buildInvocationPreview, getExactSensitiveStdinValues, normalizeRunInput, validateStdinCommandContract, } from "./prepare-input.js";
19
+ export { prepareAgentBrowserArgs, repairScreenshotData } from "./prepare-artifacts.js";
20
+ function rawPageFailure(input) {
21
+ const error = getPageTargetValidationError({
22
+ args: input.toolArgs,
23
+ stdin: input.toolStdin,
24
+ trustedFirstBatchTabSelection: true,
25
+ });
26
+ if (error === undefined || error === "") {
27
+ return undefined;
51
28
  }
29
+ return preparationFailure({
30
+ message: error,
31
+ details: {
32
+ args: input.redactedArgs,
33
+ ...buildAgentBrowserResultCategoryDetails({
34
+ args: input.redactedArgs,
35
+ errorText: error,
36
+ succeeded: false,
37
+ validationError: error,
38
+ }),
39
+ validationError: error,
40
+ },
41
+ });
52
42
  }
53
- export function buildInvocationPreview(effectiveArgs) {
54
- const preview = effectiveArgs.join(" ");
55
- return preview.length > 120 ? `${preview.slice(0, 117)}...` : preview;
56
- }
57
- function getArtifactParentPathTokenIndex(commandTokens) {
58
- if (commandTokens[0] === "download" && commandTokens.length >= 3)
59
- return 2;
60
- if (commandTokens[0] === "pdf" && commandTokens.length >= 2)
61
- return 1;
62
- if (commandTokens[0] === "state" && commandTokens[1] === "save" && commandTokens.length >= 3)
63
- return 2;
64
- if (commandTokens[0] === "wait")
65
- return parseWaitCommandTokens(commandTokens).downloadPathIndex;
66
- return undefined;
67
- }
68
- async function ensureArtifactParentDirectory(commandTokens, cwd) {
69
- const pathIndex = getArtifactParentPathTokenIndex(commandTokens);
70
- if (pathIndex === undefined)
71
- return;
72
- const requestedPath = commandTokens[pathIndex];
73
- if (!requestedPath)
74
- return;
75
- await mkdir(dirname(resolve(cwd, requestedPath)), { recursive: true });
76
- }
77
- async function normalizeScreenshotPathInTokens(commandTokens, cwd, batchStep = false) {
78
- // Native batch rows skip outer CLI global-flag cleanup.
79
- const projection = batchStep ? undefined : projectUpstreamGlobalFlags(commandTokens);
80
- const pathIndex = getScreenshotPathTokenIndex(projection?.tokens ?? commandTokens);
81
- const screenshotPathTokenIndex = pathIndex === undefined ? undefined : projection ? projection.indices[pathIndex] : pathIndex;
82
- if (screenshotPathTokenIndex === undefined)
83
- return { tokens: commandTokens };
84
- const requestedPath = commandTokens[screenshotPathTokenIndex];
85
- const absolutePath = resolve(cwd, requestedPath);
86
- await mkdir(dirname(absolutePath), { recursive: true });
87
- const tokens = [...commandTokens];
88
- tokens[screenshotPathTokenIndex] = absolutePath;
89
- const terminatorIndex = batchStep ? -1 : tokens.indexOf("--");
90
- if (terminatorIndex >= 0) {
91
- tokens.splice(terminatorIndex, 1);
92
- }
43
+ async function prepareCommandPhases(state, controls, context) {
44
+ const plan = context.semantic.selection.executionPlan;
45
+ const isRestoreDisabled = () => state.managedSessionRestoreState.isDisabled(plan.sessionName, plan.namespace);
46
+ const evidence = prepareGuardEvidence(controls.preserveAttachedBrowserSession, context);
47
+ const guarded = await validatePreparationGuards({
48
+ pageState: state.sessionPageState,
49
+ update: context.update,
50
+ traceOwners: state.traceOwners,
51
+ artifactManifest: state.artifactManifest,
52
+ }, { ...controls, isRestoreDisabled }, context, evidence);
53
+ if (guarded) {
54
+ return guarded;
55
+ }
56
+ const observation = await prepareObservations({
57
+ pageState: state.sessionPageState,
58
+ restoreState: state.managedSessionRestoreState,
59
+ update: context.update,
60
+ artifactManifest: state.artifactManifest,
61
+ artifactStore: controls.artifactStore,
62
+ }, controls, context, evidence);
63
+ if (observation) {
64
+ return observation;
65
+ }
66
+ return prepareNativeCommand({ ...controls, managedSessionActive: state.managedSessionActive, isRestoreDisabled }, context, evidence);
67
+ }
68
+ async function preparePagePhases(state, controls, planning, request) {
69
+ const { plan, session, policy } = planning;
70
+ const page = await preparePageState(state, controls, {
71
+ plan,
72
+ session,
73
+ inactive: policy.inactive,
74
+ update: request.update,
75
+ preserveAttachedBrowserSession: controls.preserveAttachedBrowserSession,
76
+ });
77
+ const selection = await preparePageSelection(state.sessionPageState, controls, session.readConfirmation !== undefined, {
78
+ ...request,
79
+ plan,
80
+ page,
81
+ restoreDisabled: state.managedSessionRestoreState.isDisabled(plan.sessionName, plan.namespace),
82
+ });
83
+ if ("earlyResult" in selection) {
84
+ return selection.earlyResult;
85
+ }
86
+ const semantic = await prepareSemanticAction(controls, request.sessionFacts, {
87
+ hasReadConfirmation: session.readConfirmation !== undefined,
88
+ ownsSession: session.ownedManagedSession !== undefined,
89
+ }, {
90
+ ...request,
91
+ selection,
92
+ });
93
+ return prepareCommandPhases(state, controls, { ...request, semantic, session, policy });
94
+ }
95
+ async function prepareRequest(identity, input, settings) {
96
+ const freshSessionName = createFreshSessionName(identity.managedSessionBaseName, identity.ephemeralSessionSeed, identity.freshSessionOrdinal + 1);
97
+ const rawFailure = rawPageFailure(input);
98
+ if (rawFailure) {
99
+ return { earlyResult: rawFailure };
100
+ }
101
+ const electron = await prepareElectronLaunch({
102
+ ...settings,
103
+ managedSessionActive: identity.managedSessionActive,
104
+ managedSessionName: identity.managedSessionName,
105
+ }, input, freshSessionName);
106
+ if ("earlyResult" in electron) {
107
+ return electron;
108
+ }
109
+ const launch = electron.electronLaunch;
93
110
  return {
94
111
  request: {
95
- absolutePath,
96
- path: requestedPath,
112
+ input,
113
+ freshSessionName,
114
+ freshSessionOrdinal: identity.freshSessionOrdinal,
115
+ sessionMode: input.compiledElectron?.action === "launch" ? "fresh" : (settings.sessionMode ?? "auto"),
116
+ runtimeToolArgs: launch ? ["connect", launch.connectArg] : input.toolArgs,
117
+ stdin: launch ? undefined : input.toolStdin,
118
+ electronLaunch: launch,
97
119
  },
98
- tokens,
99
- };
100
- }
101
- async function prepareBatchScreenshotPaths(args, stdin, cwd) {
102
- const commandTokens = extractUpstreamCommandTokens(args);
103
- if (commandTokens[0] !== "batch") {
104
- return undefined;
105
- }
106
- const argumentSteps = getUpstreamEffectiveBatchSteps(commandTokens, undefined);
107
- if (argumentSteps.length > 0) {
108
- // Upstream executes raw argument steps exclusively and ignores stdin, so
109
- // prepare parent directories for the rows that will run and skip stdin
110
- // preparation (no directories for never-executed rows).
111
- for (const step of argumentSteps) {
112
- await ensureArtifactParentDirectory(step, cwd);
113
- if (step[0] === "screenshot") {
114
- // Reuse the screenshot path resolution for its parent-directory side
115
- // effect only: raw strings are never rewritten, so the normalized
116
- // tokens and path request are deliberately discarded.
117
- await normalizeScreenshotPathInTokens(step, cwd, true);
118
- }
119
- }
120
- return undefined;
121
- }
122
- if (stdin === undefined) {
123
- return undefined;
124
- }
125
- const parsed = parseBatchStdinJsonArray(stdin);
126
- if (parsed.error || parsed.steps === undefined) {
127
- return undefined;
128
- }
129
- let changed = false;
130
- const batchScreenshotPathRequests = [];
131
- const preparedSteps = await Promise.all(parsed.steps.map(async (step, index) => {
132
- if (!Array.isArray(step) || !step.every((item) => typeof item === "string")) {
133
- return step;
134
- }
135
- await ensureArtifactParentDirectory(step, cwd);
136
- if (step[0] !== "screenshot") {
137
- return step;
138
- }
139
- const normalized = await normalizeScreenshotPathInTokens(step, cwd, true);
140
- batchScreenshotPathRequests[index] = normalized.request;
141
- if (normalized.request) {
142
- changed = true;
143
- }
144
- return normalized.tokens;
145
- }));
146
- return changed
147
- ? {
148
- args,
149
- batchScreenshotPathRequests: parsed.steps.flatMap((step, index) => Array.isArray(step) && step.length === 0 ? [] : [batchScreenshotPathRequests[index]]),
150
- stdin: JSON.stringify(preparedSteps),
151
- }
152
- : undefined;
153
- }
154
- export async function prepareAgentBrowserArgs(args, stdin, cwd) {
155
- const preparedBatch = await prepareBatchScreenshotPaths(args, stdin, cwd);
156
- if (preparedBatch) {
157
- return preparedBatch;
158
- }
159
- const commandTokens = extractCommandTokens(args);
160
- await ensureArtifactParentDirectory(extractUpstreamCommandTokens(args), cwd);
161
- const normalized = await normalizeScreenshotPathInTokens(commandTokens, cwd);
162
- if (!normalized.request) {
163
- return { args };
164
- }
165
- const commandStartIndex = args.length - commandTokens.length;
166
- return {
167
- args: [...args.slice(0, commandStartIndex), ...normalized.tokens],
168
- screenshotPathRequest: normalized.request,
169
120
  };
170
121
  }
171
- async function repairScreenshotData(options) {
172
- const { cwd, data, request } = options;
173
- if (data.changed === false)
174
- return { data };
175
- const reportedPath = typeof data.path === "string" ? data.path : undefined;
176
- const reportedAbsolutePath = reportedPath ? resolve(cwd, reportedPath) : undefined;
177
- let status = await pathExists(request.absolutePath) ? "saved" : "missing";
178
- let tempPath;
179
- if (reportedAbsolutePath && reportedAbsolutePath !== request.absolutePath) {
180
- tempPath = reportedAbsolutePath;
181
- if (status === "missing" && await pathExists(reportedAbsolutePath)) {
182
- await mkdir(dirname(request.absolutePath), { recursive: true });
183
- await copyFile(reportedAbsolutePath, request.absolutePath);
184
- status = "repaired-from-temp";
185
- }
186
- }
122
+ function preparationControls(options) {
187
123
  return {
188
- data: {
189
- ...data,
190
- path: request.absolutePath,
191
- },
192
- request: {
193
- ...request,
194
- status,
195
- tempPath,
196
- },
124
+ cwd: options.cwd,
125
+ signal: options.signal,
126
+ timeoutMs: options.params.timeoutMs,
127
+ modelVisible: options.modelVisible,
128
+ onUpdate: options.onUpdate,
129
+ promptPolicy: options.promptPolicy,
130
+ preserveAttachedBrowserSession: options.preserveAttachedBrowserSession,
131
+ establishAttachedBrowserSession: options.establishAttachedBrowserSession,
132
+ artifactStore: getPersistentSessionArtifactStore(options.ctx),
197
133
  };
198
134
  }
199
- export { repairScreenshotData };
200
- const DIALOG_COMMAND_PROCESS_TIMEOUT_MS = 5_000;
201
- const DIALOG_COMMAND_PROCESS_TIMEOUT_ENV = "PI_AGENT_BROWSER_DIALOG_PROCESS_TIMEOUT_MS";
202
- const LIKELY_DIALOG_TRIGGER_PROCESS_TIMEOUT_MS = 8_000;
203
- const LIKELY_DIALOG_TRIGGER_PROCESS_TIMEOUT_ENV = "PI_AGENT_BROWSER_DIALOG_TRIGGER_PROCESS_TIMEOUT_MS";
204
- const DIALOG_TRIGGER_TEXT_PATTERN = /\b(?:alert|confirm|dialog|prompt)\b/i;
205
- function getPositiveIntegerEnv(name) {
206
- const value = getAgentBrowserProcessEnvironment()[name];
207
- if (!value || !/^\d+$/.test(value.trim()))
208
- return undefined;
209
- const parsed = Number(value.trim());
210
- return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : undefined;
211
- }
212
- function getRefIdsFromDirectCommand(commandTokens) {
213
- return [...new Set(getGuardedRefUsage(commandTokens))];
214
- }
215
- function commandTextLooksLikeDialogTrigger(commandTokens, refSnapshot) {
216
- if (commandTokens.some((token) => DIALOG_TRIGGER_TEXT_PATTERN.test(token)))
217
- return true;
218
- for (const refId of getRefIdsFromDirectCommand(commandTokens)) {
219
- const ref = refSnapshot?.refs?.[refId];
220
- if (ref && DIALOG_TRIGGER_TEXT_PATTERN.test(`${ref.role} ${ref.name}`))
221
- return true;
222
- }
223
- return false;
224
- }
225
- function getDialogAwareProcessTimeoutMs(commandTokens, refSnapshot, stdin) {
226
- const command = commandTokens[0];
227
- if (command === "dialog")
228
- return getPositiveIntegerEnv(DIALOG_COMMAND_PROCESS_TIMEOUT_ENV) ?? DIALOG_COMMAND_PROCESS_TIMEOUT_MS;
229
- if (command === "eval" && typeof stdin === "string" && DIALOG_TRIGGER_TEXT_PATTERN.test(stdin))
230
- return getPositiveIntegerEnv(LIKELY_DIALOG_TRIGGER_PROCESS_TIMEOUT_ENV) ?? LIKELY_DIALOG_TRIGGER_PROCESS_TIMEOUT_MS;
231
- if ((command === "click" || command === "tap" || (command === "find" && commandTokens.includes("click"))) && commandTextLooksLikeDialogTrigger(commandTokens, refSnapshot))
232
- return getPositiveIntegerEnv(LIKELY_DIALOG_TRIGGER_PROCESS_TIMEOUT_ENV) ?? LIKELY_DIALOG_TRIGGER_PROCESS_TIMEOUT_MS;
233
- return undefined;
234
- }
235
- function describeRef(refSnapshot, refId) {
236
- const ref = refSnapshot?.refs?.[refId];
237
- return ref ? `${ref.role} ${JSON.stringify(ref.name)}` : "not present";
238
- }
239
- function getSamePageFreshnessPreflightFailure(options) {
240
- const { refIds } = options;
241
- if (refIds.length === 0)
242
- return undefined;
243
- const previousUrl = normalizeComparableUrl(options.previousSnapshot.target?.url);
244
- const currentUrl = normalizeComparableUrl(options.currentSnapshot.target?.url);
245
- if (!previousUrl || !currentUrl || previousUrl !== currentUrl || currentUrl === "about:blank")
246
- return undefined;
247
- const mismatchedRefs = refIds.filter((refId) => {
248
- const previous = options.previousSnapshot.refs?.[refId];
249
- const current = options.currentSnapshot.refs?.[refId];
250
- if (!options.currentSnapshot.refIds.includes(refId))
251
- return true;
252
- if (!previous || !current)
253
- return previous !== current;
254
- return previous.role !== current.role || previous.name !== current.name;
255
- });
256
- if (mismatchedRefs.length === 0)
257
- return undefined;
258
- const refText = mismatchedRefs.map((refId) => `@${refId}`).join(", ");
259
- const evidence = mismatchedRefs.map((refId) => `@${refId}: previous ${describeRef(options.previousSnapshot, refId)}, current ${describeRef(options.currentSnapshot, refId)}`).join("; ");
135
+ function preparationSessionFacts(state) {
260
136
  return {
261
- message: `Ref ${refText} no longer matches the latest same-page snapshot. The page likely rerendered after the previous snapshot; run snapshot -i and retry with current refs. Evidence: ${evidence}.`,
262
- refIds: mismatchedRefs,
137
+ managedSessionActive: state.managedSessionActive,
138
+ managedSessionName: state.managedSessionName,
139
+ managedSessionNamespace: state.managedSessionNamespace,
140
+ managedSessionCompatibilityWorkaround: state.managedSessionCompatibilityWorkaround,
141
+ managedSessionHeadedAutosaveDisabled: state.managedSessionHeadedAutosaveDisabled,
142
+ managedSessionHeadedAutosaveInterval: state.managedSessionHeadedAutosaveInterval,
263
143
  };
264
144
  }
265
- async function collectSamePageRefFreshnessPreflight(options) {
266
- const refIds = [...new Set(getGuardedRefUsage(options.commandTokens, options.stdin))];
267
- if (!options.previousSnapshot || !options.sessionName || refIds.length === 0)
268
- return undefined;
269
- const previousUrl = normalizeComparableUrl(options.previousSnapshot.target?.url);
270
- const currentTargetUrl = normalizeComparableUrl(options.currentTarget?.url);
271
- if (currentTargetUrl === "about:blank" || (previousUrl && currentTargetUrl && previousUrl !== currentTargetUrl))
272
- return undefined;
273
- const snapshotData = await runSessionCommandData({ args: ["snapshot", "-i"], cwd: options.cwd, namespace: options.namespace, sessionName: options.sessionName, signal: options.signal });
274
- const currentSnapshot = extractRefSnapshotFromData(snapshotData);
275
- if (!currentSnapshot)
276
- return undefined;
277
- const snapshotWithTarget = { ...currentSnapshot, target: currentSnapshot.target ?? options.currentTarget };
278
- const mismatch = getSamePageFreshnessPreflightFailure({ currentSnapshot: snapshotWithTarget, previousSnapshot: options.previousSnapshot, refIds });
279
- if (!mismatch)
280
- return undefined;
281
- return { message: mismatch.message, refIds: mismatch.refIds, snapshot: snapshotWithTarget };
282
- }
283
- function getIdleTimeoutMismatch(args, configuredValue) {
284
- for (let index = 0; index < args.length; index += 1) {
285
- if (args[index] !== "--idle-timeout")
286
- continue;
287
- const requestedToken = args[++index];
288
- if (!requestedToken || !/^\d+$/.test(requestedToken) || Number(requestedToken) === Number(configuredValue))
289
- continue;
290
- return `--idle-timeout ${requestedToken} conflicts with this Pi process's managed-session idle timeout (${configuredValue} ms). Restart Pi with PI_AGENT_BROWSER_IMPLICIT_SESSION_IDLE_TIMEOUT_MS=${requestedToken} and omit --idle-timeout; changing the launch value for one call can restart the upstream browser and discard the active tab.`;
291
- }
292
- return undefined;
293
- }
294
- function isPasswordStdinAuthSave(options) {
295
- return options.command === "auth" && options.commandTokens[1] === "save" && options.commandTokens.includes("--password-stdin");
296
- }
297
- export function getExactSensitiveStdinValues(options) {
298
- if (options.stdin === undefined || !isPasswordStdinAuthSave(options)) {
299
- return [];
300
- }
301
- return [...new Set([options.stdin, options.stdin.trimEnd(), options.stdin.trim()].filter((value) => value.length > 0))];
302
- }
303
- export function validateStdinCommandContract(options) {
304
- if (options.stdin === undefined) {
305
- return undefined;
306
- }
307
- if (options.command === "batch") {
308
- return undefined;
309
- }
310
- if (options.command === "eval" && options.commandTokens.includes("--stdin")) {
311
- return undefined;
312
- }
313
- if (isPasswordStdinAuthSave(options)) {
314
- return undefined;
315
- }
316
- const commandLabel = options.command ? `\`${options.command}\`` : "the requested command";
317
- return `agent_browser stdin is only supported for \`batch\`, \`eval --stdin\`, and \`auth save --password-stdin\`; remove stdin from ${commandLabel} or use one of those command forms.`;
318
- }
319
- function canResolveSemanticVisibleRef(compiled) {
320
- if (!compiled?.locator)
321
- return false;
322
- if (compiled.action === "select")
323
- return true;
324
- return compiled.locator === "role" && ["check", "click", "fill"].includes(compiled.action);
325
- }
326
- function requiresResolvedSemanticVisibleRef(compiled) {
327
- return compiled?.action === "select" && compiled.locator !== undefined;
328
- }
329
- async function resolveSemanticActionVisibleRefArgs(options) {
330
- if (!canResolveSemanticVisibleRef(options.compiled) || !options.sessionName)
331
- return undefined;
332
- const snapshotData = options.refSnapshot ? undefined : await runSessionCommandData({ args: ["snapshot", "-i"], cwd: options.cwd, namespace: options.namespace, sessionName: options.sessionName, signal: options.signal });
333
- const resolution = resolveVisibleRefActionFromSnapshot({ allowFill: true, compiledAction: options.compiled, refSnapshot: options.refSnapshot, snapshotData });
334
- return resolution ? { args: [...getCompiledSemanticActionSessionPrefix(options.compiled), ...resolution.args], snapshot: resolution.snapshot } : undefined;
335
- }
336
145
  export async function prepareBrowserRun(options) {
337
- const { cwd, onUpdate, params, signal, state } = options;
338
- const { sessionPageState, traceOwners, managedSessionBaseName, ephemeralSessionSeed } = state;
339
- const agentBrowserProcessEnv = getAgentBrowserProcessEnvironment();
340
- let freshSessionOrdinal = state.freshSessionOrdinal;
341
- const { compiledElectron, compiledJob, compiledNetworkSourceLookup, compiledQaPreset, compiledSemanticAction, compiledSourceLookup, redactedArgs, redactedCompiledElectron, redactedCompiledJob, redactedCompiledNetworkSourceLookup, redactedCompiledQaPreset, redactedCompiledSemanticAction, redactedCompiledSourceLookup, toolArgs, toolStdin, } = normalizeRunInput(options.input);
342
- let runtimeToolArgs = toolArgs;
343
- let runtimeToolStdin = toolStdin;
344
- let electronLaunch;
345
- const sessionMode = compiledElectron?.action === "launch" ? "fresh" : params.sessionMode ?? "auto";
346
- const freshSessionName = createFreshSessionName(managedSessionBaseName, ephemeralSessionSeed, freshSessionOrdinal + 1);
347
- const rawPageTargetError = getPageTargetValidationError({
348
- args: runtimeToolArgs,
349
- stdin: runtimeToolStdin,
350
- trustedFirstBatchTabSelection: true,
146
+ const input = normalizeRunInput(options.input);
147
+ const state = options.state;
148
+ const launched = await prepareRequest(state, input, {
149
+ signal: options.signal,
150
+ sessionMode: options.params.sessionMode,
151
+ getOwnerSessionId: () => options.ctx.sessionManager.getSessionId(),
351
152
  });
352
- if (rawPageTargetError) {
353
- return {
354
- kind: "early-result",
355
- result: {
356
- content: [{ type: "text", text: rawPageTargetError }],
357
- details: {
358
- args: redactedArgs,
359
- ...buildAgentBrowserResultCategoryDetails({ args: redactedArgs, errorText: rawPageTargetError, succeeded: false, validationError: rawPageTargetError }),
360
- validationError: rawPageTargetError,
361
- },
362
- isError: true,
363
- },
364
- };
365
- }
366
- if (compiledElectron?.action === "launch") {
367
- const launchResult = await launchElectronApp({ ...compiledElectron, signal });
368
- if (!launchResult.ok) {
369
- const managedSessionOutcome = buildManagedSessionOutcome({
370
- activeAfter: state.managedSessionActive,
371
- activeBefore: state.managedSessionActive,
372
- attemptedSessionName: freshSessionName,
373
- command: "connect",
374
- currentSessionName: state.managedSessionName,
375
- previousSessionName: state.managedSessionName,
376
- sessionMode: "fresh",
377
- succeeded: false,
378
- });
379
- return { kind: "early-result", result: buildElectronHostFailureResult({
380
- compiledElectron: redactedCompiledElectron ?? compiledElectron,
381
- errorText: launchResult.failure.error,
382
- failureCategory: getElectronLaunchFailureCategory(launchResult.failure),
383
- launchFailure: launchResult.failure,
384
- managedSessionOutcome,
385
- status: launchResult.failure.reason,
386
- }) };
387
- }
388
- electronLaunch = launchResult.value;
389
- electronLaunch.record.ownerSessionId = options.ctx.sessionManager.getSessionId();
390
- runtimeToolArgs = ["connect", electronLaunch.connectArg];
391
- runtimeToolStdin = undefined;
153
+ if ("earlyResult" in launched) {
154
+ return launched.earlyResult;
392
155
  }
393
- let managedSessionPolicyLock;
394
- let managedSessionPolicyLockTransferred = false;
395
- let electronLaunchTransferred = false;
156
+ const request = launched.request;
157
+ let policy;
158
+ let transferred = false;
396
159
  try {
397
- let preparedArgs;
398
- try {
399
- preparedArgs = await prepareAgentBrowserArgs(runtimeToolArgs, runtimeToolStdin, cwd);
400
- }
401
- catch (error) {
402
- signal?.throwIfAborted();
403
- if (!(error instanceof Error) || !("syscall" in error) || error.syscall !== "mkdir" || !("path" in error) || typeof error.path !== "string")
404
- throw error;
405
- const guidance = "Choose a writable artifact path whose parent components are directories. Use absolute paths in raw batch artifact rows.";
406
- const validationError = redactSensitiveText(`Could not prepare artifact directory ${error.path}: ${error.message}. ${guidance}`);
407
- const nextActions = [{ artifactPath: redactSensitiveText(error.path), id: "verify-artifact-path", reason: guidance, safety: "The requested browser command did not run; inspect the directory with host file tools before retrying.", tool: "agent_browser" }];
408
- return { kind: "early-result", result: {
409
- content: [{ type: "text", text: validationError }],
410
- details: {
411
- agentBrowserStarted: false,
412
- args: redactedArgs,
413
- nextActions,
414
- ...buildAgentBrowserResultCategoryDetails({ args: redactedArgs, succeeded: false, validationError }),
415
- validationError,
416
- },
417
- isError: true,
418
- } };
419
- }
420
- const userRequestedJson = getBooleanFlagValue(runtimeToolArgs, "--json") === true;
421
- const routedReadConfirmation = state.sessionPageState.findReadConfirmation(preparedArgs.args, resolveAgentBrowserNamespace(preparedArgs.args, agentBrowserProcessEnv.AGENT_BROWSER_NAMESPACE), runtimeToolStdin);
422
- const readConfirmation = suppressConfirmationPageHelpers(routedReadConfirmation) ? routedReadConfirmation : undefined;
423
- const browserIndependentConfirmation = isBrowserIndependentConfirmation(readConfirmation);
424
- let executionPlan = buildExecutionPlan(preparedArgs.args, {
425
- freshSessionName,
426
- managedSessionActive: state.managedSessionActive,
427
- managedSessionCompatibilityWorkaround: state.managedSessionCompatibilityWorkaround,
428
- managedSessionName: state.managedSessionName,
429
- managedSessionNamespace: state.managedSessionNamespace,
430
- sessionMode,
431
- stdin: runtimeToolStdin,
432
- browserIndependentReadConfirmation: browserIndependentConfirmation,
433
- });
434
- const browserIndependent = browserIndependentConfirmation || isBrowserIndependentRead(extractUpstreamCommandTokens(preparedArgs.args), runtimeToolStdin)
435
- || (executionPlan.commandInfo.command === "session" && executionPlan.commandInfo.subcommand === "info");
436
- const ownedSessionKey = getSessionContextKey(executionPlan.sessionName, executionPlan.namespace);
437
- const plannedSessionPageState = sessionPageState.get(ownedSessionKey);
438
- const pageTargetError = readConfirmation && executionPlan.commandInfo.command !== "batch" ? undefined : getPageTargetValidationError({
439
- allowFirstBatchConfirmation: readConfirmation !== undefined,
440
- args: executionPlan.effectiveArgs,
441
- currentPageUrl: plannedSessionPageState.tabTarget?.url,
442
- pageUrlUnknown: plannedSessionPageState.tabTargetUnknown === true,
443
- stdin: runtimeToolStdin,
160
+ const controls = preparationControls(options);
161
+ const artifacts = await prepareArtifactArguments(controls, {
162
+ args: request.runtimeToolArgs,
163
+ stdin: request.stdin,
164
+ redactedArgs: input.redactedArgs,
444
165
  });
445
- if (!executionPlan.validationError && pageTargetError)
446
- executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: pageTargetError };
447
- const recordedOwnedSession = ownedSessionKey ? state.ownedManagedSessions.get(ownedSessionKey) : undefined;
448
- const targetsCurrentManagedSession = state.managedSessionActive
449
- && ownedSessionKey === getSessionContextKey(state.managedSessionName, state.managedSessionNamespace);
450
- const targetsOffCurrentOwnedSession = recordedOwnedSession !== undefined && !targetsCurrentManagedSession;
451
- const idleTimeoutMismatch = !browserIndependent && (executionPlan.managedSessionName || recordedOwnedSession || targetsCurrentManagedSession || (state.managedSessionActive && extractExplicitSessionName(preparedArgs.args) === undefined))
452
- ? getIdleTimeoutMismatch(preparedArgs.args, options.implicitSessionIdleTimeoutMs)
453
- : undefined;
454
- if (idleTimeoutMismatch)
455
- executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: idleTimeoutMismatch };
456
- const offCurrentLaunchScopedFlags = targetsOffCurrentOwnedSession
457
- ? executionPlan.startupScopedFlags.filter((flag) => flag !== "--namespace")
458
- : [];
459
- const offCurrentCompatibilityUpgrade = targetsOffCurrentOwnedSession
460
- && executionPlan.compatibilityWorkaround !== undefined
461
- && recordedOwnedSession.compatibilityWorkaround === undefined;
462
- if (!browserIndependent && targetsOffCurrentOwnedSession && canUseHeadlessCompatibilityUserAgent(preparedArgs.args, agentBrowserProcessEnv)) {
463
- const compatibilityWorkaround = executionPlan.compatibilityWorkaround ?? recordedOwnedSession.compatibilityWorkaround;
464
- if (compatibilityWorkaround) {
465
- const userAgentIndex = executionPlan.effectiveArgs.indexOf("--user-agent");
466
- executionPlan = {
467
- ...executionPlan,
468
- compatibilityWorkaround,
469
- effectiveArgs: userAgentIndex < 0
470
- ? executionPlan.effectiveArgs
471
- : [...executionPlan.effectiveArgs.slice(0, userAgentIndex), ...executionPlan.effectiveArgs.slice(userAgentIndex + 2)],
472
- };
473
- }
166
+ if ("earlyResult" in artifacts) {
167
+ return artifacts.earlyResult;
474
168
  }
475
- const retainedHeadedAutosaveDisabled = recordedOwnedSession?.headedManagedAutosaveDisabled === true
476
- || (targetsCurrentManagedSession && state.managedSessionHeadedAutosaveDisabled === true);
477
- const retainedHeadedAutosaveInterval = recordedOwnedSession?.headedManagedAutosaveInterval
478
- ?? (targetsCurrentManagedSession ? state.managedSessionHeadedAutosaveInterval : undefined);
479
- const explicitAutosaveInterval = resolveExplicitAutosaveInterval(agentBrowserProcessEnv.AGENT_BROWSER_AUTOSAVE_INTERVAL_MS);
480
- const autosavePolicyChangeError = getRunningHeadedAutosavePolicyChangeError(retainedHeadedAutosaveInterval, isCloseCommand(executionPlan.commandInfo.command));
481
- if (!browserIndependent && !executionPlan.validationError && autosavePolicyChangeError) {
482
- executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: autosavePolicyChangeError };
483
- }
484
- const headedLaunch = getBooleanFlagValue(executionPlan.effectiveArgs, "--headed") ?? isUpstreamEnvFlagEnabled(agentBrowserProcessEnv.AGENT_BROWSER_HEADED);
485
- const providerLaunch = executionPlan.startupScopedFlags.some((flag) => flag === "--provider" || flag === "-p") || agentBrowserProcessEnv.AGENT_BROWSER_PROVIDER !== undefined;
486
- const headedManagedAutosaveDisabled = retainedHeadedAutosaveDisabled || (explicitAutosaveInterval === undefined && headedLaunch);
487
- const headedManagedAutosaveInterval = retainedHeadedAutosaveInterval ?? (headedLaunch ? explicitAutosaveInterval ?? "0" : undefined);
488
- const compatibilityUserAgent = executionPlan.compatibilityWorkaround ? getDefaultHeadlessCompatUserAgent() : undefined;
489
- const compatibilityUserAgentApplied = compatibilityUserAgent !== undefined
490
- && executionPlan.effectiveArgs.some((token, index) => token === "--user-agent" && executionPlan.effectiveArgs[index + 1] === compatibilityUserAgent);
491
- const ownedManagedSession = browserIndependent && !recordedOwnedSession && !targetsCurrentManagedSession ? undefined : buildOwnedManagedSessionRestoreContext({
492
- args: executionPlan.effectiveArgs,
493
- reuseOnly: browserIndependent,
494
- cwd: recordedOwnedSession?.cwd ?? cwd,
495
- currentManagedSessionName: state.managedSessionName,
496
- currentManagedSessionNamespace: state.managedSessionNamespace,
497
- headedManagedAutosaveDisabled: browserIndependent ? retainedHeadedAutosaveDisabled : headedManagedAutosaveDisabled,
498
- headedManagedAutosaveInterval: browserIndependent ? retainedHeadedAutosaveInterval : headedManagedAutosaveInterval,
499
- managedSessionName: executionPlan.managedSessionName,
500
- namespace: executionPlan.namespace,
501
- parentEnv: agentBrowserProcessEnv,
502
- recordedOwnedSession,
169
+ const sessionFacts = preparationSessionFacts(state);
170
+ const initial = prepareSessionPlan({
171
+ pageState: state.sessionPageState,
503
172
  restoreState: state.managedSessionRestoreState,
504
- sessionName: executionPlan.sessionName,
505
- stdin: runtimeToolStdin,
506
- compatibilityUserAgent: compatibilityUserAgentApplied ? compatibilityUserAgent : undefined,
507
- wrapperInjectedUserAgent: compatibilityUserAgentApplied,
508
- });
509
- let managedSessionDaemonInactive = false;
510
- let managedSessionCleanupOnlyReason;
511
- if (!browserIndependent && !executionPlan.validationError && ownedManagedSession) {
512
- const closeCommand = isCloseCommand(executionPlan.commandInfo.command);
513
- const policy = await acquireOwnedManagedSessionDaemonPolicy({
514
- context: ownedManagedSession,
515
- electronLaunchRecord: findElectronLaunchRecordForSession(executionPlan.sessionName, state.electronLaunchRecords, executionPlan.namespace),
516
- electronVerificationTimeoutMs: params.timeoutMs,
517
- mode: closeCommand ? "close" : "reuse",
518
- signal,
519
- });
520
- managedSessionPolicyLock = policy.lock;
521
- managedSessionDaemonInactive = policy.daemonStatus === "inactive";
522
- if (policy.error) {
523
- managedSessionCleanupOnlyReason = policy.cleanupOnlyReason;
524
- executionPlan = {
525
- ...executionPlan,
526
- recoveryHint: undefined,
527
- validationError: policy.error,
528
- };
529
- }
530
- else if (!closeCommand && policy.daemonStatus === "active" && offCurrentLaunchScopedFlags.length > 0) {
531
- executionPlan = {
532
- ...executionPlan,
533
- recoveryHint: undefined,
534
- validationError: `This older wrapper-owned session is already running, so launch-scoped flags ${offCurrentLaunchScopedFlags.join(", ")} would replace or be ignored by upstream agent-browser. Close it first, or remove the explicit --session and retry with sessionMode: \"fresh\".`,
535
- };
536
- }
537
- else if (!closeCommand && policy.daemonStatus === "active" && offCurrentCompatibilityUpgrade) {
538
- executionPlan = {
539
- ...executionPlan,
540
- recoveryHint: undefined,
541
- validationError: "This older wrapper-owned session is already running without the user agent required by this site. Close it first, or remove the explicit --session and retry with sessionMode: \"fresh\".",
542
- };
543
- }
544
- else if (!closeCommand && policy.daemonStatus === "inactive" && compatibilityUserAgent && !compatibilityUserAgentApplied) {
545
- ownedManagedSession.compatibilityUserAgent = compatibilityUserAgent;
546
- executionPlan = {
547
- ...executionPlan,
548
- effectiveArgs: ["--user-agent", compatibilityUserAgent, ...executionPlan.effectiveArgs],
549
- };
550
- }
551
- }
552
- let chromeStartupArgs;
553
- if (options.input.chromeStartupArgs !== undefined && !options.preserveAttachedBrowserSession && !browserIndependent
554
- && !executionPlan.validationError && !isCloseCommand(executionPlan.commandInfo.command)
555
- && needsManagedSession(parseArgvDescriptor(preparedArgs.args), runtimeToolStdin)) {
556
- const inactive = ownedManagedSession ? managedSessionDaemonInactive : options.daemonInactive
557
- ?? (executionPlan.sessionName !== undefined && (await inspectManagedSessionDaemon({ cwd, signal, sessionName: executionPlan.sessionName, namespace: executionPlan.namespace })).status === "inactive");
558
- if (inactive || options.input.configuredChromeLaunch)
559
- chromeStartupArgs = options.input.chromeStartupArgs;
560
- }
561
- return await withChromeStartupArgs(chromeStartupArgs, () => withOwnedManagedSessionContext(ownedManagedSession, async () => {
562
- const managedSessionRestoreDisabled = () => state.managedSessionRestoreState.isDisabled(executionPlan.sessionName, executionPlan.namespace);
563
- const sessionStateKey = getSessionContextKey(executionPlan.sessionName, executionPlan.namespace);
564
- const priorSessionPageState = sessionPageState.get(sessionStateKey);
565
- let priorSessionTabTarget = priorSessionPageState.tabTarget;
566
- let priorSessionTabTargetUnknown = priorSessionPageState.tabTargetUnknown;
567
- const sessionTabPinningReason = priorSessionPageState.pinningReason;
568
- let priorRefSnapshotState = priorSessionPageState.refSnapshot;
569
- let priorRefSnapshotInvalidation = priorSessionPageState.refSnapshotInvalidation;
570
- const confirmedCapture = sessionStateKey ? sessionPageState.getReadConfirmation(sessionStateKey) : undefined;
571
- // ponytail: reuse the approved capture for one call; DOM-only renames after that sample are not resampled on this use.
572
- const reuseConfirmedCapture = confirmedCapture?.refSnapshotFresh === true;
573
- if (reuseConfirmedCapture && confirmedCapture) {
574
- const consumed = { ...confirmedCapture };
575
- delete consumed.refSnapshotFresh;
576
- sessionPageState.applyReadConfirmation(consumed, options.sessionPageStateUpdate);
577
- state.observedBrowserEffects = { ...state.observedBrowserEffects, readConfirmation: consumed };
578
- }
579
- let nativeGenerationChanged = false;
580
- if (!browserIndependent && !isCloseCommand(executionPlan.commandInfo.command) && priorRefSnapshotState?.refIds.length && sessionStateKey && executionPlan.sessionName) {
581
- const daemon = await inspectManagedSessionDaemon({ cwd, namespace: executionPlan.namespace, sessionName: executionPlan.sessionName, signal, includeGeneration: true, headedManagedAutosaveInterval: ownedManagedSession?.headedManagedAutosaveInterval ?? (ownedManagedSession?.headedManagedAutosaveDisabled ? "0" : undefined), timeoutMs: params.timeoutMs });
582
- sessionPageState.bindSnapshotGeneration(sessionStateKey, daemon.status === "active" ? daemon.generation : undefined);
583
- if (daemon.status !== "active" || daemon.generation === undefined || priorRefSnapshotState.generation !== daemon.generation) {
584
- nativeGenerationChanged = daemon.status === "active" && daemon.generation !== undefined && priorRefSnapshotState.generation !== undefined && priorRefSnapshotState.generation !== daemon.generation;
585
- priorRefSnapshotState = undefined;
586
- priorRefSnapshotInvalidation = buildPageTransitionRefSnapshotInvalidation("The native browser generation changed or could not be verified. Take a new complete snapshot before using refs, even when the URL is unchanged.");
587
- sessionPageState.applyRefSnapshotInvalidation({ invalidation: priorRefSnapshotInvalidation, sessionName: sessionStateKey, update: options.sessionPageStateUpdate });
588
- }
589
- }
590
- const coldManagedSession = !browserIndependent && (managedSessionDaemonInactive || nativeGenerationChanged || priorSessionPageState.tabReopenPending === true)
591
- && recordedOwnedSession !== undefined
592
- && sessionTabPinningReason === "restore"
593
- && ownedManagedSession?.restoreDecision === "enabled"
594
- && !managedSessionRestoreDisabled()
595
- && !options.preserveAttachedBrowserSession;
596
- if (coldManagedSession && sessionStateKey) {
597
- sessionPageState.setTabReopenPending({ pending: true, sessionName: sessionStateKey, update: options.sessionPageStateUpdate });
598
- priorRefSnapshotState = undefined;
599
- priorRefSnapshotInvalidation = buildPageTransitionRefSnapshotInvalidation("The managed browser shut down. Reopening its URL reloads the page; run snapshot -i before using page-scoped refs.");
600
- sessionPageState.applyRefSnapshotInvalidation({ invalidation: priorRefSnapshotInvalidation, sessionName: sessionStateKey, update: options.sessionPageStateUpdate });
601
- }
602
- let semanticActionVisibleRefResolution;
603
- let livePageVerified = false;
604
- let sessionTabCorrection;
605
- let sessionTabSelectionError;
606
- const plannedCommandTokens = extractUpstreamCommandTokens(preparedArgs.args);
607
- const knownStaleRef = buildStaleRefPreflight({ commandTokens: plannedCommandTokens, currentTarget: priorSessionTabTarget, refSnapshot: priorRefSnapshotState, refSnapshotInvalidation: priorRefSnapshotInvalidation, stdin: runtimeToolStdin });
608
- const invalidStdin = validateStdinCommandContract({ command: executionPlan.commandInfo.command, commandTokens: plannedCommandTokens, stdin: runtimeToolStdin });
609
- const pinSessionTab = shouldPinSessionTabForCommand({
610
- command: executionPlan.commandInfo.command,
611
- commandTokens: plannedCommandTokens,
612
- // URL QA clears diagnostics before its explicit open; those clears do not need the old tab.
613
- pinningRequired: !readConfirmation && sessionTabPinningReason !== undefined && compiledQaPreset?.checks.url === undefined,
614
- reopenPending: coldManagedSession,
615
- sessionName: executionPlan.sessionName,
616
- stdin: runtimeToolStdin,
617
- });
618
- if (!executionPlan.validationError && !executionPlan.plainTextInspection && !knownStaleRef && !invalidStdin && priorSessionTabTarget && pinSessionTab) {
619
- signal?.throwIfAborted();
620
- const reopenedData = coldManagedSession ? await runSessionCommandData({
621
- args: ["open", priorSessionTabTarget.url], cwd, namespace: executionPlan.namespace, sessionName: executionPlan.sessionName, signal, timeoutMs: params.timeoutMs,
622
- onProcessResult: ({ agentBrowserStarted }) => {
623
- // A started open may have navigated even if its CLI was aborted before replying.
624
- if (agentBrowserStarted && sessionStateKey)
625
- sessionPageState.setTabReopenPending({ pending: false, sessionName: sessionStateKey, update: options.sessionPageStateUpdate });
626
- },
627
- }) : undefined;
628
- const reopened = !coldManagedSession || reopenedData !== undefined;
629
- if (coldManagedSession && reopened)
630
- priorSessionTabTarget = {
631
- ...priorSessionTabTarget,
632
- targetId: isRecord(reopenedData) && typeof reopenedData.targetId === "string" ? reopenedData.targetId : undefined,
633
- };
634
- const selection = signal?.aborted ? undefined : reopened
635
- ? await ensureSessionTabTarget({ cwd, namespace: executionPlan.namespace, sessionName: executionPlan.sessionName, signal, target: priorSessionTabTarget })
636
- : { error: "agent-browser could not reopen the remembered URL after the managed browser shut down. Navigate explicitly, then run snapshot -i before retrying." };
637
- if (coldManagedSession && signal?.aborted) {
638
- const errorText = "agent_browser was aborted while reopening the remembered page. The requested command did not run.";
639
- return { kind: "early-result", result: {
640
- content: [{ type: "text", text: errorText }],
641
- details: {
642
- aborted: true, args: redactedArgs, command: executionPlan.commandInfo.command,
643
- effectiveArgs: redactInvocationArgs(executionPlan.effectiveArgs), sessionMode,
644
- ...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
645
- ...buildAgentBrowserResultCategoryDetails({ args: redactedArgs, command: executionPlan.commandInfo.command, errorText, failureCategory: "aborted", succeeded: false }),
646
- },
647
- isError: true,
648
- } };
649
- }
650
- signal?.throwIfAborted();
651
- sessionTabCorrection = selection?.correction;
652
- sessionTabSelectionError = selection?.error;
653
- if (selection?.error)
654
- executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: selection.error };
655
- }
656
- const isCallerOwnedExplicitSession = () => executionPlan.sessionName !== undefined
657
- && executionPlan.usedImplicitSession === false
658
- && ownedManagedSession === undefined;
659
- const requiresLivePageVerification = () => !readConfirmation && (reuseConfirmedCapture || isCallerOwnedExplicitSession() || options.preserveAttachedBrowserSession === true);
660
- const verifyLivePage = async (request) => {
661
- if (!request.requirement || !executionPlan.sessionName)
662
- return;
663
- if (options.establishAttachedBrowserSession) {
664
- executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: request.requirement };
665
- return;
666
- }
667
- let liveUrl;
668
- try {
669
- const liveUrlData = await runSessionCommandData({
670
- args: ["get", "url"],
671
- cwd,
672
- namespace: executionPlan.namespace,
673
- sessionName: executionPlan.sessionName,
674
- signal,
675
- throwOnFailure: true,
676
- });
677
- liveUrl = extractStringResultField(liveUrlData, "result") ?? extractStringResultField(liveUrlData, "url");
678
- }
679
- catch (error) {
680
- if (signal?.aborted)
681
- throw signal.reason ?? error;
682
- }
683
- if (liveUrl === undefined) {
684
- executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: request.requirement };
685
- return;
686
- }
687
- const livePageValidationError = getPageTargetValidationError({
688
- args: request.args,
689
- currentPageUrl: liveUrl,
690
- pageUrlUnknown: false,
691
- stdin: request.stdin,
692
- });
693
- if (livePageValidationError) {
694
- executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: livePageValidationError };
695
- return;
696
- }
697
- livePageVerified = true;
698
- priorSessionTabTarget = priorSessionTabTarget?.url === liveUrl
699
- ? { ...priorSessionTabTarget, url: liveUrl }
700
- : { url: liveUrl };
701
- priorSessionTabTargetUnknown = undefined;
702
- };
703
- const hasPotentialLiveSemanticSession = state.managedSessionActive || priorSessionTabTarget !== undefined || isCallerOwnedExplicitSession() || options.preserveAttachedBrowserSession === true;
704
- const mayResolveSemanticVisibleRef = executionPlan.managedSessionName !== freshSessionName && hasPotentialLiveSemanticSession && canResolveSemanticVisibleRef(compiledSemanticAction);
705
- if (!executionPlan.validationError && mayResolveSemanticVisibleRef && requiresLivePageVerification()) {
706
- await verifyLivePage({
707
- args: ["snapshot", "-i"],
708
- requirement: getExplicitSessionPageVerificationRequirement({ args: ["snapshot", "-i"] }),
709
- });
710
- }
711
- if (!executionPlan.validationError && mayResolveSemanticVisibleRef) {
712
- semanticActionVisibleRefResolution = await resolveSemanticActionVisibleRefArgs({
713
- compiled: compiledSemanticAction,
714
- cwd,
715
- namespace: executionPlan.namespace,
716
- refSnapshot: reuseConfirmedCapture && !priorSessionTabTargetUnknown && !priorRefSnapshotInvalidation ? priorRefSnapshotState : undefined,
717
- sessionName: executionPlan.sessionName,
718
- signal,
719
- });
720
- }
721
- if (!executionPlan.validationError && requiresResolvedSemanticVisibleRef(compiledSemanticAction) && !semanticActionVisibleRefResolution) {
722
- const freshLocatorError = executionPlan.managedSessionName === freshSessionName
723
- ? "semanticAction select with locator cannot resolve a current @ref in sessionMode fresh. Open the page first, then reuse that session, or pass selector plus value/values."
724
- : undefined;
725
- executionPlan = {
726
- ...executionPlan,
727
- validationError: freshLocatorError ?? (hasPotentialLiveSemanticSession
728
- ? "semanticAction select with locator could not resolve to exactly one current visible combobox/listbox ref. Run snapshot -i and retry with selector or a more specific role/name."
729
- : "semanticAction select with locator requires an active browser session so the wrapper can resolve a current @ref; open a page first or pass selector plus value/values."),
730
- };
731
- }
732
- if (semanticActionVisibleRefResolution) {
733
- executionPlan = buildExecutionPlan(semanticActionVisibleRefResolution.args, {
734
- freshSessionName,
735
- managedSessionActive: state.managedSessionActive,
736
- managedSessionCompatibilityWorkaround: state.managedSessionCompatibilityWorkaround,
737
- managedSessionName: state.managedSessionName,
738
- managedSessionNamespace: state.managedSessionNamespace,
739
- sessionMode,
740
- });
741
- }
742
- const commandTokens = semanticActionVisibleRefResolution ? extractUpstreamCommandTokens(semanticActionVisibleRefResolution.args) : extractUpstreamCommandTokens(preparedArgs.args);
743
- const unsupportedScrollIntoViewRecovery = executionPlan.validationError || executionPlan.plainTextInspection
744
- ? undefined
745
- : [commandTokens, ...getUpstreamEffectiveBatchSteps(commandTokens, runtimeToolStdin)]
746
- .map((tokens) => buildUnsupportedScrollIntoViewRecovery({ commandTokens: tokens, sessionName: executionPlan.sessionName }))
747
- .find((recovery) => recovery !== undefined);
748
- if (unsupportedScrollIntoViewRecovery)
749
- executionPlan = { ...executionPlan, recoveryHint: undefined, validationError: unsupportedScrollIntoViewRecovery.error };
750
- const resolvedSemanticActionRefSnapshot = semanticActionVisibleRefResolution?.snapshot
751
- ? { ...semanticActionVisibleRefResolution.snapshot, target: semanticActionVisibleRefResolution.snapshot.target ?? priorSessionTabTarget }
752
- : undefined;
753
- const preLiveStaleRefPreflight = buildStaleRefPreflight({
754
- commandTokens,
755
- currentTarget: priorSessionTabTarget,
756
- refSnapshot: resolvedSemanticActionRefSnapshot ?? priorRefSnapshotState,
757
- refSnapshotInvalidation: resolvedSemanticActionRefSnapshot ? undefined : priorRefSnapshotInvalidation,
758
- stdin: runtimeToolStdin,
759
- });
760
- const livePageAccessEligible = !executionPlan.validationError
761
- && preLiveStaleRefPreflight === undefined
762
- && validateStdinCommandContract({ command: executionPlan.commandInfo.command, commandTokens, stdin: runtimeToolStdin }) === undefined
763
- && requiresLivePageVerification();
764
- const livePageRequirement = livePageAccessEligible
765
- && !livePageVerified
766
- ? getExplicitSessionPageVerificationRequirement({
767
- args: executionPlan.effectiveArgs,
768
- stdin: runtimeToolStdin,
769
- })
770
- : undefined;
771
- await verifyLivePage({
772
- args: executionPlan.effectiveArgs,
773
- requirement: livePageRequirement,
774
- stdin: runtimeToolStdin,
775
- });
776
- const redactedEffectiveArgs = redactInvocationArgs(prepareAgentBrowserSpawnArgs(executionPlan.effectiveArgs, undefined, options.preserveAttachedBrowserSession, chromeStartupArgs));
777
- const redactedRecoveryHint = redactRecoveryHint(executionPlan.recoveryHint);
778
- const compatibilityWorkaround = executionPlan.compatibilityWorkaround;
779
- const statePatch = executionPlan.managedSessionName === freshSessionName
780
- ? { freshSessionOrdinal: freshSessionOrdinal + 1 }
781
- : {};
782
- if (executionPlan.managedSessionName === freshSessionName) {
783
- freshSessionOrdinal += 1;
784
- }
785
- if (executionPlan.validationError) {
786
- const nextActions = applyNamespaceToNextActions(sessionTabSelectionError ? buildSessionTabRecoveryNextActions({ kind: "tab-drift", resultCategory: "failure", sessionName: executionPlan.sessionName, tabCorrection: sessionTabCorrection, target: priorSessionTabTarget }) : unsupportedScrollIntoViewRecovery?.nextActions, executionPlan.namespace);
787
- const nextActionsText = formatAgentBrowserNextActionsText(nextActions);
788
- return { kind: "early-result", statePatch, result: {
789
- content: [{ type: "text", text: [executionPlan.validationError, nextActionsText].filter((text) => text !== undefined).join("\n\n") }],
790
- details: {
791
- args: redactedArgs,
792
- compiledElectron: redactedCompiledElectron,
793
- compiledJob: redactedCompiledJob,
794
- compiledQaPreset: redactedCompiledQaPreset,
795
- compiledSourceLookup: redactedCompiledSourceLookup,
796
- compiledNetworkSourceLookup: redactedCompiledNetworkSourceLookup,
797
- invalidValueFlag: executionPlan.invalidValueFlag,
798
- managedSessionCleanupOnlyReason,
799
- ...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
800
- ...(managedSessionCleanupOnlyReason ? { namespace: ownedManagedSession?.namespace ?? "" } : {}),
801
- nextActions,
802
- sessionMode,
803
- sessionRecoveryHint: redactedRecoveryHint,
804
- startupScopedFlags: executionPlan.startupScopedFlags,
805
- ...(sessionTabSelectionError ? { effectiveArgs: redactedEffectiveArgs, sessionTabCorrection } : {}),
806
- ...(coldManagedSession ? { refSnapshotInvalidation: priorRefSnapshotInvalidation } : {}),
807
- ...buildAgentBrowserResultCategoryDetails({ args: redactedArgs, command: executionPlan.commandInfo.command, errorText: executionPlan.validationError, failureCategory: sessionTabSelectionError ? "tab-drift" : undefined, succeeded: false, validationError: executionPlan.validationError }),
808
- validationError: executionPlan.validationError,
809
- },
810
- isError: true,
811
- } };
812
- }
813
- const exactSensitiveValues = getExactSensitiveStdinValues({
814
- command: executionPlan.commandInfo.command,
815
- commandTokens,
816
- stdin: runtimeToolStdin,
817
- });
818
- const traceOwnerGuardMessage = getTraceOwnerGuardMessage({
819
- command: executionPlan.commandInfo.command,
820
- sessionName: sessionStateKey,
821
- subcommand: executionPlan.commandInfo.subcommand,
822
- traceOwners,
823
- });
824
- if (traceOwnerGuardMessage) {
825
- return { kind: "early-result", statePatch, result: {
826
- content: [{ type: "text", text: traceOwnerGuardMessage }],
827
- details: {
828
- args: redactedArgs,
829
- command: executionPlan.commandInfo.command,
830
- compatibilityWorkaround,
831
- effectiveArgs: redactedEffectiveArgs,
832
- sessionMode,
833
- ...buildAgentBrowserResultCategoryDetails({ args: redactedEffectiveArgs, command: executionPlan.commandInfo.command, errorText: traceOwnerGuardMessage, succeeded: false, validationError: traceOwnerGuardMessage }),
834
- validationError: traceOwnerGuardMessage,
835
- ...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
836
- },
837
- isError: true,
838
- } };
839
- }
840
- const stdinValidationError = validateStdinCommandContract({
841
- command: executionPlan.commandInfo.command,
842
- commandTokens,
843
- stdin: runtimeToolStdin,
844
- });
845
- if (stdinValidationError) {
846
- return { kind: "early-result", statePatch, result: {
847
- content: [{ type: "text", text: stdinValidationError }],
848
- details: {
849
- args: redactedArgs,
850
- command: executionPlan.commandInfo.command,
851
- compatibilityWorkaround,
852
- effectiveArgs: redactedEffectiveArgs,
853
- sessionMode,
854
- ...buildAgentBrowserResultCategoryDetails({ args: redactedEffectiveArgs, command: executionPlan.commandInfo.command, errorText: stdinValidationError, succeeded: false, validationError: stdinValidationError }),
855
- validationError: stdinValidationError,
856
- ...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
857
- },
858
- isError: true,
859
- } };
860
- }
861
- const promptRefSnapshot = resolvedSemanticActionRefSnapshot ?? priorRefSnapshotState;
862
- const requestedArtifactCloseViolation = await findRequestedArtifactCloseViolation({ artifactManifest: state.artifactManifest, command: executionPlan.commandInfo.command, cwd, promptPolicy: options.promptPolicy });
863
- if (requestedArtifactCloseViolation) {
864
- return { kind: "early-result", statePatch, result: {
865
- content: [{ type: "text", text: requestedArtifactCloseViolation.message }],
866
- details: {
867
- args: redactedArgs,
868
- command: executionPlan.commandInfo.command,
869
- compatibilityWorkaround,
870
- effectiveArgs: redactedEffectiveArgs,
871
- promptGuard: requestedArtifactCloseViolation,
872
- sessionMode,
873
- ...buildAgentBrowserResultCategoryDetails({ args: redactedEffectiveArgs, command: executionPlan.commandInfo.command, errorText: requestedArtifactCloseViolation.message, failureCategory: "policy-blocked", succeeded: false, validationError: requestedArtifactCloseViolation.message }),
874
- validationError: requestedArtifactCloseViolation.message,
875
- ...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
876
- },
877
- isError: true,
878
- } };
879
- }
880
- const staleRefPreflight = buildStaleRefPreflight({
881
- commandTokens,
882
- currentTarget: priorSessionTabTarget,
883
- requireExactTargetUrl: reuseConfirmedCapture,
884
- refSnapshot: resolvedSemanticActionRefSnapshot ?? priorRefSnapshotState,
885
- refSnapshotInvalidation: resolvedSemanticActionRefSnapshot ? undefined : priorRefSnapshotInvalidation,
886
- stdin: runtimeToolStdin,
887
- });
888
- if (staleRefPreflight) {
889
- return { kind: "early-result", statePatch, result: {
890
- content: [{ type: "text", text: staleRefPreflight.message }],
891
- details: {
892
- args: redactedArgs,
893
- command: executionPlan.commandInfo.command,
894
- compatibilityWorkaround,
895
- effectiveArgs: redactedEffectiveArgs,
896
- nextActions: applyNamespaceToNextActions(buildSessionAwareStaleRefNextActions(executionPlan.sessionName), executionPlan.namespace),
897
- refIds: staleRefPreflight.refIds,
898
- refSnapshot: staleRefPreflight.snapshot,
899
- refSnapshotInvalidation: staleRefPreflight.snapshotInvalidation,
900
- sessionMode,
901
- ...buildAgentBrowserResultCategoryDetails({ args: redactedEffectiveArgs, command: executionPlan.commandInfo.command, errorText: staleRefPreflight.message, failureCategory: "stale-ref", succeeded: false }),
902
- ...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
903
- },
904
- isError: true,
905
- } };
906
- }
907
- const samePageRefFreshnessPreflight = await collectSamePageRefFreshnessPreflight({
908
- commandTokens,
909
- cwd,
910
- currentTarget: priorSessionTabTarget,
911
- previousSnapshot: resolvedSemanticActionRefSnapshot || reuseConfirmedCapture ? undefined : priorRefSnapshotState,
912
- stdin: runtimeToolStdin,
913
- namespace: executionPlan.namespace,
914
- sessionName: executionPlan.sessionName,
915
- signal,
916
- });
917
- if (samePageRefFreshnessPreflight) {
918
- if (samePageRefFreshnessPreflight.snapshot && sessionStateKey) {
919
- sessionPageState.applyRefSnapshot({ fallbackTarget: priorSessionTabTarget, sessionName: sessionStateKey, snapshot: samePageRefFreshnessPreflight.snapshot, update: options.sessionPageStateUpdate });
920
- }
921
- return { kind: "early-result", statePatch, result: {
922
- content: [{ type: "text", text: samePageRefFreshnessPreflight.message }],
923
- details: {
924
- args: redactedArgs,
925
- command: executionPlan.commandInfo.command,
926
- compatibilityWorkaround,
927
- effectiveArgs: redactedEffectiveArgs,
928
- nextActions: applyNamespaceToNextActions(buildSessionAwareStaleRefNextActions(executionPlan.sessionName), executionPlan.namespace),
929
- refIds: samePageRefFreshnessPreflight.refIds,
930
- refSnapshot: samePageRefFreshnessPreflight.snapshot,
931
- sessionMode,
932
- ...buildAgentBrowserResultCategoryDetails({ args: redactedEffectiveArgs, command: executionPlan.commandInfo.command, errorText: samePageRefFreshnessPreflight.message, failureCategory: "stale-ref", succeeded: false }),
933
- ...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
934
- },
935
- isError: true,
936
- } };
937
- }
938
- if (compiledQaPreset?.checks.attached) {
939
- const qaAttachedPrecondition = await validateQaAttachedPrecondition({
940
- cwd,
941
- namespace: executionPlan.namespace,
942
- sessionName: executionPlan.sessionName,
943
- signal,
944
- });
945
- if (qaAttachedPrecondition) {
946
- return { kind: "early-result", statePatch, result: {
947
- content: [{ type: "text", text: qaAttachedPrecondition.error }],
948
- details: {
949
- args: redactedArgs,
950
- compiledQaPreset: redactedCompiledQaPreset,
951
- compatibilityWorkaround,
952
- effectiveArgs: redactedEffectiveArgs,
953
- nextActions: applyNamespaceToNextActions(qaAttachedPrecondition.nextActions, executionPlan.namespace),
954
- sessionMode,
955
- ...buildAgentBrowserResultCategoryDetails({ args: redactedEffectiveArgs, command: executionPlan.commandInfo.command, errorText: qaAttachedPrecondition.error, succeeded: false, validationError: qaAttachedPrecondition.error }),
956
- validationError: qaAttachedPrecondition.error,
957
- ...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
958
- },
959
- isError: true,
960
- } };
961
- }
962
- }
963
- const persistentArtifactStore = getPersistentSessionArtifactStore(options.ctx);
964
- const snapshotFilter = await trySnapshotFilter({
965
- modelVisible: options.modelVisible,
966
- artifactManifest: state.artifactManifest,
967
- commandTokens,
968
- compatibilityWorkaround,
969
- cwd,
970
- effectiveArgs: redactedEffectiveArgs,
971
- managedSessionRestoreDisabled,
972
- persistentArtifactStore,
973
- previousRefSnapshot: priorRefSnapshotState,
974
- redactedArgs,
975
- namespace: executionPlan.namespace,
976
- sessionMode,
977
- sessionName: executionPlan.sessionName,
978
- sessionStateKey,
979
- sessionPageState,
980
- sessionPageStateUpdate: options.sessionPageStateUpdate,
981
- signal,
982
- usedImplicitSession: executionPlan.usedImplicitSession,
983
- });
984
- if (snapshotFilter) {
985
- if (sessionStateKey && executionPlan.sessionName) {
986
- const daemon = await inspectManagedSessionDaemon({ cwd, namespace: executionPlan.namespace, sessionName: executionPlan.sessionName, signal, includeGeneration: true, headedManagedAutosaveInterval: ownedManagedSession?.headedManagedAutosaveInterval ?? (ownedManagedSession?.headedManagedAutosaveDisabled ? "0" : undefined), timeoutMs: params.timeoutMs });
987
- sessionPageState.bindSnapshotGeneration(sessionStateKey, daemon.status === "active" ? daemon.generation : undefined);
988
- if (ownedManagedSession && daemon.status === "active" && daemon.generation)
989
- state.managedSessionRestoreState.recordDaemonRestoreKey(executionPlan.sessionName, executionPlan.namespace, daemon.restoreKey, daemon.generation);
990
- if (isRecord(snapshotFilter.result.details))
991
- snapshotFilter.result.details.refSnapshot = sessionPageState.get(sessionStateKey).refSnapshot;
992
- }
993
- return { kind: "early-result", statePatch: { ...statePatch, artifactManifest: snapshotFilter.artifactManifest ?? statePatch.artifactManifest }, result: snapshotFilter.result };
994
- }
995
- const networkRequestsPageFilter = await tryNetworkRequestsPageFilter({
996
- commandTokens,
997
- compatibilityWorkaround,
998
- cwd,
999
- effectiveArgs: redactedEffectiveArgs,
1000
- managedSessionRestoreDisabled,
1001
- redactedArgs,
1002
- sessionMode,
1003
- namespace: executionPlan.namespace,
1004
- sessionName: executionPlan.sessionName,
1005
- signal,
1006
- usedImplicitSession: executionPlan.usedImplicitSession,
1007
- });
1008
- if (networkRequestsPageFilter)
1009
- return { kind: "early-result", statePatch, result: networkRequestsPageFilter };
1010
- if (executionPlan.startupScopedFlags.length === 0) {
1011
- const containerScroll = await tryContainerScroll({
1012
- commandTokens,
1013
- compatibilityWorkaround,
1014
- cwd,
1015
- effectiveArgs: redactedEffectiveArgs,
1016
- managedSessionRestoreDisabled,
1017
- redactedArgs,
1018
- sessionMode,
1019
- namespace: executionPlan.namespace,
1020
- sessionName: executionPlan.sessionName,
1021
- signal,
1022
- usedImplicitSession: executionPlan.usedImplicitSession,
1023
- });
1024
- if (containerScroll)
1025
- return { kind: "early-result", statePatch, result: containerScroll };
1026
- const pageScrollTo = await tryPageScrollTo({
1027
- commandTokens,
1028
- compatibilityWorkaround,
1029
- cwd,
1030
- effectiveArgs: redactedEffectiveArgs,
1031
- managedSessionRestoreDisabled,
1032
- redactedArgs,
1033
- sessionMode,
1034
- namespace: executionPlan.namespace,
1035
- sessionName: executionPlan.sessionName,
1036
- signal,
1037
- usedImplicitSession: executionPlan.usedImplicitSession,
1038
- });
1039
- if (pageScrollTo)
1040
- return { kind: "early-result", statePatch, result: pageScrollTo };
1041
- }
1042
- const processArgs = executionPlan.effectiveArgs;
1043
- const processStdin = preparedArgs.stdin ?? runtimeToolStdin;
1044
- let readTimeoutPageUrl = priorSessionTabTarget?.url;
1045
- if (options.params.timeoutMs === undefined && readTimeoutPageUrl === undefined && executionPlan.sessionName && commandTimeoutNeedsActivePageUrl(commandTokens, processStdin)) {
1046
- try {
1047
- const data = await runSessionCommandData({ args: ["get", "url"], cwd, namespace: executionPlan.namespace, sessionName: executionPlan.sessionName, signal });
1048
- readTimeoutPageUrl = extractStringResultField(data, "result") ?? extractStringResultField(data, "url");
1049
- }
1050
- catch { }
1051
- }
1052
- const processTimeoutMs = options.params.timeoutMs ?? getDialogAwareProcessTimeoutMs(commandTokens, promptRefSnapshot, processStdin) ?? getCommandAwareProcessTimeoutMs(commandTokens, processStdin, readTimeoutPageUrl);
1053
- const clickDispatchProbe = compiledElectron === undefined
1054
- ? await prepareClickDispatchProbe({ commandTokens, cwd, namespace: executionPlan.namespace, refSnapshot: promptRefSnapshot, sessionName: executionPlan.sessionName, signal, timeoutMs: processTimeoutMs })
1055
- : undefined;
1056
- const redactedProcessArgs = redactInvocationArgs(prepareAgentBrowserSpawnArgs(processArgs, ownedManagedSession?.compatibilityUserAgent, options.preserveAttachedBrowserSession, chromeStartupArgs));
1057
- const scrollAmount = Number(commandTokens.find((token) => /^\d+(?:\.\d+)?$/.test(token)));
1058
- const shouldProbeScrollNoop = executionPlan.commandInfo.command === "scroll" && executionPlan.startupScopedFlags.length === 0 && (state.managedSessionActive || sessionMode === "fresh") && (!Number.isFinite(scrollAmount) || scrollAmount >= 500);
1059
- const scrollPositionBefore = shouldProbeScrollNoop
1060
- ? await collectScrollPositionSnapshot({ cwd, namespace: executionPlan.namespace, sessionName: executionPlan.sessionName, signal })
1061
- : undefined;
1062
- onUpdate?.({
1063
- content: [{ type: "text", text: `Running agent-browser ${buildInvocationPreview(redactedProcessArgs)}` }],
1064
- details: {
1065
- compatibilityWorkaround,
1066
- effectiveArgs: redactedProcessArgs,
1067
- sessionMode,
1068
- sessionTabCorrection,
1069
- ...buildSessionDetailFields(executionPlan.sessionName, executionPlan.usedImplicitSession, executionPlan.namespace, managedSessionRestoreDisabled()),
1070
- },
1071
- });
1072
- managedSessionPolicyLockTransferred = true;
1073
- electronLaunchTransferred = true;
1074
- return {
1075
- kind: "ready",
1076
- prepared: {
1077
- chromeStartupArgs,
1078
- commandTokens,
1079
- headedLaunch,
1080
- providerLaunch,
1081
- managedSessionPolicyLock,
1082
- compiledElectron,
1083
- compiledJob,
1084
- compiledNetworkSourceLookup,
1085
- compiledQaPreset,
1086
- compiledSemanticAction,
1087
- compiledSourceLookup,
1088
- compatibilityWorkaround,
1089
- clickDispatchProbe,
1090
- electronLaunch,
1091
- exactSensitiveValues,
1092
- executionPlan,
1093
- ownedManagedSessionContext: ownedManagedSession,
1094
- preparedArgs,
1095
- readConfirmation,
1096
- priorRefSnapshotState,
1097
- priorSessionTabTarget,
1098
- priorSessionTabTargetUnknown,
1099
- processArgs,
1100
- processStdin,
1101
- processTimeoutMs,
1102
- redactedArgs,
1103
- redactedCompiledElectron,
1104
- redactedCompiledJob,
1105
- redactedCompiledNetworkSourceLookup,
1106
- redactedCompiledQaPreset,
1107
- redactedCompiledSemanticAction: semanticActionVisibleRefResolution && redactedCompiledSemanticAction?.action === "select"
1108
- ? { ...redactedCompiledSemanticAction, args: redactInvocationArgs(semanticActionVisibleRefResolution.args) }
1109
- : redactedCompiledSemanticAction,
1110
- redactedCompiledSourceLookup,
1111
- redactedEffectiveArgs,
1112
- redactedProcessArgs,
1113
- redactedRecoveryHint,
1114
- resolvedSemanticActionRefSnapshot,
1115
- runtimeToolArgs,
1116
- runtimeToolStdin,
1117
- scrollPositionBefore,
1118
- sessionMode,
1119
- sessionTabCorrection,
1120
- sessionTabPinningReason,
1121
- shouldProbeScrollNoop,
1122
- statePatch,
1123
- userRequestedJson,
1124
- },
1125
- };
1126
- }));
173
+ ownedSessions: state.ownedManagedSessions,
174
+ }, sessionFacts, artifacts.preparedArgs, { ...request, cwd: options.cwd, idleTimeoutMs: options.implicitSessionIdleTimeoutMs });
175
+ const planning = await prepareDaemonPolicy(controls, findElectronLaunchRecordForSession(initial.plan.sessionName, state.electronLaunchRecords, initial.plan.namespace), initial);
176
+ policy = planning.policy;
177
+ const chromeStartupArgs = await prepareChromeStartupArgs({
178
+ ...controls,
179
+ chromeStartupArgs: options.input.chromeStartupArgs,
180
+ configuredChromeLaunch: options.input.configuredChromeLaunch,
181
+ daemonInactive: options.daemonInactive,
182
+ }, planning, { preparedArgs: artifacts.preparedArgs, stdin: request.stdin });
183
+ const result = await withChromeStartupArgs(chromeStartupArgs, () => withOwnedManagedSessionContext(planning.session.ownedManagedSession, () => preparePagePhases(state, controls, planning, {
184
+ ...request,
185
+ preparedArgs: artifacts.preparedArgs,
186
+ chromeStartupArgs,
187
+ update: options.sessionPageStateUpdate,
188
+ sessionFacts,
189
+ })));
190
+ transferred = result.kind === "ready";
191
+ return result;
1127
192
  }
1128
193
  finally {
1129
- if (!managedSessionPolicyLockTransferred)
1130
- await managedSessionPolicyLock?.release();
1131
- if (electronLaunch && !electronLaunchTransferred) {
1132
- try {
1133
- const cleanup = await cleanupElectronLaunchResources({
1134
- child: electronLaunch.child,
1135
- record: electronLaunch.record,
1136
- timeoutMs: options.implicitSessionCloseTimeoutMs,
1137
- });
1138
- if (cleanup.partial) {
1139
- state.electronLaunchRecords.set(cleanup.launchId, cleanup.record);
1140
- state.electronChildProcesses.set(cleanup.launchId, electronLaunch.child);
1141
- }
1142
- }
1143
- catch {
1144
- state.electronLaunchRecords.set(electronLaunch.record.launchId, electronLaunch.record);
1145
- state.electronChildProcesses.set(electronLaunch.record.launchId, electronLaunch.child);
1146
- }
194
+ if (!transferred) {
195
+ await cleanupPreparationResources(state, {
196
+ lock: policy?.lock,
197
+ electronLaunch: request.electronLaunch,
198
+ timeoutMs: options.implicitSessionCloseTimeoutMs,
199
+ });
1147
200
  }
1148
201
  }
1149
202
  }