pi-agent-browser-native 0.9.3 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (394) hide show
  1. package/CHANGELOG.md +106 -5
  2. package/README.md +58 -791
  3. package/dist/extensions/agent-browser/index.js +43101 -2031
  4. package/dist/extensions/agent-browser/lib/argv-descriptor.js +49 -26
  5. package/dist/extensions/agent-browser/lib/argv-grammar.js +82 -93
  6. package/dist/extensions/agent-browser/lib/bash-guard.js +129 -126
  7. package/dist/extensions/agent-browser/lib/batch-lifecycle.js +112 -51
  8. package/dist/extensions/agent-browser/lib/browser-execution-claim-codec.js +61 -0
  9. package/dist/extensions/agent-browser/lib/browser-execution-claim-storage.js +232 -0
  10. package/dist/extensions/agent-browser/lib/browser-execution-claims.js +202 -0
  11. package/dist/extensions/agent-browser/lib/browser-execution-identity.js +77 -0
  12. package/dist/extensions/agent-browser/lib/browser-journal-branch.js +98 -0
  13. package/dist/extensions/agent-browser/lib/browser-journal-contracts.js +1 -0
  14. package/dist/extensions/agent-browser/lib/browser-journal-projection.js +221 -0
  15. package/dist/extensions/agent-browser/lib/browser-journal-reader.js +89 -0
  16. package/dist/extensions/agent-browser/lib/browser-journal-replay.js +246 -0
  17. package/dist/extensions/agent-browser/lib/browser-journal.js +103 -394
  18. package/dist/extensions/agent-browser/lib/browser-legacy-pages.js +220 -0
  19. package/dist/extensions/agent-browser/lib/browser-legacy-projection.js +282 -0
  20. package/dist/extensions/agent-browser/lib/browser-legacy-types.js +1 -0
  21. package/dist/extensions/agent-browser/lib/browser-session-conversion-stream.js +217 -0
  22. package/dist/extensions/agent-browser/lib/browser-session-conversion.js +80 -335
  23. package/dist/extensions/agent-browser/lib/browser-transcript-contracts.js +35 -0
  24. package/dist/extensions/agent-browser/lib/browser-transcript-validation.js +166 -0
  25. package/dist/extensions/agent-browser/lib/browser-transcript.js +137 -82
  26. package/dist/extensions/agent-browser/lib/browser-value-parsing.js +15 -0
  27. package/dist/extensions/agent-browser/lib/command-capabilities.js +340 -0
  28. package/dist/extensions/agent-browser/lib/command-policy.js +107 -88
  29. package/dist/extensions/agent-browser/lib/command-taxonomy.js +49 -322
  30. package/dist/extensions/agent-browser/lib/config-policy.js +138 -343
  31. package/dist/extensions/agent-browser/lib/config-providers.js +71 -0
  32. package/dist/extensions/agent-browser/lib/config-validation.js +231 -0
  33. package/dist/extensions/agent-browser/lib/config.js +20 -8
  34. package/dist/extensions/agent-browser/lib/electron/cdp.js +20 -8
  35. package/dist/extensions/agent-browser/lib/electron/cleanup.js +128 -83
  36. package/dist/extensions/agent-browser/lib/electron/discovery-darwin.js +109 -0
  37. package/dist/extensions/agent-browser/lib/electron/discovery-desktop.js +136 -0
  38. package/dist/extensions/agent-browser/lib/electron/discovery-evidence.js +90 -0
  39. package/dist/extensions/agent-browser/lib/electron/discovery-linux.js +93 -0
  40. package/dist/extensions/agent-browser/lib/electron/discovery-packages.js +162 -0
  41. package/dist/extensions/agent-browser/lib/electron/discovery-types.js +2 -0
  42. package/dist/extensions/agent-browser/lib/electron/discovery.js +140 -549
  43. package/dist/extensions/agent-browser/lib/electron/launch-monitor.js +102 -0
  44. package/dist/extensions/agent-browser/lib/electron/launch-process.js +209 -0
  45. package/dist/extensions/agent-browser/lib/electron/launch-types.js +2 -0
  46. package/dist/extensions/agent-browser/lib/electron/launch.js +261 -355
  47. package/dist/extensions/agent-browser/lib/executable-path.js +21 -12
  48. package/dist/extensions/agent-browser/lib/execution-cwd.js +35 -18
  49. package/dist/extensions/agent-browser/lib/fs-utils.js +1 -9
  50. package/dist/extensions/agent-browser/lib/input-modes/electron.js +162 -121
  51. package/dist/extensions/agent-browser/lib/input-modes/job.js +123 -317
  52. package/dist/extensions/agent-browser/lib/input-modes/lookup-network-evidence.js +116 -0
  53. package/dist/extensions/agent-browser/lib/input-modes/lookup-plan.js +132 -0
  54. package/dist/extensions/agent-browser/lib/input-modes/lookup-redaction.js +57 -0
  55. package/dist/extensions/agent-browser/lib/input-modes/lookup-source-evidence.js +151 -0
  56. package/dist/extensions/agent-browser/lib/input-modes/lookup-workspace.js +142 -0
  57. package/dist/extensions/agent-browser/lib/input-modes/lookups.js +58 -412
  58. package/dist/extensions/agent-browser/lib/input-modes/params.js +86 -40
  59. package/dist/extensions/agent-browser/lib/input-modes/qa-analysis.js +268 -0
  60. package/dist/extensions/agent-browser/lib/input-modes/qa-presentation.js +117 -0
  61. package/dist/extensions/agent-browser/lib/input-modes/script-child.js +396 -0
  62. package/dist/extensions/agent-browser/lib/input-modes/script-protocol.js +86 -0
  63. package/dist/extensions/agent-browser/lib/input-modes/script-types.js +1 -0
  64. package/dist/extensions/agent-browser/lib/input-modes/script-validation.js +60 -0
  65. package/dist/extensions/agent-browser/lib/input-modes/script.js +60 -409
  66. package/dist/extensions/agent-browser/lib/input-modes/semantic-action.js +218 -128
  67. package/dist/extensions/agent-browser/lib/input-modes/shared.js +15 -4
  68. package/dist/extensions/agent-browser/lib/input-modes/types.js +56 -7
  69. package/dist/extensions/agent-browser/lib/json-schema.js +22 -10
  70. package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +17 -5
  71. package/dist/extensions/agent-browser/lib/managed-session-policy-lock.js +92 -425
  72. package/dist/extensions/agent-browser/lib/managed-session-posix-storage.js +58 -0
  73. package/dist/extensions/agent-browser/lib/managed-session-project-identity.js +244 -0
  74. package/dist/extensions/agent-browser/lib/managed-session-restore-context.js +84 -0
  75. package/dist/extensions/agent-browser/lib/managed-session-restore-policy.js +119 -0
  76. package/dist/extensions/agent-browser/lib/managed-session-restore-state.js +83 -0
  77. package/dist/extensions/agent-browser/lib/managed-session-restore.js +168 -300
  78. package/dist/extensions/agent-browser/lib/managed-session-snapshot-records.js +277 -0
  79. package/dist/extensions/agent-browser/lib/managed-session-snapshots.js +128 -305
  80. package/dist/extensions/agent-browser/lib/managed-session-storage.js +56 -253
  81. package/dist/extensions/agent-browser/lib/native-confirmation.js +140 -0
  82. package/dist/extensions/agent-browser/lib/native-output.js +43 -9
  83. package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +106 -59
  84. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-merge.js +14 -6
  85. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +109 -57
  86. package/dist/extensions/agent-browser/lib/orchestration/browser-run/browser-observation-result.js +82 -0
  87. package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +164 -60
  88. package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostic-values.js +31 -0
  89. package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +152 -781
  90. package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-observation.js +203 -0
  91. package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-text-diagnostics.js +109 -0
  92. package/dist/extensions/agent-browser/lib/orchestration/browser-run/fill-diagnostics.js +119 -0
  93. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-action-recovery.js +147 -0
  94. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-actions.js +144 -0
  95. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-content.js +123 -0
  96. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-contracts.js +1 -0
  97. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-details.js +156 -0
  98. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-electron.js +187 -0
  99. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-evidence.js +39 -0
  100. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-missing-binary.js +89 -0
  101. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-recovery.js +97 -0
  102. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-redaction.js +106 -0
  103. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-timeout.js +110 -0
  104. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +41 -538
  105. package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +199 -154
  106. package/dist/extensions/agent-browser/lib/orchestration/browser-run/interaction-diagnostics.js +290 -0
  107. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-close.js +167 -0
  108. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-inspection.js +108 -0
  109. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +127 -205
  110. package/dist/extensions/agent-browser/lib/orchestration/browser-run/native-helper-observation.js +65 -0
  111. package/dist/extensions/agent-browser/lib/orchestration/browser-run/observation-types.js +1 -0
  112. package/dist/extensions/agent-browser/lib/orchestration/browser-run/overlay-diagnostics.js +120 -0
  113. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.js +113 -30
  114. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.js +109 -28
  115. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter-data.js +150 -0
  116. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +147 -253
  117. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-rendered-text.js +147 -0
  118. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.js +59 -24
  119. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-artifacts.js +159 -0
  120. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-command.js +131 -0
  121. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-contracts.js +1 -0
  122. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-daemon.js +93 -0
  123. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-failure.js +42 -0
  124. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-guards.js +242 -0
  125. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-input.js +75 -0
  126. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-observations.js +92 -0
  127. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-selection.js +254 -0
  128. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-state.js +121 -0
  129. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-refs.js +130 -0
  130. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-resources.js +114 -0
  131. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-semantic.js +121 -0
  132. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-session-plan.js +222 -0
  133. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-timeouts.js +68 -0
  134. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +176 -1123
  135. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-analysis.js +191 -0
  136. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-confirmation.js +152 -0
  137. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-diagnostics.js +182 -0
  138. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-electron.js +150 -0
  139. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-contracts.js +1 -0
  140. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase-contracts.js +1 -0
  141. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase.js +115 -0
  142. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle.js +256 -0
  143. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed-contracts.js +1 -0
  144. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed.js +256 -0
  145. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase-contracts.js +1 -0
  146. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase.js +93 -0
  147. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native.js +113 -0
  148. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation-contracts.js +1 -0
  149. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation.js +316 -0
  150. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-ownership.js +28 -0
  151. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase-contracts.js +1 -0
  152. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase.js +142 -0
  153. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation-contracts.js +1 -0
  154. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation.js +333 -0
  155. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase-contracts.js +1 -0
  156. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase.js +71 -0
  157. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication.js +201 -0
  158. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-receipts.js +183 -0
  159. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-refs.js +200 -0
  160. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-tabs.js +142 -0
  161. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +18 -968
  162. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prompt-guards.js +23 -13
  163. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-receipt-reconciliation.js +198 -0
  164. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-contracts.js +1 -0
  165. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-presentation.js +154 -0
  166. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery.js +68 -151
  167. package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-capture.js +14 -0
  168. package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-observation.js +169 -46
  169. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-commands.js +130 -0
  170. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-electron.js +212 -0
  171. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-observations.js +61 -0
  172. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-outcomes.js +187 -0
  173. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-refs.js +169 -0
  174. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-tabs.js +228 -0
  175. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +77 -765
  176. package/dist/extensions/agent-browser/lib/orchestration/browser-run/text-visibility-diagnostics.js +182 -0
  177. package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-diagnostics.js +256 -0
  178. package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-progress.js +108 -0
  179. package/dist/extensions/agent-browser/lib/orchestration/code-artifact-observation.js +39 -0
  180. package/dist/extensions/agent-browser/lib/orchestration/code-image-observation.js +119 -0
  181. package/dist/extensions/agent-browser/lib/orchestration/electron-host/branch.js +93 -0
  182. package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup-result.js +58 -0
  183. package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup.js +78 -0
  184. package/dist/extensions/agent-browser/lib/orchestration/electron-host/contracts.js +1 -0
  185. package/dist/extensions/agent-browser/lib/orchestration/electron-host/discovery.js +106 -0
  186. package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +48 -821
  187. package/dist/extensions/agent-browser/lib/orchestration/electron-host/policy.js +86 -0
  188. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-collection.js +68 -0
  189. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-data.js +169 -0
  190. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-presentation.js +182 -0
  191. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe.js +161 -0
  192. package/dist/extensions/agent-browser/lib/orchestration/electron-host/status.js +167 -0
  193. package/dist/extensions/agent-browser/lib/orchestration/execution-queue.js +22 -10
  194. package/dist/extensions/agent-browser/lib/orchestration/extension-artifact-preflight.js +211 -0
  195. package/dist/extensions/agent-browser/lib/orchestration/extension-artifacts.js +23 -0
  196. package/dist/extensions/agent-browser/lib/orchestration/extension-attachment-replay.js +99 -0
  197. package/dist/extensions/agent-browser/lib/orchestration/extension-branch-restore.js +275 -0
  198. package/dist/extensions/agent-browser/lib/orchestration/extension-code.js +280 -0
  199. package/dist/extensions/agent-browser/lib/orchestration/extension-command-admission.js +303 -0
  200. package/dist/extensions/agent-browser/lib/orchestration/extension-command-output.js +36 -0
  201. package/dist/extensions/agent-browser/lib/orchestration/extension-command-result.js +335 -0
  202. package/dist/extensions/agent-browser/lib/orchestration/extension-command-run.js +227 -0
  203. package/dist/extensions/agent-browser/lib/orchestration/extension-command-state.js +1 -0
  204. package/dist/extensions/agent-browser/lib/orchestration/extension-electron-ownership.js +204 -0
  205. package/dist/extensions/agent-browser/lib/orchestration/extension-execution-locks.js +139 -0
  206. package/dist/extensions/agent-browser/lib/orchestration/extension-execution-queue.js +24 -0
  207. package/dist/extensions/agent-browser/lib/orchestration/extension-host-coordination.js +98 -0
  208. package/dist/extensions/agent-browser/lib/orchestration/extension-host-run.js +295 -0
  209. package/dist/extensions/agent-browser/lib/orchestration/extension-intent-replay.js +41 -0
  210. package/dist/extensions/agent-browser/lib/orchestration/extension-invocation.js +7 -0
  211. package/dist/extensions/agent-browser/lib/orchestration/extension-lifecycle.js +102 -0
  212. package/dist/extensions/agent-browser/lib/orchestration/extension-managed-ownership.js +133 -0
  213. package/dist/extensions/agent-browser/lib/orchestration/extension-observation.js +120 -0
  214. package/dist/extensions/agent-browser/lib/orchestration/extension-prompt.js +180 -0
  215. package/dist/extensions/agent-browser/lib/orchestration/extension-recording.js +290 -0
  216. package/dist/extensions/agent-browser/lib/orchestration/extension-resource-contracts.js +1 -0
  217. package/dist/extensions/agent-browser/lib/orchestration/extension-resource-replay.js +269 -0
  218. package/dist/extensions/agent-browser/lib/orchestration/extension-result-state.js +113 -0
  219. package/dist/extensions/agent-browser/lib/orchestration/extension-runtime.js +146 -0
  220. package/dist/extensions/agent-browser/lib/orchestration/extension-script-leases.js +58 -0
  221. package/dist/extensions/agent-browser/lib/orchestration/extension-tool-boundary.js +62 -0
  222. package/dist/extensions/agent-browser/lib/orchestration/extension-version-check.js +54 -0
  223. package/dist/extensions/agent-browser/lib/orchestration/input-plan-types.js +1 -0
  224. package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +261 -185
  225. package/dist/extensions/agent-browser/lib/orchestration/input-redaction.js +62 -0
  226. package/dist/extensions/agent-browser/lib/orchestration/native-config.js +144 -0
  227. package/dist/extensions/agent-browser/lib/orchestration/native-root-launch.js +77 -0
  228. package/dist/extensions/agent-browser/lib/orchestration/native-session-defaults.js +210 -157
  229. package/dist/extensions/agent-browser/lib/orchestration/operation-paths.js +124 -58
  230. package/dist/extensions/agent-browser/lib/orchestration/output-file.js +197 -99
  231. package/dist/extensions/agent-browser/lib/orchestration/script-mode.js +199 -96
  232. package/dist/extensions/agent-browser/lib/owned-managed-session-context.js +55 -0
  233. package/dist/extensions/agent-browser/lib/page-target-batch.js +118 -0
  234. package/dist/extensions/agent-browser/lib/page-target-guards.js +50 -0
  235. package/dist/extensions/agent-browser/lib/page-target-navigation.js +104 -0
  236. package/dist/extensions/agent-browser/lib/page-target-validation.js +55 -246
  237. package/dist/extensions/agent-browser/lib/parsing.js +13 -4
  238. package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +133 -68
  239. package/dist/extensions/agent-browser/lib/playbook.js +16 -12
  240. package/dist/extensions/agent-browser/lib/process-child.js +284 -0
  241. package/dist/extensions/agent-browser/lib/process-environment.js +13 -6
  242. package/dist/extensions/agent-browser/lib/process-errors.js +23 -0
  243. package/dist/extensions/agent-browser/lib/process-identity.js +47 -15
  244. package/dist/extensions/agent-browser/lib/process-socket-storage.js +256 -0
  245. package/dist/extensions/agent-browser/lib/process-stdout.js +74 -0
  246. package/dist/extensions/agent-browser/lib/process.js +145 -536
  247. package/dist/extensions/agent-browser/lib/prompt-artifacts.js +287 -0
  248. package/dist/extensions/agent-browser/lib/prompt-policy.js +15 -194
  249. package/dist/extensions/agent-browser/lib/read-command.js +41 -0
  250. package/dist/extensions/agent-browser/lib/read-confirmation.js +131 -68
  251. package/dist/extensions/agent-browser/lib/recording-reservations.js +118 -45
  252. package/dist/extensions/agent-browser/lib/redaction-fields.js +75 -0
  253. package/dist/extensions/agent-browser/lib/redaction-json.js +149 -0
  254. package/dist/extensions/agent-browser/lib/redaction-url.js +88 -0
  255. package/dist/extensions/agent-browser/lib/results/action-contracts.js +1 -0
  256. package/dist/extensions/agent-browser/lib/results/action-recommendations.js +28 -271
  257. package/dist/extensions/agent-browser/lib/results/artifact-contracts.js +1 -0
  258. package/dist/extensions/agent-browser/lib/results/artifact-manifest-validation.js +133 -0
  259. package/dist/extensions/agent-browser/lib/results/artifact-manifest.js +96 -94
  260. package/dist/extensions/agent-browser/lib/results/artifact-recommendations.js +73 -0
  261. package/dist/extensions/agent-browser/lib/results/categories.js +111 -54
  262. package/dist/extensions/agent-browser/lib/results/confirmation.js +29 -13
  263. package/dist/extensions/agent-browser/lib/results/editable-ref-evidence.js +62 -27
  264. package/dist/extensions/agent-browser/lib/results/electron-recommendations.js +83 -0
  265. package/dist/extensions/agent-browser/lib/results/envelope-decoding.js +48 -0
  266. package/dist/extensions/agent-browser/lib/results/envelope.js +90 -67
  267. package/dist/extensions/agent-browser/lib/results/evidence-contracts.js +1 -0
  268. package/dist/extensions/agent-browser/lib/results/failure-recommendations.js +180 -0
  269. package/dist/extensions/agent-browser/lib/results/network-routes.js +86 -45
  270. package/dist/extensions/agent-browser/lib/results/network.js +35 -12
  271. package/dist/extensions/agent-browser/lib/results/next-actions.js +49 -19
  272. package/dist/extensions/agent-browser/lib/results/presentation/artifact-files.js +320 -0
  273. package/dist/extensions/agent-browser/lib/results/presentation/artifact-format.js +138 -0
  274. package/dist/extensions/agent-browser/lib/results/presentation/artifact-images.js +113 -0
  275. package/dist/extensions/agent-browser/lib/results/presentation/artifact-verification.js +145 -0
  276. package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +99 -555
  277. package/dist/extensions/agent-browser/lib/results/presentation/batch-contracts.js +1 -0
  278. package/dist/extensions/agent-browser/lib/results/presentation/batch-recording.js +118 -0
  279. package/dist/extensions/agent-browser/lib/results/presentation/batch-redaction.js +68 -0
  280. package/dist/extensions/agent-browser/lib/results/presentation/batch-rendering.js +135 -0
  281. package/dist/extensions/agent-browser/lib/results/presentation/batch-step.js +227 -0
  282. package/dist/extensions/agent-browser/lib/results/presentation/batch-summary.js +91 -0
  283. package/dist/extensions/agent-browser/lib/results/presentation/batch.js +91 -460
  284. package/dist/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.js +9 -5
  285. package/dist/extensions/agent-browser/lib/results/presentation/command-presenters.js +216 -0
  286. package/dist/extensions/agent-browser/lib/results/presentation/common.js +26 -9
  287. package/dist/extensions/agent-browser/lib/results/presentation/content.js +86 -29
  288. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-a11y.js +67 -0
  289. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-health.js +79 -0
  290. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-identity.js +199 -0
  291. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-logs.js +75 -0
  292. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network-actions.js +216 -0
  293. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network.js +124 -0
  294. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-redaction.js +64 -0
  295. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-storage.js +209 -0
  296. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-stream.js +69 -0
  297. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-summary.js +222 -0
  298. package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +103 -1052
  299. package/dist/extensions/agent-browser/lib/results/presentation/early-result.js +70 -0
  300. package/dist/extensions/agent-browser/lib/results/presentation/errors.js +130 -60
  301. package/dist/extensions/agent-browser/lib/results/presentation/input-contracts.js +1 -0
  302. package/dist/extensions/agent-browser/lib/results/presentation/large-output.js +60 -145
  303. package/dist/extensions/agent-browser/lib/results/presentation/navigation.js +147 -88
  304. package/dist/extensions/agent-browser/lib/results/presentation/notices.js +75 -0
  305. package/dist/extensions/agent-browser/lib/results/presentation/observation-contracts.js +1 -0
  306. package/dist/extensions/agent-browser/lib/results/presentation/observation-rendering.js +127 -0
  307. package/dist/extensions/agent-browser/lib/results/presentation/outcomes.js +120 -0
  308. package/dist/extensions/agent-browser/lib/results/presentation/output-completion.js +77 -0
  309. package/dist/extensions/agent-browser/lib/results/presentation/output-spill.js +51 -0
  310. package/dist/extensions/agent-browser/lib/results/presentation/registry.js +116 -240
  311. package/dist/extensions/agent-browser/lib/results/presentation/semantic-action.js +35 -21
  312. package/dist/extensions/agent-browser/lib/results/presentation/skills.js +109 -73
  313. package/dist/extensions/agent-browser/lib/results/presentation/source.js +109 -0
  314. package/dist/extensions/agent-browser/lib/results/presentation.js +17 -261
  315. package/dist/extensions/agent-browser/lib/results/recommendation-contracts.js +1 -0
  316. package/dist/extensions/agent-browser/lib/results/recording.js +52 -14
  317. package/dist/extensions/agent-browser/lib/results/recovery-actions.js +14 -5
  318. package/dist/extensions/agent-browser/lib/results/recovery-next-actions.js +30 -22
  319. package/dist/extensions/agent-browser/lib/results/selector-recovery-target.js +83 -0
  320. package/dist/extensions/agent-browser/lib/results/selector-recovery.js +119 -119
  321. package/dist/extensions/agent-browser/lib/results/snapshot-compact.js +266 -0
  322. package/dist/extensions/agent-browser/lib/results/snapshot-content.js +32 -0
  323. package/dist/extensions/agent-browser/lib/results/snapshot-high-value-controls.js +104 -71
  324. package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +31 -11
  325. package/dist/extensions/agent-browser/lib/results/snapshot-segments.js +125 -66
  326. package/dist/extensions/agent-browser/lib/results/snapshot-spill.js +26 -7
  327. package/dist/extensions/agent-browser/lib/results/snapshot.js +28 -248
  328. package/dist/extensions/agent-browser/lib/results/text.js +16 -5
  329. package/dist/extensions/agent-browser/lib/runtime-args-validation.js +133 -0
  330. package/dist/extensions/agent-browser/lib/runtime-compatibility.js +81 -0
  331. package/dist/extensions/agent-browser/lib/runtime-contracts.js +1 -0
  332. package/dist/extensions/agent-browser/lib/runtime-redaction.js +118 -0
  333. package/dist/extensions/agent-browser/lib/runtime-replay-events.js +144 -0
  334. package/dist/extensions/agent-browser/lib/runtime-session-identity.js +76 -0
  335. package/dist/extensions/agent-browser/lib/runtime-session-plan.js +114 -0
  336. package/dist/extensions/agent-browser/lib/runtime-session-replay.js +123 -0
  337. package/dist/extensions/agent-browser/lib/runtime-tab-correction.js +65 -0
  338. package/dist/extensions/agent-browser/lib/runtime-timeouts.js +28 -0
  339. package/dist/extensions/agent-browser/lib/runtime.js +137 -1041
  340. package/dist/extensions/agent-browser/lib/session-identity.js +51 -0
  341. package/dist/extensions/agent-browser/lib/session-page-observation.js +357 -0
  342. package/dist/extensions/agent-browser/lib/session-page-state.js +178 -333
  343. package/dist/extensions/agent-browser/lib/session-page-types.js +1 -0
  344. package/dist/extensions/agent-browser/lib/temp-artifact-budget.js +81 -0
  345. package/dist/extensions/agent-browser/lib/temp-mutation-queue.js +7 -0
  346. package/dist/extensions/agent-browser/lib/temp-root-ownership.js +234 -0
  347. package/dist/extensions/agent-browser/lib/temp-root.js +211 -0
  348. package/dist/extensions/agent-browser/lib/temp.js +33 -446
  349. package/dist/extensions/agent-browser/lib/tool-surface.js +94 -24
  350. package/dist/extensions/agent-browser/lib/upstream-version.js +3 -2
  351. package/dist/extensions/agent-browser/lib/web-search-providers.js +193 -0
  352. package/dist/extensions/agent-browser/lib/web-search-request.js +102 -0
  353. package/dist/extensions/agent-browser/lib/web-search-results.js +281 -0
  354. package/dist/extensions/agent-browser/lib/web-search-schema.js +82 -0
  355. package/dist/extensions/agent-browser/lib/web-search.js +124 -614
  356. package/dist/extensions/agent-browser/lib/webmcp-observation.js +13 -6
  357. package/dist/extensions/agent-browser/lib/windows-stock-launcher.js +63 -37
  358. package/dist/extensions/agent-browser/script-worker.js +80 -43
  359. package/dist/scripts/agent-browser-target.mjs +4 -2
  360. package/docs/ARCHITECTURE.md +19 -6
  361. package/docs/CODE_QUALITY.md +267 -0
  362. package/docs/COMMAND_REFERENCE.md +272 -241
  363. package/docs/ELECTRON.md +77 -46
  364. package/docs/REFERENCE.md +869 -0
  365. package/docs/RELEASE.md +25 -22
  366. package/docs/REQUIREMENTS.md +2 -1
  367. package/docs/SUPPORT_MATRIX.md +81 -79
  368. package/docs/TOOL_CONTRACT.md +158 -125
  369. package/docs/platform-smoke.md +8 -8
  370. package/package.json +144 -120
  371. package/scripts/agent-browser-capability-baseline.mjs +361 -957
  372. package/scripts/agent-browser-target.mjs +6 -2
  373. package/scripts/build.mjs +37 -8
  374. package/scripts/capability-core-commands.mjs +193 -0
  375. package/scripts/capability-options.mjs +283 -0
  376. package/scripts/capability-samples.mjs +133 -0
  377. package/scripts/capability-section.mjs +11 -0
  378. package/scripts/config.mjs +235 -132
  379. package/scripts/convert-browser-session.mjs +30 -9
  380. package/scripts/doctor-sources.mjs +195 -0
  381. package/scripts/doctor.mjs +94 -249
  382. package/scripts/platform-smoke/artifacts.mjs +38 -11
  383. package/scripts/platform-smoke/commands.mjs +104 -0
  384. package/scripts/platform-smoke/crabbox-runner.mjs +167 -80
  385. package/scripts/platform-smoke/doctor-support.mjs +157 -0
  386. package/scripts/platform-smoke/doctor-windows.mjs +230 -0
  387. package/scripts/platform-smoke/doctor.mjs +212 -320
  388. package/scripts/platform-smoke/lease-evidence.mjs +132 -0
  389. package/scripts/platform-smoke/linux-image/Dockerfile +8 -2
  390. package/scripts/platform-smoke/suite-checks.mjs +98 -0
  391. package/scripts/platform-smoke/suite-evidence.mjs +281 -0
  392. package/scripts/platform-smoke/targets.mjs +154 -472
  393. package/scripts/platform-smoke.mjs +55 -40
  394. package/scripts/prepare.mjs +16 -7
@@ -1,50 +1,60 @@
1
- import { AsyncLocalStorage } from "node:async_hooks";
2
- import { rm } from "node:fs/promises";
3
- import { getScreenshotPositionalIndices } from "./artifact-paths.js";
4
- import { observeNativeWebMcp } from "../../webmcp-observation.js";
5
- import { getAgentBrowserSessionIdentityKey } from "../../argv-grammar.js";
6
- import { parseArgvDescriptor } from "../../argv-descriptor.js";
7
- import { isBrowserIndependentRead, needsManagedSession } from "../../command-policy.js";
8
- import { runAgentBrowserProcess } from "../../process.js";
9
- import { buildAgentBrowserNextActions } from "../../results/action-recommendations.js";
10
- import { parseAgentBrowserEnvelope } from "../../results/envelope.js";
11
- import { detectConfirmationRequired } from "../../results/confirmation.js";
12
- import { buildNextToolAction, withOptionalNamespaceArgs, withOptionalSessionArgs } from "../../results/next-actions.js";
13
- import { getSessionPageStateKey, isAboutBlankUrl, normalizeComparableUrl, targetsMatch, } from "../../session-page-state.js";
14
- import { getRecordCommandOperands, isCloseCommand, isElectronPostCommandHealthCommand, isNavigationObservableCommandName, isOpenNavigationCommand, isRefGuardedCommand, isRefInvalidatingBatchCommand, isSessionTabPinningExcludedCommand, isSessionTabPostCommandCorrectionExcludedCommand, isWindowOrDiffPageTransitionCommand, } from "../../command-taxonomy.js";
15
- import { chooseOpenResultTabCorrection } from "../../runtime.js";
16
- import { isRecord, parseRefId } from "../../parsing.js";
17
- import { getUpstreamEffectiveBatchSteps } from "../batch-stdin.js";
18
- import { findFirstPositionalArgument } from "./prepare/wait-timeouts.js";
1
+ import { isCloseCommand } from "../../command-taxonomy.js";
2
+ import { getSessionPageStateKey } from "../../session-page-state.js";
3
+ export { buildManagedSessionOutcome, formatManagedSessionOutcomeText, buildManagedSessionFreshFailureNextActions, } from "./session-state-outcomes.js";
4
+ export { extractStringResultField, extractNavigationSummaryFromData, shouldCaptureNavigationSummary, mergeNavigationSummaryIntoData, buildAboutBlankRecoveryHint, buildAboutBlankWarning, extractBatchResultCommand, } from "./session-state-observations.js";
5
+ export { getStaleRefArgs, getGuardedRefUsage, buildStaleRefPreflight, } from "./session-state-refs.js";
6
+ export { withSessionCommandObservation, nativePolicyDefinitelyUnestablished, runSessionCommandData, } from "./session-state-commands.js";
7
+ export { commandChoosesSessionTabTarget, shouldPinSessionTabForCommand, shouldCorrectSessionTabAfterCommand, collectOpenResultTabCorrection, collectSessionTabTarget, collectSessionTabSelection, ensureSessionTabTarget, applyOpenResultTabCorrection, } from "./session-state-tabs.js";
8
+ export { isLiveElectronRendererTarget, getLiveElectronRendererTargets, electronTargetLabel, getActiveElectronRecords, findElectronLaunchRecordForSession, buildElectronMismatchNextActions, buildElectronSessionMismatch, formatElectronSessionMismatchText, shouldInspectElectronPostCommandHealth, buildElectronLifecycleNextActions, buildElectronPostCommandHealthDiagnostic, formatElectronPostCommandHealthText, buildElectronIdentifiers, buildElectronRefFreshnessNextActions, buildElectronRefFreshnessDiagnostic, formatElectronRefFreshnessText, } from "./session-state-electron.js";
9
+ function managedLaunchUpdate(patch) {
10
+ return {
11
+ ...("managedSessionCompatibilityWorkaround" in patch
12
+ ? { managedSessionCompatibilityWorkaround: patch.managedSessionCompatibilityWorkaround }
13
+ : {}),
14
+ ...(patch.managedSessionHeadedAutosaveDisabled !== undefined
15
+ ? { managedSessionHeadedAutosaveDisabled: patch.managedSessionHeadedAutosaveDisabled }
16
+ : {}),
17
+ ...("managedSessionHeadedAutosaveInterval" in patch
18
+ ? { managedSessionHeadedAutosaveInterval: patch.managedSessionHeadedAutosaveInterval }
19
+ : {}),
20
+ };
21
+ }
22
+ function managedIdentityUpdate(patch) {
23
+ return {
24
+ ...(patch.managedSessionCwd !== undefined
25
+ ? { managedSessionCwd: patch.managedSessionCwd }
26
+ : {}),
27
+ ...(patch.managedSessionName !== undefined
28
+ ? { managedSessionName: patch.managedSessionName }
29
+ : {}),
30
+ ...("managedSessionNamespace" in patch
31
+ ? { managedSessionNamespace: patch.managedSessionNamespace }
32
+ : {}),
33
+ ...(patch.managedSessionActive !== undefined
34
+ ? { managedSessionActive: patch.managedSessionActive }
35
+ : {}),
36
+ ...(patch.freshSessionOrdinal !== undefined
37
+ ? { freshSessionOrdinal: patch.freshSessionOrdinal }
38
+ : {}),
39
+ };
40
+ }
19
41
  export function applyBrowserRunStatePatch(state, patch) {
20
- if (!patch)
42
+ if (!patch) {
21
43
  return;
22
- if ("artifactManifest" in patch)
44
+ }
45
+ if ("artifactManifest" in patch) {
23
46
  state.artifactManifest = patch.artifactManifest;
24
- if (patch.freshSessionOrdinal !== undefined)
25
- state.freshSessionOrdinal = patch.freshSessionOrdinal;
26
- if (patch.managedSessionActive !== undefined)
27
- state.managedSessionActive = patch.managedSessionActive;
28
- if ("managedSessionCompatibilityWorkaround" in patch)
29
- state.managedSessionCompatibilityWorkaround = patch.managedSessionCompatibilityWorkaround;
30
- if (patch.managedSessionHeadedAutosaveDisabled !== undefined)
31
- state.managedSessionHeadedAutosaveDisabled = patch.managedSessionHeadedAutosaveDisabled;
32
- if ("managedSessionHeadedAutosaveInterval" in patch)
33
- state.managedSessionHeadedAutosaveInterval = patch.managedSessionHeadedAutosaveInterval;
34
- if (patch.managedSessionCwd !== undefined)
35
- state.managedSessionCwd = patch.managedSessionCwd;
36
- if (patch.managedSessionName !== undefined)
37
- state.managedSessionName = patch.managedSessionName;
38
- if ("managedSessionNamespace" in patch)
39
- state.managedSessionNamespace = patch.managedSessionNamespace;
40
- if (patch.networkRoutesBySession)
47
+ }
48
+ if (patch.networkRoutesBySession) {
41
49
  state.networkRoutesBySession = patch.networkRoutesBySession;
50
+ }
51
+ Object.assign(state, managedLaunchUpdate(patch), managedIdentityUpdate(patch));
42
52
  }
43
53
  export const getSessionContextKey = getSessionPageStateKey;
44
54
  export function buildSessionDetailFields(sessionName, usedImplicitSession, namespace, managedSessionRestoreDisabled = false) {
45
55
  return {
46
56
  ...(namespace !== undefined ? { namespace } : {}),
47
- ...(sessionName
57
+ ...((sessionName?.length ?? 0) > 0
48
58
  ? {
49
59
  sessionName,
50
60
  usedImplicitSession,
@@ -53,753 +63,55 @@ export function buildSessionDetailFields(sessionName, usedImplicitSession, names
53
63
  : {}),
54
64
  };
55
65
  }
56
- export function buildManagedSessionOutcome(options) {
57
- const { activeAfter, activeBefore, attemptedSessionName, command, currentSessionName, currentSessionNamespace, previousSessionName, replacedSessionName, replacedSessionNamespace, sessionMode, succeeded } = options;
58
- if (!attemptedSessionName)
59
- return undefined;
60
- let status;
61
- let summary;
62
- if (isCloseCommand(command)) {
63
- status = succeeded ? "closed" : activeBefore ? "preserved" : "abandoned";
64
- summary = succeeded
65
- ? `Managed session ${attemptedSessionName} was closed.`
66
- : activeBefore
67
- ? `Managed session close failed; previous managed session ${previousSessionName} remains current.`
68
- : `Managed session close failed; no managed session is active.`;
69
- }
70
- else if (succeeded) {
71
- if (replacedSessionName) {
72
- status = "replaced";
73
- summary = `Managed session ${replacedSessionName} was replaced by ${currentSessionName}.`;
74
- }
75
- else if (!activeBefore && activeAfter) {
76
- status = "created";
77
- summary = `Managed session ${currentSessionName} is now current.`;
78
- }
79
- else {
80
- status = "unchanged";
81
- summary = `Managed session ${currentSessionName} remains current.`;
82
- }
83
- }
84
- else if (activeBefore) {
85
- status = "preserved";
86
- summary = sessionMode === "fresh" && attemptedSessionName !== previousSessionName
87
- ? `Fresh managed session ${attemptedSessionName} failed before becoming current; previous managed session ${previousSessionName} was preserved.`
88
- : `Managed session call failed; previous managed session ${previousSessionName} was preserved.`;
89
- }
90
- else {
91
- status = "abandoned";
92
- summary = sessionMode === "fresh"
93
- ? `Fresh managed session ${attemptedSessionName} failed before becoming current; no previous managed session was active, so no managed session is current.`
94
- : `Managed session call failed before any managed session became current.`;
95
- }
96
- return {
97
- activeAfter,
98
- activeBefore,
99
- attemptedSessionName,
100
- currentSessionName,
101
- ...(currentSessionNamespace ? { currentSessionNamespace } : {}),
102
- previousSessionName,
103
- replacedSessionName,
104
- replacedSessionNamespace,
105
- sessionMode,
106
- status,
107
- succeeded,
108
- summary,
109
- };
110
- }
111
- function isFreshPostLaunchFailure(outcome) {
112
- return !outcome.succeeded && outcome.sessionMode === "fresh" && outcome.activeAfter && !!outcome.currentSessionName && (outcome.status === "created" || outcome.status === "replaced" || outcome.status === "unchanged");
113
- }
114
- function formatManagedSessionOutcomeHeadline(outcome) {
115
- if (outcome.status === "preserved") {
116
- return "Managed session outcome: Fresh launch failed; your previous browser session is still active.";
117
- }
118
- if (outcome.status === "abandoned") {
119
- return "Managed session outcome: Fresh launch failed; no managed browser session is current.";
120
- }
121
- if (isFreshPostLaunchFailure(outcome)) {
122
- return "Managed session outcome: Fresh launch became current, but this tool call failed after launch.";
123
- }
124
- return `Managed session outcome: ${outcome.summary}`;
125
- }
126
- function formatManagedSessionOutcomeRecoveryGuidance(outcome) {
127
- const lines = ["Recovery:"];
128
- if (outcome.status === "preserved") {
129
- lines.push('- Continue with sessionMode "auto" on the current session, or retry the intended launch with sessionMode "fresh".');
130
- lines.push("- Run doctor to verify agent-browser install and environment when failures persist.");
131
- }
132
- else if (outcome.status === "abandoned") {
133
- lines.push('- Retry with sessionMode "fresh" (for example args: ["open", "<url>"]) after verifying agent-browser is on PATH.');
134
- lines.push("- Run doctor when install or environment issues are suspected.");
135
- }
136
- else if (isFreshPostLaunchFailure(outcome)) {
137
- lines.push('- Continue with sessionMode "auto" on the current session, or inspect failureCategory / qaPreset to fix the post-launch failure.');
138
- lines.push("- Run doctor only if later browser commands also fail.");
139
- }
140
- else {
141
- lines.push('- Retry with sessionMode "fresh" when launch-scoped flags must apply, or run doctor to verify the environment.');
142
- }
143
- lines.push("- Full session names and transition details remain in details.managedSessionOutcome.");
144
- return lines.join("\n");
145
- }
146
- export function formatManagedSessionOutcomeText(outcome) {
147
- if (!outcome)
148
- return undefined;
149
- if (outcome.replacedSessionClosed === false) {
150
- const cleanupWarning = "Cleanup warning: Automatic close of the previous wrapper-managed session failed, so it remains wrapper-owned. Use details.managedSessionOutcome for its exact identity and close it explicitly when safe.";
151
- return outcome.succeeded
152
- ? ["Managed session outcome: The fresh browser became current.", cleanupWarning].join("\n")
153
- : [formatManagedSessionOutcomeHeadline(outcome), formatManagedSessionOutcomeRecoveryGuidance(outcome), cleanupWarning].join("\n");
154
- }
155
- if (outcome.status === "closed" && outcome.succeeded) {
156
- return [
157
- "Managed session outcome: The current wrapper-managed browser session was closed.",
158
- "Next sessionMode auto call will start or attach a managed session as needed. If upstream session list still shows rows, they are separate saved/upstream sessions; use close --all only when full cleanup is intended.",
159
- "Full session names and transition details remain in details.managedSessionOutcome.",
160
- ].join("\n");
161
- }
162
- if (outcome.succeeded || outcome.sessionMode !== "fresh")
163
- return undefined;
164
- return [formatManagedSessionOutcomeHeadline(outcome), formatManagedSessionOutcomeRecoveryGuidance(outcome)].join("\n");
165
- }
166
- export function buildManagedSessionFreshFailureNextActions(outcome) {
167
- if (!outcome || outcome.succeeded || outcome.sessionMode !== "fresh")
168
- return [];
169
- const actions = [];
170
- if (!isFreshPostLaunchFailure(outcome)) {
171
- actions.push(buildNextToolAction({
172
- args: ["doctor"],
173
- id: "run-agent-browser-doctor",
174
- reason: "Verify agent-browser install, PATH, and environment after a failed fresh launch.",
175
- safety: "Read-only local diagnostics; does not mutate browser state.",
176
- }));
177
- }
178
- if ((outcome.status === "preserved" || isFreshPostLaunchFailure(outcome)) && outcome.activeAfter && outcome.currentSessionName) {
179
- const sessionLabel = isFreshPostLaunchFailure(outcome) ? "current managed session" : "preserved managed session";
180
- const currentSessionArgs = (args) => withOptionalNamespaceArgs(outcome.currentSessionNamespace, withOptionalSessionArgs(outcome.currentSessionName, args));
181
- actions.push(buildNextToolAction({
182
- args: currentSessionArgs(["get", "url"]),
183
- id: "verify-current-managed-session",
184
- reason: `Confirm the ${sessionLabel} before continuing with sessionMode auto.`,
185
- safety: `Read-only URL check on the ${sessionLabel}.`,
186
- }), buildNextToolAction({
187
- args: currentSessionArgs(["snapshot", "-i"]),
188
- id: "snapshot-current-managed-session",
189
- reason: `Refresh interactive refs on the ${sessionLabel} before retrying the workflow.`,
190
- safety: "Read-only snapshot; no navigation.",
191
- }));
192
- }
193
- else {
194
- actions.push(buildNextToolAction({
195
- args: ["open", "about:blank"],
196
- id: "retry-fresh-managed-session",
197
- reason: "Start a new managed browser session after the failed fresh launch.",
198
- safety: "Replace about:blank with the intended URL from your workflow.",
199
- sessionMode: "fresh",
200
- }));
201
- }
202
- return actions;
203
- }
204
66
  function getTraceOwner(command) {
205
67
  return command === "trace" || command === "profiler" ? command : undefined;
206
68
  }
207
69
  export function getTraceOwnerGuardMessage(options) {
208
70
  const owner = getTraceOwner(options.command);
209
- if (!owner || !options.sessionName || (options.subcommand !== "start" && options.subcommand !== "stop")) {
210
- return undefined;
71
+ const sessionName = options.sessionName;
72
+ if (owner === undefined ||
73
+ sessionName === undefined ||
74
+ sessionName.length === 0 ||
75
+ (options.subcommand !== "start" && options.subcommand !== "stop")) {
76
+ return;
211
77
  }
212
- const activeOwner = options.traceOwners.get(options.sessionName);
213
- if (!activeOwner || activeOwner === owner) {
214
- return undefined;
78
+ const activeOwner = options.traceOwners.get(sessionName);
79
+ if (activeOwner === undefined || activeOwner === owner) {
80
+ return;
215
81
  }
216
82
  return options.subcommand === "start"
217
- ? `Wrapper believes ${activeOwner} tracing is active for session ${options.sessionName}; stop ${activeOwner} before starting ${owner}.`
218
- : `Wrapper believes tracing for session ${options.sessionName} is owned by ${activeOwner}; run ${activeOwner} stop instead of ${owner} stop.`;
83
+ ? `Wrapper believes ${activeOwner} tracing is active for session ${sessionName}; stop ${activeOwner} before starting ${owner}.`
84
+ : `Wrapper believes tracing for session ${sessionName} is owned by ${activeOwner}; run ${activeOwner} stop instead of ${owner} stop.`;
219
85
  }
220
86
  export function updateTraceOwnerState(options) {
221
- if (!options.sessionName || !options.succeeded)
87
+ const sessionName = options.sessionName;
88
+ if (sessionName === undefined || sessionName.length === 0 || !options.succeeded) {
222
89
  return;
90
+ }
223
91
  if (isCloseCommand(options.command)) {
224
- options.traceOwners.delete(options.sessionName);
92
+ options.traceOwners.delete(sessionName);
225
93
  return;
226
94
  }
227
95
  const owner = getTraceOwner(options.command);
228
- if (!owner)
96
+ if (owner === undefined) {
229
97
  return;
230
- if (options.subcommand === "start") {
231
- options.traceOwners.set(options.sessionName, owner);
232
- }
233
- if (options.subcommand === "stop" && options.traceOwners.get(options.sessionName) === owner) {
234
- options.traceOwners.delete(options.sessionName);
235
- }
236
- }
237
- export function extractStringResultField(data, fieldName) {
238
- if (typeof data === "string") {
239
- if (fieldName === "value")
240
- return data;
241
- const text = data.trim();
242
- return text.length > 0 ? text : undefined;
243
- }
244
- if (!isRecord(data) || typeof data[fieldName] !== "string") {
245
- return undefined;
246
- }
247
- if (fieldName === "value")
248
- return data[fieldName];
249
- const text = data[fieldName].trim();
250
- return text.length > 0 ? text : undefined;
251
- }
252
- export function extractNavigationSummaryFromData(data) {
253
- const result = isRecord(data) && isRecord(data.result) ? data.result : data;
254
- const title = extractStringResultField(result, "title");
255
- const url = extractStringResultField(result, "url");
256
- const urlChanged = isRecord(result) && typeof result.urlChanged === "boolean" ? result.urlChanged : undefined;
257
- return title || url ? { title, url, urlChanged } : undefined;
258
- }
259
- export function shouldCaptureNavigationSummary(command, data, subcommand) {
260
- if (command === "eval")
261
- return true;
262
- // A completed compound action may navigate without returning a page URL (e.g. recording restart).
263
- if (command === "confirm" && isRecord(data) && data.confirmed === true && data.action === "navigate"
264
- && isRecord(data.result) && data.result.success === true && extractStringResultField(data.result.data, "url") === undefined)
265
- return true;
266
- return (isNavigationObservableCommandName(command, subcommand) &&
267
- (!isRecord(data) || (typeof data.title !== "string" && typeof data.url !== "string")));
268
- }
269
- export function mergeNavigationSummaryIntoData(data, navigationSummary) {
270
- if (isRecord(data)) {
271
- return { ...data, navigationSummary };
272
- }
273
- return { navigationSummary, result: data };
274
- }
275
- export function buildAboutBlankRecoveryHint() {
276
- return "agent_browser detected that the active tab became about:blank while this session still had a prior intended tab. Run tab list for this session and re-select the intended tab, or retry with sessionMode:fresh if the tab is gone.".replace("sessionMode:fresh", "sessionMode=fresh");
277
- }
278
- export function buildAboutBlankWarning(mismatch) {
279
- return `Warning: agent_browser detected that this session returned about:blank while the prior intended tab was ${mismatch.targetUrl}. ${mismatch.recoveryApplied ? "The wrapper re-selected the intended tab for the session." : "No matching tab could be re-selected; run tab list for the same session or retry with sessionMode=fresh."}`;
280
- }
281
- function extractBatchResultCommand(item) {
282
- return Array.isArray(item.command) ? item.command.filter((token) => typeof token === "string") : [];
283
- }
284
- export function getStaleRefArgs(commandTokens, stdin) {
285
- if (commandTokens[0] !== "batch") {
286
- return commandTokens;
287
- }
288
- const steps = getUpstreamEffectiveBatchSteps(commandTokens, stdin);
289
- return steps.length > 0 ? steps.flatMap((step) => step) : commandTokens;
290
- }
291
- // Inspect only upstream's selector slots: fill text, file paths and key data are not refs.
292
- function collectRefsFromTokens(tokens) {
293
- if (!isRefGuardedCommand(tokens[0]) || (tokens[0] === "diff" && tokens[1] !== "screenshot"))
294
- return [];
295
- let selectors;
296
- switch (tokens[0]) {
297
- case "click":
298
- selectors = [tokens.slice(1).find((token) => token !== "--new-tab" && token !== "--human")];
299
- break;
300
- case "drag":
301
- selectors = tokens.slice(1, 3);
302
- break;
303
- case "get":
304
- selectors = [!["url", "title", "cdp-url", "count"].includes(tokens[1]) ? tokens[2] : undefined];
305
- break;
306
- case "is":
307
- selectors = [tokens[2]];
308
- break;
309
- case "screenshot":
310
- selectors = [tokens[getScreenshotPositionalIndices(tokens)[0]]];
311
- break;
312
- case "diff":
313
- case "scroll": {
314
- let selector;
315
- for (let index = tokens[0] === "diff" ? 2 : 1; index < tokens.length; index += 1) {
316
- const token = tokens[index];
317
- if (token === "--selector" || token === "-s")
318
- selector = tokens[++index];
319
- else if (tokens[0] === "diff" && ["--baseline", "-b", "--output", "-o", "--threshold", "-t", "--depth", "-d"].includes(token))
320
- index += 1;
321
- }
322
- selectors = [selector];
323
- break;
324
- }
325
- default: selectors = [tokens[1]];
326
- }
327
- return selectors.flatMap((selector) => {
328
- const ref = selector === undefined ? undefined : parseRefId(selector);
329
- return ref === undefined ? [] : [ref];
330
- });
331
- }
332
- export function getGuardedRefUsage(commandTokens, stdin, options = {}) {
333
- if (commandTokens[0] !== "batch") {
334
- return collectRefsFromTokens(commandTokens);
335
98
  }
336
- const steps = getUpstreamEffectiveBatchSteps(commandTokens, stdin);
337
- const refsBeforeInBatchSnapshot = [];
338
- for (const step of steps) {
339
- if (!options.includeRefsAfterBatchSnapshot && (step[0] ?? "") === "snapshot")
340
- break;
341
- refsBeforeInBatchSnapshot.push(...collectRefsFromTokens(step));
342
- }
343
- return refsBeforeInBatchSnapshot;
344
- }
345
- function getSnapshotRefRole(refSnapshot, refId) {
346
- return refSnapshot?.refs?.[refId]?.role?.toLowerCase();
347
- }
348
- function isSafeSameSnapshotFormBatchStep(step, refSnapshot) {
349
- const command = step[0];
350
- const refIds = collectRefsFromTokens(step);
351
- if (refIds.length === 0 || !refSnapshot)
352
- return false;
353
- const roles = refIds.map((refId) => getSnapshotRefRole(refSnapshot, refId));
354
- if (roles.some((role) => role === undefined))
355
- return false;
356
- if (command === "check" || command === "uncheck")
357
- return roles.every((role) => role === "checkbox" || role === "radio");
358
- if (command === "click" || command === "tap")
359
- return roles.every((role) => role === "checkbox" || role === "radio");
360
- if (command === "select")
361
- return roles.every((role) => role === "combobox");
362
- return false;
363
- }
364
- function getBatchRefInvalidationMessage(commandTokens, stdin, refSnapshot) {
365
- if (commandTokens[0] !== "batch")
366
- return undefined;
367
- let priorStepInvalidatesRefs = false;
368
- for (const step of getUpstreamEffectiveBatchSteps(commandTokens, stdin)) {
369
- if ((step[0] ?? "") === "snapshot") {
370
- priorStepInvalidatesRefs = false;
371
- }
372
- const refIds = collectRefsFromTokens(step);
373
- if (refIds.length > 0 && isRefGuardedCommand(step[0]) && priorStepInvalidatesRefs) {
374
- return `Batch step ${step[0]} uses page-scoped ref ${refIds.map((refId) => `@${refId}`).join(", ")} after an earlier batch step can navigate or mutate the page. Split the batch, run snapshot -i after the page-changing step, then retry with current refs.`;
375
- }
376
- if (isRefInvalidatingBatchCommand(step) && !isSafeSameSnapshotFormBatchStep(step, refSnapshot)) {
377
- priorStepInvalidatesRefs = true;
378
- }
379
- }
380
- return undefined;
381
- }
382
- export function buildStaleRefPreflight(options) {
383
- const guardedRefIds = [...new Set(getGuardedRefUsage(options.commandTokens, options.stdin))];
384
- const usedRefIds = options.refSnapshotInvalidation
385
- ? [...new Set(getGuardedRefUsage(options.commandTokens, options.stdin, { includeRefsAfterBatchSnapshot: true }))]
386
- : guardedRefIds;
387
- const batchInvalidationMessage = getBatchRefInvalidationMessage(options.commandTokens, options.stdin, options.refSnapshot);
388
- if (batchInvalidationMessage && guardedRefIds.length > 0) {
389
- return {
390
- message: batchInvalidationMessage,
391
- refIds: guardedRefIds,
392
- snapshot: options.refSnapshot,
393
- };
394
- }
395
- if (usedRefIds.length === 0)
396
- return undefined;
397
- if (options.refSnapshotInvalidation) {
398
- return {
399
- message: options.refSnapshotInvalidation.reason === "page-transition"
400
- ? `Ref ${usedRefIds.map((refId) => `@${refId}`).join(", ")} cannot be used yet. ${options.refSnapshotInvalidation.summary}`
401
- : `Ref ${usedRefIds.map((refId) => `@${refId}`).join(", ")} cannot be used because the latest snapshot for this session reported No active page. Run snapshot -i successfully before using page-scoped refs.`,
402
- refIds: usedRefIds,
403
- snapshotInvalidation: options.refSnapshotInvalidation,
404
- };
405
- }
406
- if (!options.refSnapshot)
407
- return undefined;
408
- if (!targetsMatch(options.refSnapshot.target, options.currentTarget)
409
- || options.requireExactTargetUrl && options.refSnapshot.target && options.currentTarget && options.refSnapshot.target.url !== options.currentTarget.url) {
410
- return {
411
- message: `Ref ${usedRefIds.map((refId) => `@${refId}`).join(", ")} came from a snapshot for ${options.refSnapshot.target?.url ?? "a prior page"}, but the current session target is ${options.currentTarget?.url ?? "unknown"}. Run snapshot -i again before using page-scoped refs.`,
412
- refIds: usedRefIds,
413
- snapshot: options.refSnapshot,
414
- };
415
- }
416
- const knownRefs = new Set(options.refSnapshot.refIds);
417
- const missingRefs = usedRefIds.filter((refId) => !knownRefs.has(refId));
418
- if (missingRefs.length > 0) {
419
- return {
420
- message: `Ref ${missingRefs.map((refId) => `@${refId}`).join(", ")} was not present in the latest snapshot for this session. Run snapshot -i again before using page-scoped refs.`,
421
- refIds: missingRefs,
422
- snapshot: options.refSnapshot,
423
- };
424
- }
425
- return undefined;
426
- }
427
- export function commandChoosesSessionTabTarget(args) {
428
- const tokens = parseArgvDescriptor(args).upstreamCommandTokens;
429
- const [command, subcommand] = tokens;
430
- return isOpenNavigationCommand(command) || isCloseCommand(command) || command === "connect"
431
- || (command === "state" && subcommand === "load")
432
- || (command === "tab" && subcommand !== undefined && subcommand !== "list")
433
- || isWindowOrDiffPageTransitionCommand(command, subcommand)
434
- || (command === "a11y" && findFirstPositionalArgument(tokens) !== undefined)
435
- || (["vitals", "web-vitals"].includes(command) && tokens.slice(1).some((token) => !token.startsWith("--")))
436
- || getRecordCommandOperands(tokens).url !== undefined;
437
- }
438
- export function shouldPinSessionTabForCommand(options) {
439
- if (!options.pinningRequired || !options.sessionName || !options.command || isBrowserIndependentRead(options.commandTokens, options.stdin))
440
- return false;
441
- const steps = options.command === "batch" ? getUpstreamEffectiveBatchSteps(options.commandTokens, options.stdin) : [options.commandTokens];
442
- for (const step of steps) {
443
- const descriptor = parseArgvDescriptor(step);
444
- const tokens = descriptor.upstreamCommandTokens;
445
- const [command, subcommand] = tokens;
446
- // A later page action uses the explicit destination, not the remembered tab.
447
- if (commandChoosesSessionTabTarget(tokens))
448
- return false;
449
- if (!needsManagedSession(descriptor) || isSessionTabPinningExcludedCommand(command))
450
- continue;
451
- if (command === "get" && subcommand === "url" && !options.reopenPending)
452
- continue;
453
- if (command === "record" && subcommand === "stop")
454
- continue;
455
- if (["console", "errors"].includes(command))
456
- continue;
457
- if (command === "network" && !(subcommand === "requests" && tokens.some((token) => ["--current-page", "--current-origin", "--current-url"].includes(token))))
458
- continue;
459
- return true;
460
- }
461
- return false;
462
- }
463
- export function shouldCorrectSessionTabAfterCommand(options) {
464
- return (options.pinningRequired === true &&
465
- options.sessionName !== undefined &&
466
- options.command !== undefined &&
467
- !isSessionTabPostCommandCorrectionExcludedCommand(options.command));
468
- }
469
- function getTabSelection(tab) {
470
- if (tab.targetId)
471
- return { selectedTab: tab.targetId, selectionKind: "targetId" };
472
- if (typeof tab.tabId === "string" && tab.tabId.trim().length > 0)
473
- return { selectedTab: tab.tabId.trim(), selectionKind: "tabId" };
474
- if (typeof tab.label === "string" && tab.label.trim().length > 0)
475
- return { selectedTab: tab.label.trim(), selectionKind: "label" };
476
- return typeof tab.index === "number" ? { selectedTab: String(tab.index), selectionKind: "index" } : undefined;
477
- }
478
- function selectSessionTargetTab(options) {
479
- if (options.target.targetId) {
480
- const target = selectAnySessionTargetTab(options);
481
- return target && options.tabs.find((tab) => tab.targetId === options.target.targetId)?.active !== true ? target : undefined;
482
- }
483
- return chooseOpenResultTabCorrection({
484
- tabs: options.tabs,
485
- targetTitle: options.target.title,
486
- targetUrl: options.target.url,
487
- });
488
- }
489
- function selectAnySessionTargetTab(options) {
490
- const targetUrl = typeof options.target.url === "string" ? normalizeComparableUrl(options.target.url) : undefined;
491
- if (!targetUrl)
492
- return undefined;
493
- const matchingTabs = options.tabs.filter((tab) => options.target.targetId
494
- ? tab.targetId === options.target.targetId
495
- : normalizeComparableUrl(tab.url ?? "") === targetUrl);
496
- const targetTitle = options.target.title?.trim() ?? "";
497
- const titledTabs = targetTitle ? matchingTabs.filter((tab) => tab.title?.trim() === targetTitle) : [];
498
- const selectedTab = titledTabs.find((tab) => tab.active) ?? titledTabs[0] ?? matchingTabs.find((tab) => tab.active) ?? matchingTabs[0];
499
- const selection = selectedTab ? getTabSelection(selectedTab) : undefined;
500
- return selection ? { ...selection, ...(targetTitle ? { targetTitle } : {}), targetUrl } : undefined;
501
- }
502
- const sessionCommandObservation = new AsyncLocalStorage();
503
- export function withSessionCommandObservation(observer, run) {
504
- return sessionCommandObservation.run(observer, run);
505
- }
506
- export function nativePolicyDefinitelyUnestablished(result, envelope, commandTokens) {
507
- if (commandTokens && !needsManagedSession(parseArgvDescriptor(commandTokens)) && !isBrowserIndependentRead(commandTokens))
508
- return true;
509
- if (!result.agentBrowserStarted)
510
- return true;
511
- if (result.aborted || result.timedOut || result.spawnError || result.exitCode !== 1)
512
- return false;
513
- // Native CLI parse/config failures precede ensure_daemon; a failed executed action does not.
514
- return envelope?.success === false && isRecord(envelope.data) && Object.keys(envelope.data).length === 1
515
- && ["unknown_command", "unknown_subcommand", "missing_arguments", "invalid_value", "invalid_session_name"].includes(String(envelope.data.type))
516
- || result.stdout.trim() === "" && /config file not found:|failed to load config from /.test(result.stderr);
517
- }
518
- export async function runSessionCommandData(options) {
519
- const { args, cwd, env, namespace, pinNamespace, sessionName, signal, stdin, throwOnFailure, timeoutMs } = options;
520
- if (!sessionName || sessionCommandObservation.getStore()?.allow(options) === false)
521
- return undefined;
522
- const processResult = await runAgentBrowserProcess({
523
- args: ["--json", ...(namespace !== undefined || pinNamespace ? ["--namespace", namespace ?? ""] : []), "--session", sessionName, ...args],
524
- cwd, env, signal, stdin, timeoutMs,
525
- });
526
- try {
527
- options.onProcessResult?.(processResult);
528
- const parsed = await parseAgentBrowserEnvelope({ stdout: processResult.stdout, stdoutPath: processResult.stdoutSpillPath });
529
- sessionCommandObservation.getStore()?.observe(options, processResult, parsed.envelope);
530
- if (processResult.aborted || processResult.spawnError || processResult.exitCode !== 0) {
531
- if (throwOnFailure) {
532
- const reason = processResult.aborted ? "command was aborted" : processResult.spawnError ? "process could not start" : `process exited with code ${processResult.exitCode}`;
533
- throw new Error(`agent-browser ${reason}`);
534
- }
535
- return undefined;
536
- }
537
- if (parsed.parseError || parsed.envelope?.success === false || detectConfirmationRequired(parsed.envelope?.data)) {
538
- if (throwOnFailure)
539
- throw new Error(parsed.parseError ? "agent-browser returned invalid structured output" : "agent-browser reported failure or requires confirmation");
540
- return undefined;
541
- }
542
- observeNativeWebMcp(parsed.envelope?.data);
543
- return parsed.envelope?.data;
544
- }
545
- finally {
546
- if (processResult.stdoutSpillPath)
547
- await rm(processResult.stdoutSpillPath, { force: true }).catch(() => undefined);
548
- }
549
- }
550
- export async function collectOpenResultTabCorrection(options) {
551
- const { cwd, namespace, sessionName, signal, targetTitle, targetUrl } = options;
552
- const tabData = await runSessionCommandData({ args: ["tab", "list"], cwd, namespace, sessionName, signal });
553
- if (!isRecord(tabData) || !Array.isArray(tabData.tabs)) {
554
- return undefined;
555
- }
556
- const tabs = tabData.tabs.filter(isRecord).map((tab, index) => ({
557
- active: tab.active === true,
558
- index: typeof tab.index === "number" ? tab.index : index,
559
- label: typeof tab.label === "string" ? tab.label : undefined,
560
- tabId: typeof tab.tabId === "string" ? tab.tabId : undefined,
561
- targetId: typeof tab.targetId === "string" ? tab.targetId : undefined,
562
- title: typeof tab.title === "string" ? tab.title : undefined,
563
- url: typeof tab.url === "string" ? tab.url : undefined,
564
- }));
565
- return chooseOpenResultTabCorrection({ tabs, targetTitle, targetUrl });
566
- }
567
- function mapTabData(tabData) {
568
- if (!isRecord(tabData) || !Array.isArray(tabData.tabs))
569
- return undefined;
570
- return tabData.tabs.filter(isRecord).map((tab, index) => ({
571
- active: tab.active === true,
572
- index: typeof tab.index === "number" ? tab.index : index,
573
- label: typeof tab.label === "string" ? tab.label : undefined,
574
- tabId: typeof tab.tabId === "string" ? tab.tabId : undefined,
575
- targetId: typeof tab.targetId === "string" ? tab.targetId : undefined,
576
- title: typeof tab.title === "string" ? tab.title : undefined,
577
- url: typeof tab.url === "string" ? tab.url : undefined,
578
- }));
579
- }
580
- export async function collectSessionTabTarget(options) {
581
- const tabs = mapTabData(await runSessionCommandData({ ...options, args: ["tab", "list"] }));
582
- const active = tabs?.find((tab) => tab.active);
583
- const observedUrl = normalizeComparableUrl(options.target.url);
584
- if (normalizeComparableUrl(active?.url) !== observedUrl && tabs?.some((tab) => normalizeComparableUrl(tab.url) === observedUrl))
585
- return options.target;
586
- return active?.targetId
587
- ? { ...options.target, targetId: active.targetId }
588
- : options.target;
589
- }
590
- export async function collectSessionTabSelection(options) {
591
- const { cwd, namespace, sessionName, signal, target } = options;
592
- const tabData = await runSessionCommandData({ args: ["tab", "list"], cwd, namespace, sessionName, signal });
593
- const tabs = mapTabData(tabData);
594
- return tabs ? selectSessionTargetTab({ tabs, target }) : undefined;
595
- }
596
- export async function ensureSessionTabTarget(options) {
597
- const readTabs = async () => mapTabData(await runSessionCommandData({ ...options, args: ["tab", "list"] }));
598
- const tabs = await readTabs();
599
- const active = tabs?.find((tab) => tab.active);
600
- const correction = tabs && selectAnySessionTargetTab({ tabs, target: options.target });
601
- const error = "agent-browser could not re-select and verify the intended tab before running the command. Run tab list and select the intended tab, then snapshot -i before retrying.";
602
- if (!correction)
603
- return { error };
604
- const verifyUrl = async (tab) => {
605
- if (normalizeComparableUrl(tab.url) === normalizeComparableUrl(options.target.url))
606
- return true;
607
- // Native tab metadata can retain the attempted URL while get url reports Chrome's error page.
608
- const data = await runSessionCommandData({ ...options, args: ["get", "url"] });
609
- return normalizeComparableUrl(extractStringResultField(data, "url")) === normalizeComparableUrl(options.target.url);
610
- };
611
- // Native tab selection clears refs and frame scope even when selecting the current tab.
612
- if (active && getTabSelection(active)?.selectedTab === correction.selectedTab)
613
- return await verifyUrl(active) ? {} : { error };
614
- if (!await applyOpenResultTabCorrection({ ...options, correction }))
615
- return { correction, error };
616
- const selected = (await readTabs())?.find((tab) => tab.active);
617
- return selected && getTabSelection(selected)?.selectedTab === correction.selectedTab && await verifyUrl(selected)
618
- ? { correction }
619
- : { correction, error };
620
- }
621
- export async function applyOpenResultTabCorrection(options) {
622
- const { correction, cwd, namespace, sessionName, signal } = options;
623
- const result = await runSessionCommandData({
624
- args: ["tab", correction.selectedTab],
625
- cwd,
626
- namespace,
627
- sessionName,
628
- signal,
629
- });
630
- return result === undefined ? undefined : correction;
631
- }
632
- export function isLiveElectronRendererTarget(target) {
633
- const normalizedUrl = normalizeComparableUrl(target.url);
634
- if (!normalizedUrl || normalizedUrl === "about:blank" || normalizedUrl.startsWith("devtools://"))
635
- return false;
636
- return target.type === undefined || target.type === "page" || target.type === "webview";
637
- }
638
- export function getLiveElectronRendererTargets(targets) {
639
- return targets.filter(isLiveElectronRendererTarget);
640
- }
641
- export function electronTargetLabel(target) {
642
- if (!target)
643
- return "unknown target";
644
- return [target.title, target.url, target.id].find((value) => typeof value === "string" && value.trim().length > 0) ?? "unknown target";
645
- }
646
- export function getActiveElectronRecords(records) {
647
- return [...records.values()].filter((record) => record.cleanupState === "active" || record.cleanupState === "dead" || record.cleanupState === "partial" || record.cleanupState === "failed");
648
- }
649
- export function findElectronLaunchRecordForSession(sessionName, records, namespace) {
650
- if (!sessionName)
651
- return undefined;
652
- const sessionKey = getAgentBrowserSessionIdentityKey(sessionName, namespace);
653
- return getActiveElectronRecords(records).find((record) => record.sessionName && getAgentBrowserSessionIdentityKey(record.sessionName, record.namespace) === sessionKey);
654
- }
655
- function buildElectronReattachNextAction(record, liveTarget) {
656
- const endpoint = liveTarget?.webSocketDebuggerUrl ?? record.webSocketDebuggerUrl ?? String(record.port);
657
- return {
658
- id: "reattach-electron-launch",
659
- params: { args: ["connect", endpoint], sessionMode: "fresh" },
660
- reason: "Attach a fresh managed session to the same wrapper-tracked Electron debug endpoint when the current session no longer matches the live renderer.",
661
- safety: "Creates a new managed browser session; it does not mutate the Electron app. Keep the launchId for later status and cleanup.",
662
- tool: "agent_browser",
663
- };
664
- }
665
- export function buildElectronMismatchNextActions(record, liveTarget) {
666
- const baseActions = buildAgentBrowserNextActions({
667
- electron: { launchId: record.launchId, sessionName: record.sessionName, status: record.cleanupState },
668
- resultCategory: "success",
669
- successCategory: "completed",
670
- }) ?? [];
671
- const reattachAction = buildElectronReattachNextAction(record, liveTarget);
672
- const actions = [];
673
- for (const action of baseActions) {
674
- actions.push(action);
675
- if (action.id === "probe-electron-launch")
676
- actions.push(reattachAction);
677
- }
678
- if (!actions.some((action) => action.id === reattachAction.id))
679
- actions.push(reattachAction);
680
- return actions;
681
- }
682
- export function buildElectronSessionMismatch(options) {
683
- const liveTargets = getLiveElectronRendererTargets(options.statusTargets);
684
- if (liveTargets.length === 0)
685
- return undefined;
686
- const managedUrl = normalizeComparableUrl(options.managedSession.url);
687
- const matchingLiveTarget = managedUrl
688
- ? liveTargets.find((target) => normalizeComparableUrl(target.url) === managedUrl)
689
- : undefined;
690
- if (matchingLiveTarget)
691
- return undefined;
692
- const liveTarget = liveTargets[0];
693
- let reason;
694
- if (isAboutBlankUrl(options.managedSession.url)) {
695
- reason = "managed-session-about-blank-while-launch-target-live";
696
- }
697
- else if (options.record.sessionName && options.record.sessionName !== options.managedSession.sessionName) {
698
- reason = "launch-session-not-current";
99
+ if (options.subcommand === "start") {
100
+ options.traceOwners.set(sessionName, owner);
699
101
  }
700
- else if (managedUrl) {
701
- reason = "managed-session-target-not-in-launch-status";
102
+ if (options.subcommand === "stop" && options.traceOwners.get(sessionName) === owner) {
103
+ options.traceOwners.delete(sessionName);
702
104
  }
703
- if (!reason)
704
- return undefined;
705
- const managedDescription = options.managedSession.url ?? options.managedSession.title ?? options.managedSession.sessionName;
706
- const liveDescription = electronTargetLabel(liveTarget);
707
- const summary = reason === "launch-session-not-current"
708
- ? `Electron session mismatch: current managed session ${options.managedSession.sessionName} is not the wrapper launch session ${options.record.sessionName ?? "unknown"}, while launch ${options.record.launchId} still has live target ${liveDescription}.`
709
- : `Electron session mismatch: managed session ${options.managedSession.sessionName} is on ${managedDescription}, but launch ${options.record.launchId} still has live target ${liveDescription}.`;
710
- const nextActions = buildElectronMismatchNextActions(options.record, liveTarget);
711
- return {
712
- launchId: options.record.launchId,
713
- liveTarget,
714
- managedSession: options.managedSession,
715
- nextActionIds: nextActions.map((action) => action.id),
716
- reason,
717
- sessionName: options.record.sessionName,
718
- statusTargets: options.statusTargets,
719
- summary,
720
- };
721
105
  }
722
- export function formatElectronSessionMismatchText(mismatch) {
723
- return `${mismatch.summary}\nNext: run electron.status/electron.probe with launchId ${mismatch.launchId}, reattach with the reattach-electron-launch nextAction if needed, or cleanup when finished.`;
724
- }
725
- export function shouldInspectElectronPostCommandHealth(command) {
726
- return isElectronPostCommandHealthCommand(command);
727
- }
728
- export function buildElectronLifecycleNextActions(record) {
729
- return buildAgentBrowserNextActions({
730
- electron: { launchId: record.launchId, sessionName: record.sessionName, status: record.cleanupState },
731
- resultCategory: "success",
732
- successCategory: "completed",
733
- }) ?? [];
734
- }
735
- export function buildElectronPostCommandHealthDiagnostic(options) {
736
- let reason;
737
- if (options.status.pidAlive === false)
738
- reason = "process-dead";
739
- else if (!options.status.portAlive)
740
- reason = "debug-port-dead";
741
- else if (isAboutBlankUrl(options.target?.url) && getLiveElectronRendererTargets(options.status.targets).length === 0)
742
- reason = "about-blank-no-live-target";
743
- if (!reason)
744
- return undefined;
745
- const nextActions = buildElectronLifecycleNextActions(options.record);
746
- const commandText = options.command ? `${options.command} command` : "command";
747
- const statusText = `${options.status.portAlive ? "debug port alive" : "debug port dead"}${options.status.pidAlive === undefined ? "" : options.status.pidAlive ? ", pid alive" : ", pid dead"}`;
748
- const summary = `Electron lifecycle warning: ${commandText} completed, but launch ${options.record.launchId} is no longer healthy (${statusText}).`;
749
- return {
750
- appName: options.record.appName,
751
- command: options.command,
752
- launchId: options.record.launchId,
753
- nextActionIds: nextActions.map((action) => action.id),
754
- reason,
755
- sessionName: options.record.sessionName,
756
- status: options.status,
757
- summary,
758
- target: options.target,
759
- };
760
- }
761
- export function formatElectronPostCommandHealthText(diagnostic) {
762
- if (!diagnostic)
763
- return undefined;
764
- const lines = [diagnostic.summary];
765
- if (diagnostic.target?.url)
766
- lines.push(`Current browser session target: ${diagnostic.target.url}.`);
767
- lines.push(`Status: ${diagnostic.status.portAlive ? "debug port alive" : "debug port dead"}${diagnostic.status.pidAlive === undefined ? "" : diagnostic.status.pidAlive ? ", pid alive" : ", pid dead"}; ${diagnostic.status.targets.length} CDP target(s).`);
768
- lines.push(`Next: run electron.status/electron.probe with launchId ${diagnostic.launchId}, cleanup the wrapper-owned launch if dead, or relaunch the app.`);
769
- return lines.join("\n");
770
- }
771
- export function buildElectronIdentifiers(record) {
772
- return { appName: record.appName, launchId: record.launchId, sessionName: record.sessionName };
773
- }
774
- export function buildElectronRefFreshnessNextActions(sessionName) {
775
- return [{
776
- id: "refresh-electron-refs-after-rerender",
777
- params: { args: sessionName ? ["--session", sessionName, "snapshot", "-i"] : ["snapshot", "-i"] },
778
- reason: "Electron UIs often rerender without changing URL; refresh refs before using old @e handles again.",
779
- safety: "Read-only snapshot; avoids stale same-URL refs after quick-pick, modal, theme, or editor rerenders.",
780
- tool: "agent_browser",
781
- }];
782
- }
783
- export function buildElectronRefFreshnessDiagnostic(options) {
784
- if (!options.record || !shouldInspectElectronPostCommandHealth(options.command))
785
- return undefined;
786
- if (getGuardedRefUsage(options.commandTokens, options.stdin).length === 0)
787
- return undefined;
788
- const nextActions = buildElectronRefFreshnessNextActions(options.sessionName);
789
- return {
790
- command: options.command,
791
- launchId: options.record.launchId,
792
- nextActionIds: nextActions.map((action) => action.id),
793
- sessionName: options.sessionName,
794
- summary: `Electron ref freshness: ${options.command ?? "mutation"} used page-scoped refs in an Electron UI. Re-run snapshot -i before reusing old @e refs, even if the URL did not change.`,
795
- };
796
- }
797
- export function formatElectronRefFreshnessText(diagnostic) {
798
- return diagnostic?.summary;
799
- }
800
- export { extractBatchResultCommand };
801
106
  export function getPersistentSessionArtifactStore(ctx) {
802
- const sessionDir = typeof ctx.sessionManager.getSessionDir === "function" ? ctx.sessionManager.getSessionDir() : undefined;
107
+ const sessionDir = typeof ctx.sessionManager.getSessionDir === "function"
108
+ ? ctx.sessionManager.getSessionDir()
109
+ : undefined;
803
110
  const sessionId = ctx.sessionManager.getSessionId();
804
- return sessionDir && sessionId ? { sessionDir, sessionId } : undefined;
111
+ return sessionDir !== undefined &&
112
+ sessionDir.length > 0 &&
113
+ sessionId !== undefined &&
114
+ sessionId.length > 0
115
+ ? { sessionDir, sessionId }
116
+ : undefined;
805
117
  }