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