pi-agent-browser-native 0.9.3 → 0.9.4

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 (391) hide show
  1. package/CHANGELOG.md +77 -5
  2. package/README.md +103 -81
  3. package/dist/extensions/agent-browser/index.js +43057 -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 +218 -0
  33. package/dist/extensions/agent-browser/lib/config.js +19 -7
  34. package/dist/extensions/agent-browser/lib/electron/cdp.js +15 -7
  35. package/dist/extensions/agent-browser/lib/electron/cleanup.js +134 -55
  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 +89 -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 +249 -354
  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/input-modes/electron.js +162 -121
  50. package/dist/extensions/agent-browser/lib/input-modes/job.js +116 -313
  51. package/dist/extensions/agent-browser/lib/input-modes/lookup-network-evidence.js +104 -0
  52. package/dist/extensions/agent-browser/lib/input-modes/lookup-plan.js +132 -0
  53. package/dist/extensions/agent-browser/lib/input-modes/lookup-redaction.js +57 -0
  54. package/dist/extensions/agent-browser/lib/input-modes/lookup-source-evidence.js +151 -0
  55. package/dist/extensions/agent-browser/lib/input-modes/lookup-workspace.js +142 -0
  56. package/dist/extensions/agent-browser/lib/input-modes/lookups.js +57 -412
  57. package/dist/extensions/agent-browser/lib/input-modes/params.js +63 -17
  58. package/dist/extensions/agent-browser/lib/input-modes/qa-analysis.js +268 -0
  59. package/dist/extensions/agent-browser/lib/input-modes/qa-presentation.js +117 -0
  60. package/dist/extensions/agent-browser/lib/input-modes/script-child.js +396 -0
  61. package/dist/extensions/agent-browser/lib/input-modes/script-protocol.js +86 -0
  62. package/dist/extensions/agent-browser/lib/input-modes/script-types.js +1 -0
  63. package/dist/extensions/agent-browser/lib/input-modes/script-validation.js +60 -0
  64. package/dist/extensions/agent-browser/lib/input-modes/script.js +60 -409
  65. package/dist/extensions/agent-browser/lib/input-modes/semantic-action.js +218 -128
  66. package/dist/extensions/agent-browser/lib/input-modes/shared.js +15 -4
  67. package/dist/extensions/agent-browser/lib/input-modes/types.js +56 -7
  68. package/dist/extensions/agent-browser/lib/json-schema.js +22 -10
  69. package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +17 -5
  70. package/dist/extensions/agent-browser/lib/managed-session-policy-lock.js +92 -425
  71. package/dist/extensions/agent-browser/lib/managed-session-posix-storage.js +58 -0
  72. package/dist/extensions/agent-browser/lib/managed-session-project-identity.js +244 -0
  73. package/dist/extensions/agent-browser/lib/managed-session-restore-context.js +84 -0
  74. package/dist/extensions/agent-browser/lib/managed-session-restore-policy.js +119 -0
  75. package/dist/extensions/agent-browser/lib/managed-session-restore-state.js +83 -0
  76. package/dist/extensions/agent-browser/lib/managed-session-restore.js +168 -300
  77. package/dist/extensions/agent-browser/lib/managed-session-snapshot-records.js +277 -0
  78. package/dist/extensions/agent-browser/lib/managed-session-snapshots.js +128 -305
  79. package/dist/extensions/agent-browser/lib/managed-session-storage.js +56 -253
  80. package/dist/extensions/agent-browser/lib/native-confirmation.js +140 -0
  81. package/dist/extensions/agent-browser/lib/native-output.js +43 -9
  82. package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +106 -59
  83. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-merge.js +14 -6
  84. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +109 -57
  85. package/dist/extensions/agent-browser/lib/orchestration/browser-run/browser-observation-result.js +82 -0
  86. package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +164 -60
  87. package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostic-values.js +31 -0
  88. package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +152 -781
  89. package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-observation.js +202 -0
  90. package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-text-diagnostics.js +109 -0
  91. package/dist/extensions/agent-browser/lib/orchestration/browser-run/fill-diagnostics.js +119 -0
  92. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-action-recovery.js +147 -0
  93. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-actions.js +144 -0
  94. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-content.js +123 -0
  95. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-contracts.js +1 -0
  96. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-details.js +156 -0
  97. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-electron.js +179 -0
  98. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-evidence.js +39 -0
  99. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-missing-binary.js +89 -0
  100. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-recovery.js +97 -0
  101. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-redaction.js +106 -0
  102. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-timeout.js +110 -0
  103. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +41 -538
  104. package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +199 -154
  105. package/dist/extensions/agent-browser/lib/orchestration/browser-run/interaction-diagnostics.js +290 -0
  106. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-close.js +167 -0
  107. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-inspection.js +108 -0
  108. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +127 -205
  109. package/dist/extensions/agent-browser/lib/orchestration/browser-run/native-helper-observation.js +65 -0
  110. package/dist/extensions/agent-browser/lib/orchestration/browser-run/observation-types.js +1 -0
  111. package/dist/extensions/agent-browser/lib/orchestration/browser-run/overlay-diagnostics.js +120 -0
  112. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.js +113 -30
  113. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.js +109 -28
  114. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter-data.js +150 -0
  115. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +138 -253
  116. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-rendered-text.js +147 -0
  117. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.js +59 -24
  118. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-artifacts.js +159 -0
  119. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-command.js +131 -0
  120. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-contracts.js +1 -0
  121. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-daemon.js +93 -0
  122. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-failure.js +42 -0
  123. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-guards.js +242 -0
  124. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-input.js +75 -0
  125. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-observations.js +92 -0
  126. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-selection.js +254 -0
  127. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-state.js +121 -0
  128. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-refs.js +130 -0
  129. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-resources.js +114 -0
  130. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-semantic.js +121 -0
  131. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-session-plan.js +222 -0
  132. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-timeouts.js +68 -0
  133. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +176 -1123
  134. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-analysis.js +191 -0
  135. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-confirmation.js +152 -0
  136. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-diagnostics.js +182 -0
  137. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-electron.js +150 -0
  138. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-contracts.js +1 -0
  139. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase-contracts.js +1 -0
  140. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase.js +115 -0
  141. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle.js +256 -0
  142. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed-contracts.js +1 -0
  143. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed.js +256 -0
  144. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase-contracts.js +1 -0
  145. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase.js +93 -0
  146. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native.js +113 -0
  147. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation-contracts.js +1 -0
  148. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation.js +316 -0
  149. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-ownership.js +28 -0
  150. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase-contracts.js +1 -0
  151. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase.js +142 -0
  152. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation-contracts.js +1 -0
  153. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation.js +333 -0
  154. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase-contracts.js +1 -0
  155. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase.js +71 -0
  156. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication.js +201 -0
  157. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-receipts.js +183 -0
  158. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-refs.js +200 -0
  159. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-tabs.js +142 -0
  160. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +18 -968
  161. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prompt-guards.js +23 -13
  162. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-receipt-reconciliation.js +198 -0
  163. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-contracts.js +1 -0
  164. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-presentation.js +154 -0
  165. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery.js +68 -151
  166. package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-capture.js +14 -0
  167. package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-observation.js +169 -46
  168. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-commands.js +130 -0
  169. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-electron.js +210 -0
  170. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-observations.js +61 -0
  171. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-outcomes.js +187 -0
  172. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-refs.js +171 -0
  173. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-tabs.js +228 -0
  174. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +77 -765
  175. package/dist/extensions/agent-browser/lib/orchestration/browser-run/text-visibility-diagnostics.js +182 -0
  176. package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-diagnostics.js +256 -0
  177. package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-progress.js +108 -0
  178. package/dist/extensions/agent-browser/lib/orchestration/code-artifact-observation.js +39 -0
  179. package/dist/extensions/agent-browser/lib/orchestration/code-image-observation.js +119 -0
  180. package/dist/extensions/agent-browser/lib/orchestration/electron-host/branch.js +92 -0
  181. package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup-result.js +58 -0
  182. package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup.js +78 -0
  183. package/dist/extensions/agent-browser/lib/orchestration/electron-host/contracts.js +1 -0
  184. package/dist/extensions/agent-browser/lib/orchestration/electron-host/discovery.js +106 -0
  185. package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +48 -821
  186. package/dist/extensions/agent-browser/lib/orchestration/electron-host/policy.js +86 -0
  187. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-collection.js +69 -0
  188. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-data.js +167 -0
  189. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-presentation.js +164 -0
  190. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe.js +161 -0
  191. package/dist/extensions/agent-browser/lib/orchestration/electron-host/status.js +165 -0
  192. package/dist/extensions/agent-browser/lib/orchestration/execution-queue.js +21 -9
  193. package/dist/extensions/agent-browser/lib/orchestration/extension-artifact-preflight.js +211 -0
  194. package/dist/extensions/agent-browser/lib/orchestration/extension-artifacts.js +23 -0
  195. package/dist/extensions/agent-browser/lib/orchestration/extension-attachment-replay.js +99 -0
  196. package/dist/extensions/agent-browser/lib/orchestration/extension-branch-restore.js +275 -0
  197. package/dist/extensions/agent-browser/lib/orchestration/extension-code.js +280 -0
  198. package/dist/extensions/agent-browser/lib/orchestration/extension-command-admission.js +303 -0
  199. package/dist/extensions/agent-browser/lib/orchestration/extension-command-output.js +36 -0
  200. package/dist/extensions/agent-browser/lib/orchestration/extension-command-result.js +335 -0
  201. package/dist/extensions/agent-browser/lib/orchestration/extension-command-run.js +227 -0
  202. package/dist/extensions/agent-browser/lib/orchestration/extension-command-state.js +1 -0
  203. package/dist/extensions/agent-browser/lib/orchestration/extension-electron-ownership.js +204 -0
  204. package/dist/extensions/agent-browser/lib/orchestration/extension-execution-locks.js +139 -0
  205. package/dist/extensions/agent-browser/lib/orchestration/extension-execution-queue.js +24 -0
  206. package/dist/extensions/agent-browser/lib/orchestration/extension-host-coordination.js +98 -0
  207. package/dist/extensions/agent-browser/lib/orchestration/extension-host-run.js +295 -0
  208. package/dist/extensions/agent-browser/lib/orchestration/extension-intent-replay.js +41 -0
  209. package/dist/extensions/agent-browser/lib/orchestration/extension-invocation.js +7 -0
  210. package/dist/extensions/agent-browser/lib/orchestration/extension-lifecycle.js +102 -0
  211. package/dist/extensions/agent-browser/lib/orchestration/extension-managed-ownership.js +133 -0
  212. package/dist/extensions/agent-browser/lib/orchestration/extension-observation.js +120 -0
  213. package/dist/extensions/agent-browser/lib/orchestration/extension-prompt.js +180 -0
  214. package/dist/extensions/agent-browser/lib/orchestration/extension-recording.js +290 -0
  215. package/dist/extensions/agent-browser/lib/orchestration/extension-resource-contracts.js +1 -0
  216. package/dist/extensions/agent-browser/lib/orchestration/extension-resource-replay.js +269 -0
  217. package/dist/extensions/agent-browser/lib/orchestration/extension-result-state.js +113 -0
  218. package/dist/extensions/agent-browser/lib/orchestration/extension-runtime.js +146 -0
  219. package/dist/extensions/agent-browser/lib/orchestration/extension-script-leases.js +58 -0
  220. package/dist/extensions/agent-browser/lib/orchestration/extension-tool-boundary.js +62 -0
  221. package/dist/extensions/agent-browser/lib/orchestration/extension-version-check.js +54 -0
  222. package/dist/extensions/agent-browser/lib/orchestration/input-plan-types.js +1 -0
  223. package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +261 -185
  224. package/dist/extensions/agent-browser/lib/orchestration/input-redaction.js +62 -0
  225. package/dist/extensions/agent-browser/lib/orchestration/native-config.js +144 -0
  226. package/dist/extensions/agent-browser/lib/orchestration/native-root-launch.js +77 -0
  227. package/dist/extensions/agent-browser/lib/orchestration/native-session-defaults.js +210 -157
  228. package/dist/extensions/agent-browser/lib/orchestration/operation-paths.js +124 -58
  229. package/dist/extensions/agent-browser/lib/orchestration/output-file.js +197 -99
  230. package/dist/extensions/agent-browser/lib/orchestration/script-mode.js +199 -96
  231. package/dist/extensions/agent-browser/lib/owned-managed-session-context.js +55 -0
  232. package/dist/extensions/agent-browser/lib/page-target-batch.js +118 -0
  233. package/dist/extensions/agent-browser/lib/page-target-guards.js +50 -0
  234. package/dist/extensions/agent-browser/lib/page-target-navigation.js +104 -0
  235. package/dist/extensions/agent-browser/lib/page-target-validation.js +55 -246
  236. package/dist/extensions/agent-browser/lib/parsing.js +13 -4
  237. package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +133 -68
  238. package/dist/extensions/agent-browser/lib/playbook.js +16 -12
  239. package/dist/extensions/agent-browser/lib/process-child.js +284 -0
  240. package/dist/extensions/agent-browser/lib/process-environment.js +13 -6
  241. package/dist/extensions/agent-browser/lib/process-errors.js +23 -0
  242. package/dist/extensions/agent-browser/lib/process-identity.js +47 -15
  243. package/dist/extensions/agent-browser/lib/process-socket-storage.js +256 -0
  244. package/dist/extensions/agent-browser/lib/process-stdout.js +74 -0
  245. package/dist/extensions/agent-browser/lib/process.js +145 -536
  246. package/dist/extensions/agent-browser/lib/prompt-artifacts.js +287 -0
  247. package/dist/extensions/agent-browser/lib/prompt-policy.js +15 -194
  248. package/dist/extensions/agent-browser/lib/read-command.js +41 -0
  249. package/dist/extensions/agent-browser/lib/read-confirmation.js +131 -68
  250. package/dist/extensions/agent-browser/lib/recording-reservations.js +118 -45
  251. package/dist/extensions/agent-browser/lib/redaction-fields.js +75 -0
  252. package/dist/extensions/agent-browser/lib/redaction-json.js +149 -0
  253. package/dist/extensions/agent-browser/lib/redaction-url.js +88 -0
  254. package/dist/extensions/agent-browser/lib/results/action-contracts.js +1 -0
  255. package/dist/extensions/agent-browser/lib/results/action-recommendations.js +28 -271
  256. package/dist/extensions/agent-browser/lib/results/artifact-contracts.js +1 -0
  257. package/dist/extensions/agent-browser/lib/results/artifact-manifest-validation.js +133 -0
  258. package/dist/extensions/agent-browser/lib/results/artifact-manifest.js +96 -94
  259. package/dist/extensions/agent-browser/lib/results/artifact-recommendations.js +73 -0
  260. package/dist/extensions/agent-browser/lib/results/categories.js +111 -54
  261. package/dist/extensions/agent-browser/lib/results/confirmation.js +29 -13
  262. package/dist/extensions/agent-browser/lib/results/editable-ref-evidence.js +62 -27
  263. package/dist/extensions/agent-browser/lib/results/electron-recommendations.js +83 -0
  264. package/dist/extensions/agent-browser/lib/results/envelope-decoding.js +48 -0
  265. package/dist/extensions/agent-browser/lib/results/envelope.js +90 -67
  266. package/dist/extensions/agent-browser/lib/results/evidence-contracts.js +1 -0
  267. package/dist/extensions/agent-browser/lib/results/failure-recommendations.js +180 -0
  268. package/dist/extensions/agent-browser/lib/results/network-routes.js +86 -45
  269. package/dist/extensions/agent-browser/lib/results/network.js +35 -12
  270. package/dist/extensions/agent-browser/lib/results/next-actions.js +49 -19
  271. package/dist/extensions/agent-browser/lib/results/presentation/artifact-files.js +320 -0
  272. package/dist/extensions/agent-browser/lib/results/presentation/artifact-format.js +138 -0
  273. package/dist/extensions/agent-browser/lib/results/presentation/artifact-images.js +113 -0
  274. package/dist/extensions/agent-browser/lib/results/presentation/artifact-verification.js +145 -0
  275. package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +99 -555
  276. package/dist/extensions/agent-browser/lib/results/presentation/batch-contracts.js +1 -0
  277. package/dist/extensions/agent-browser/lib/results/presentation/batch-recording.js +118 -0
  278. package/dist/extensions/agent-browser/lib/results/presentation/batch-redaction.js +68 -0
  279. package/dist/extensions/agent-browser/lib/results/presentation/batch-rendering.js +135 -0
  280. package/dist/extensions/agent-browser/lib/results/presentation/batch-step.js +227 -0
  281. package/dist/extensions/agent-browser/lib/results/presentation/batch-summary.js +91 -0
  282. package/dist/extensions/agent-browser/lib/results/presentation/batch.js +91 -460
  283. package/dist/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.js +9 -5
  284. package/dist/extensions/agent-browser/lib/results/presentation/command-presenters.js +216 -0
  285. package/dist/extensions/agent-browser/lib/results/presentation/common.js +26 -9
  286. package/dist/extensions/agent-browser/lib/results/presentation/content.js +86 -29
  287. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-a11y.js +67 -0
  288. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-health.js +79 -0
  289. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-identity.js +199 -0
  290. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-logs.js +75 -0
  291. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network-actions.js +216 -0
  292. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network.js +124 -0
  293. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-redaction.js +64 -0
  294. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-storage.js +209 -0
  295. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-stream.js +69 -0
  296. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-summary.js +222 -0
  297. package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +103 -1052
  298. package/dist/extensions/agent-browser/lib/results/presentation/early-result.js +70 -0
  299. package/dist/extensions/agent-browser/lib/results/presentation/errors.js +130 -60
  300. package/dist/extensions/agent-browser/lib/results/presentation/input-contracts.js +1 -0
  301. package/dist/extensions/agent-browser/lib/results/presentation/large-output.js +60 -145
  302. package/dist/extensions/agent-browser/lib/results/presentation/navigation.js +147 -88
  303. package/dist/extensions/agent-browser/lib/results/presentation/notices.js +75 -0
  304. package/dist/extensions/agent-browser/lib/results/presentation/observation-contracts.js +1 -0
  305. package/dist/extensions/agent-browser/lib/results/presentation/observation-rendering.js +127 -0
  306. package/dist/extensions/agent-browser/lib/results/presentation/outcomes.js +120 -0
  307. package/dist/extensions/agent-browser/lib/results/presentation/output-completion.js +77 -0
  308. package/dist/extensions/agent-browser/lib/results/presentation/output-spill.js +51 -0
  309. package/dist/extensions/agent-browser/lib/results/presentation/registry.js +116 -240
  310. package/dist/extensions/agent-browser/lib/results/presentation/semantic-action.js +35 -21
  311. package/dist/extensions/agent-browser/lib/results/presentation/skills.js +104 -73
  312. package/dist/extensions/agent-browser/lib/results/presentation/source.js +109 -0
  313. package/dist/extensions/agent-browser/lib/results/presentation.js +17 -261
  314. package/dist/extensions/agent-browser/lib/results/recommendation-contracts.js +1 -0
  315. package/dist/extensions/agent-browser/lib/results/recording.js +52 -14
  316. package/dist/extensions/agent-browser/lib/results/recovery-actions.js +14 -5
  317. package/dist/extensions/agent-browser/lib/results/recovery-next-actions.js +30 -22
  318. package/dist/extensions/agent-browser/lib/results/selector-recovery-target.js +83 -0
  319. package/dist/extensions/agent-browser/lib/results/selector-recovery.js +119 -119
  320. package/dist/extensions/agent-browser/lib/results/snapshot-compact.js +266 -0
  321. package/dist/extensions/agent-browser/lib/results/snapshot-content.js +32 -0
  322. package/dist/extensions/agent-browser/lib/results/snapshot-high-value-controls.js +104 -71
  323. package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +31 -11
  324. package/dist/extensions/agent-browser/lib/results/snapshot-segments.js +125 -66
  325. package/dist/extensions/agent-browser/lib/results/snapshot-spill.js +26 -7
  326. package/dist/extensions/agent-browser/lib/results/snapshot.js +28 -248
  327. package/dist/extensions/agent-browser/lib/results/text.js +16 -5
  328. package/dist/extensions/agent-browser/lib/runtime-args-validation.js +133 -0
  329. package/dist/extensions/agent-browser/lib/runtime-compatibility.js +81 -0
  330. package/dist/extensions/agent-browser/lib/runtime-contracts.js +1 -0
  331. package/dist/extensions/agent-browser/lib/runtime-redaction.js +118 -0
  332. package/dist/extensions/agent-browser/lib/runtime-replay-events.js +144 -0
  333. package/dist/extensions/agent-browser/lib/runtime-session-identity.js +76 -0
  334. package/dist/extensions/agent-browser/lib/runtime-session-plan.js +114 -0
  335. package/dist/extensions/agent-browser/lib/runtime-session-replay.js +123 -0
  336. package/dist/extensions/agent-browser/lib/runtime-tab-correction.js +65 -0
  337. package/dist/extensions/agent-browser/lib/runtime-timeouts.js +28 -0
  338. package/dist/extensions/agent-browser/lib/runtime.js +137 -1041
  339. package/dist/extensions/agent-browser/lib/session-identity.js +51 -0
  340. package/dist/extensions/agent-browser/lib/session-page-observation.js +357 -0
  341. package/dist/extensions/agent-browser/lib/session-page-state.js +178 -333
  342. package/dist/extensions/agent-browser/lib/session-page-types.js +1 -0
  343. package/dist/extensions/agent-browser/lib/temp-artifact-budget.js +78 -0
  344. package/dist/extensions/agent-browser/lib/temp-mutation-queue.js +7 -0
  345. package/dist/extensions/agent-browser/lib/temp-root-ownership.js +234 -0
  346. package/dist/extensions/agent-browser/lib/temp-root.js +207 -0
  347. package/dist/extensions/agent-browser/lib/temp.js +33 -446
  348. package/dist/extensions/agent-browser/lib/tool-surface.js +94 -24
  349. package/dist/extensions/agent-browser/lib/upstream-version.js +3 -2
  350. package/dist/extensions/agent-browser/lib/web-search-providers.js +229 -0
  351. package/dist/extensions/agent-browser/lib/web-search-request.js +108 -0
  352. package/dist/extensions/agent-browser/lib/web-search-results.js +281 -0
  353. package/dist/extensions/agent-browser/lib/web-search-schema.js +82 -0
  354. package/dist/extensions/agent-browser/lib/web-search.js +109 -617
  355. package/dist/extensions/agent-browser/lib/webmcp-observation.js +13 -6
  356. package/dist/extensions/agent-browser/lib/windows-stock-launcher.js +63 -37
  357. package/dist/extensions/agent-browser/script-worker.js +80 -43
  358. package/dist/scripts/agent-browser-target.mjs +4 -2
  359. package/docs/ARCHITECTURE.md +17 -5
  360. package/docs/CODE_QUALITY.md +242 -0
  361. package/docs/COMMAND_REFERENCE.md +251 -220
  362. package/docs/ELECTRON.md +53 -44
  363. package/docs/RELEASE.md +18 -15
  364. package/docs/REQUIREMENTS.md +1 -0
  365. package/docs/SUPPORT_MATRIX.md +76 -75
  366. package/docs/TOOL_CONTRACT.md +145 -116
  367. package/docs/platform-smoke.md +5 -5
  368. package/package.json +143 -120
  369. package/scripts/agent-browser-capability-baseline.mjs +361 -957
  370. package/scripts/agent-browser-target.mjs +6 -2
  371. package/scripts/build.mjs +37 -8
  372. package/scripts/capability-core-commands.mjs +193 -0
  373. package/scripts/capability-options.mjs +283 -0
  374. package/scripts/capability-samples.mjs +133 -0
  375. package/scripts/capability-section.mjs +11 -0
  376. package/scripts/config.mjs +213 -114
  377. package/scripts/convert-browser-session.mjs +30 -9
  378. package/scripts/doctor-sources.mjs +195 -0
  379. package/scripts/doctor.mjs +92 -247
  380. package/scripts/platform-smoke/artifacts.mjs +38 -11
  381. package/scripts/platform-smoke/commands.mjs +104 -0
  382. package/scripts/platform-smoke/crabbox-runner.mjs +167 -80
  383. package/scripts/platform-smoke/doctor-support.mjs +157 -0
  384. package/scripts/platform-smoke/doctor-windows.mjs +230 -0
  385. package/scripts/platform-smoke/doctor.mjs +212 -320
  386. package/scripts/platform-smoke/lease-evidence.mjs +134 -0
  387. package/scripts/platform-smoke/suite-checks.mjs +98 -0
  388. package/scripts/platform-smoke/suite-evidence.mjs +281 -0
  389. package/scripts/platform-smoke/targets.mjs +158 -472
  390. package/scripts/platform-smoke.mjs +55 -40
  391. 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
  }