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
@@ -5,33 +5,43 @@ function resolveArtifactPath(cwd, path) {
5
5
  return isAbsolute(path) ? path : resolve(cwd, path);
6
6
  }
7
7
  function manifestContainsArtifact(manifest, cwd, artifact) {
8
- if (!manifest)
8
+ if (!manifest) {
9
9
  return false;
10
+ }
10
11
  const requestedAbsolutePath = resolveArtifactPath(cwd, artifact.path);
11
12
  const expectedKind = artifact.kind === "screenshot" ? "image" : "video";
12
13
  return manifest.entries.some((entry) => {
13
14
  const entryAbsolutePath = entry.absolutePath ?? resolveArtifactPath(cwd, entry.path);
14
- return entry.storageScope === "explicit-path" && entry.kind === expectedKind && entryAbsolutePath === requestedAbsolutePath && entry.retentionState === "live" && entry.exists === true;
15
+ return (entry.storageScope === "explicit-path" &&
16
+ entry.kind === expectedKind &&
17
+ entryAbsolutePath === requestedAbsolutePath &&
18
+ entry.retentionState === "live" &&
19
+ entry.exists === true);
15
20
  });
16
21
  }
17
22
  async function isArtifactRequired(artifact) {
18
- if (artifact.required)
23
+ if (artifact.required) {
19
24
  return true;
20
- return artifact.kind === "recording" && await executableExistsOnPath("ffmpeg");
25
+ }
26
+ return artifact.kind === "recording" && (await executableExistsOnPath("ffmpeg"));
21
27
  }
22
28
  export async function findRequestedArtifactCloseViolation(options) {
23
- if (!isCloseCommand(options.command))
29
+ if (!isCloseCommand(options.command)) {
24
30
  return undefined;
25
- const missingArtifacts = [];
26
- for (const artifact of options.promptPolicy.requestedArtifacts) {
27
- if (!await isArtifactRequired(artifact))
28
- continue;
29
- if (!manifestContainsArtifact(options.artifactManifest, options.cwd, artifact))
30
- missingArtifacts.push(artifact);
31
31
  }
32
- if (missingArtifacts.length === 0)
32
+ const requirements = await Promise.all(options.promptPolicy.requestedArtifacts.map(async (artifact) => ({
33
+ artifact,
34
+ required: await isArtifactRequired(artifact),
35
+ })));
36
+ const missingArtifacts = requirements
37
+ .filter(({ artifact, required }) => required && !manifestContainsArtifact(options.artifactManifest, options.cwd, artifact))
38
+ .map(({ artifact }) => artifact);
39
+ if (missingArtifacts.length === 0) {
33
40
  return undefined;
34
- const missingList = missingArtifacts.map((artifact) => `${artifact.kind}: ${artifact.path}`).join(", ");
41
+ }
42
+ const missingList = missingArtifacts
43
+ .map((artifact) => `${artifact.kind}: ${artifact.path}`)
44
+ .join(", ");
35
45
  return {
36
46
  message: `Blocked browser close because requested artifact path${missingArtifacts.length === 1 ? " is" : "s are"} missing or unverified: ${missingList}. Save the requested artifact path first, or report why an optional artifact is unavailable before closing.`,
37
47
  missingArtifacts,
@@ -0,0 +1,198 @@
1
+ import { resolve } from "node:path";
2
+ import { getAgentBrowserSessionIdentityKey } from "../../argv-grammar.js";
3
+ import { getRecordCommandOperands } from "../../command-taxonomy.js";
4
+ import { isRecord } from "../../parsing.js";
5
+ import { extractEnvelopeErrorText } from "../../results/envelope.js";
6
+ import { getRecordingReceipt } from "../../results/recording.js";
7
+ import { getUpstreamEffectiveBatchSteps } from "../batch-stdin.js";
8
+ import { diagnosticErrorText } from "./diagnostic-values.js";
9
+ import { runSessionCommandData } from "./session-state.js";
10
+ export function isRecordingStop(tokens) {
11
+ return tokens[0] === "record" && tokens[1] === "stop";
12
+ }
13
+ function rowError(row) {
14
+ return isRecord(row) ? row.error : undefined;
15
+ }
16
+ function rowResult(row) {
17
+ return isRecord(row) && isRecord(row.result) ? row.result : undefined;
18
+ }
19
+ function stopNeedsRecovery(options, row) {
20
+ return (options.processResult.timedOut ||
21
+ /no recording in progress/i.test(extractEnvelopeErrorText(rowError(row) ?? options.envelope?.error) ?? ""));
22
+ }
23
+ function reservationForStart(options, step, row) {
24
+ if (step[0] !== "record" || !["start", "restart"].includes(step[1] ?? "")) {
25
+ return undefined;
26
+ }
27
+ if (isRecord(row) && row.success === false) {
28
+ return undefined;
29
+ }
30
+ return buildStartReservation(options, step, rowResult(row));
31
+ }
32
+ function buildStartReservation(options, step, started) {
33
+ const path = typeof started?.path === "string" ? started.path : getRecordCommandOperands(step).path;
34
+ if (path === undefined ||
35
+ path === "" ||
36
+ options.sessionName === undefined ||
37
+ options.sessionName === "") {
38
+ return undefined;
39
+ }
40
+ return {
41
+ absolutePath: resolve(options.cwd, path),
42
+ cwd: options.cwd,
43
+ path,
44
+ namespace: options.namespace,
45
+ sessionName: options.sessionName,
46
+ recordingId: typeof started?.recordingId === "string" ? started.recordingId : undefined,
47
+ startedAtMs: options.artifactRunStartedAtMs,
48
+ };
49
+ }
50
+ function recoverySource(options) {
51
+ const batch = options.commandTokens[0] === "batch";
52
+ return {
53
+ batch,
54
+ steps: batch
55
+ ? getUpstreamEffectiveBatchSteps(options.commandTokens, options.stdin)
56
+ : [options.commandTokens],
57
+ rows: batch && Array.isArray(options.envelope?.data) ? options.envelope.data : undefined,
58
+ };
59
+ }
60
+ function originalAttempt(options, stopRow) {
61
+ const error = options.processResult.timedOut
62
+ ? `Record stop timed out after ${options.processResult.timeoutMs ?? "undefined"} ms.`
63
+ : (extractEnvelopeErrorText(rowError(stopRow) ?? options.envelope?.error) ??
64
+ "Record stop did not return a receipt.");
65
+ return {
66
+ success: false,
67
+ exitCode: options.processResult.exitCode,
68
+ timedOut: options.processResult.timedOut,
69
+ error,
70
+ parseError: options.parseError,
71
+ };
72
+ }
73
+ function recordingAttemptWasInterrupted(options) {
74
+ return (options.processResult.aborted ||
75
+ (options.signal?.aborted ?? false) ||
76
+ !options.processResult.agentBrowserStarted);
77
+ }
78
+ export function planRecordingRecovery(options) {
79
+ if (recordingAttemptWasInterrupted(options)) {
80
+ return undefined;
81
+ }
82
+ const { batch, steps, rows } = recoverySource(options);
83
+ const stopIndex = steps.reduce((last, step, index) => isRecordingStop(step) && stopNeedsRecovery(options, rows?.at(index)) ? index : last, -1);
84
+ if (stopIndex < 0) {
85
+ return undefined;
86
+ }
87
+ let expected = options.reservation;
88
+ for (const [index, step] of steps.slice(0, stopIndex).entries()) {
89
+ expected = reservationForStart(options, step, rows?.at(index)) ?? expected;
90
+ }
91
+ return {
92
+ batch,
93
+ rows,
94
+ stopIndex,
95
+ expected,
96
+ attempt: originalAttempt(options, rows?.at(stopIndex)),
97
+ };
98
+ }
99
+ function receiptMatches(receipt, expected, nowMs) {
100
+ if (resolve(expected.cwd, receipt.path) !== expected.absolutePath) {
101
+ return false;
102
+ }
103
+ if (expected.recordingId !== undefined && expected.recordingId !== "") {
104
+ return receipt.recordingId === expected.recordingId;
105
+ }
106
+ const startedAtMs = Date.parse(receipt.capture.startedAt ?? "");
107
+ return (expected.startedAtMs !== undefined &&
108
+ startedAtMs >= expected.startedAtMs &&
109
+ startedAtMs <= nowMs);
110
+ }
111
+ function sameNativeSession(info, options) {
112
+ if (!isRecord(info) || typeof info.session !== "string" || options.sessionName === undefined) {
113
+ return false;
114
+ }
115
+ return (getAgentBrowserSessionIdentityKey(info.session, typeof info.namespace === "string" ? info.namespace : undefined) === getAgentBrowserSessionIdentityKey(options.sessionName, options.namespace));
116
+ }
117
+ function reconcileNativeReceipts(info, options, expected) {
118
+ const recordings = nativeRecordingState(info);
119
+ const current = getRecordingReceipt(recordings?.current);
120
+ const unavailable = {
121
+ current,
122
+ status: "unavailable",
123
+ reason: "Native session info did not provide a matching recording receipt. File presence alone cannot prove successful recording finalization.",
124
+ };
125
+ if (!recordings) {
126
+ return unavailable;
127
+ }
128
+ if (!sameNativeSession(info, options)) {
129
+ return {
130
+ current,
131
+ status: "mismatch",
132
+ reason: "Native session info reported a different namespace/session; its recording receipt was not used.",
133
+ };
134
+ }
135
+ if (!expected) {
136
+ return unavailable;
137
+ }
138
+ for (const candidate of [recordings.current, recordings.last]) {
139
+ const receipt = getRecordingReceipt(candidate);
140
+ if (receipt && receiptMatches(receipt, expected, Date.now())) {
141
+ return { ...unavailable, receipt, data: candidate };
142
+ }
143
+ }
144
+ return {
145
+ current,
146
+ status: "mismatch",
147
+ reason: "Native recording IDs, paths or capture windows did not match this attempt; unrelated receipt measurements were not used.",
148
+ };
149
+ }
150
+ function nativeRecordingState(info) {
151
+ const runtime = isRecord(info) && isRecord(info.runtime) ? info.runtime : undefined;
152
+ return isRecord(runtime?.recording) ? runtime.recording : undefined;
153
+ }
154
+ export async function collectRecordingReceiptEvidence(options, expected) {
155
+ try {
156
+ const info = await runSessionCommandData({
157
+ args: ["session", "info"],
158
+ cwd: options.cwd,
159
+ namespace: options.namespace,
160
+ pinNamespace: true,
161
+ sessionName: options.sessionName,
162
+ signal: options.signal,
163
+ timeoutMs: 2_000,
164
+ });
165
+ return reconcileNativeReceipts(info, options, expected);
166
+ }
167
+ catch (error) {
168
+ return {
169
+ status: "unavailable",
170
+ reason: `Native session info was unavailable: ${diagnosticErrorText(error)}. File presence alone cannot prove successful recording finalization.`,
171
+ };
172
+ }
173
+ }
174
+ export function anotherTakeUsesPath(evidence, expected) {
175
+ const { current, receipt } = evidence;
176
+ return (current !== undefined &&
177
+ receipt !== undefined &&
178
+ expected !== undefined &&
179
+ current.recordingId !== receipt.recordingId &&
180
+ resolve(expected.cwd, current.path) === expected.absolutePath);
181
+ }
182
+ function encodedOutputIsComplete(receipt) {
183
+ return (receipt.success === true &&
184
+ receipt.output.encoderSucceeded === true &&
185
+ receipt.output.encodedFrames !== null &&
186
+ receipt.output.encodedFrames > 0 &&
187
+ receipt.file.exists === true &&
188
+ receipt.file.sizeBytes !== null &&
189
+ receipt.file.sizeBytes > 0);
190
+ }
191
+ export function recordingHasTerminalMeasurements(evidence, expected) {
192
+ const receipt = evidence.receipt;
193
+ return (receipt !== undefined &&
194
+ encodedOutputIsComplete(receipt) &&
195
+ Number.isFinite(Date.parse(receipt.capture.startedAt ?? "")) &&
196
+ Number.isFinite(Date.parse(receipt.capture.endedAt ?? "")) &&
197
+ !anotherTakeUsesPath(evidence, expected));
198
+ }
@@ -0,0 +1,154 @@
1
+ import { buildToolPresentation } from "../../results/presentation.js";
2
+ import { isRecord } from "../../parsing.js";
3
+ import { anotherTakeUsesPath, } from "./recording-receipt-reconciliation.js";
4
+ export function recordingRecoveryData(plan, evidence) {
5
+ return (evidence.data ??
6
+ (plan.expected
7
+ ? { path: plan.expected.absolutePath, recordingId: plan.expected.recordingId, success: null }
8
+ : undefined));
9
+ }
10
+ export async function presentRecordingReceipt(options, plan, evidence, terminalMeasurements) {
11
+ const expected = plan.expected;
12
+ const data = recordingRecoveryData(plan, evidence);
13
+ return buildToolPresentation({
14
+ modelVisible: options.modelVisible,
15
+ artifactManifest: options.artifactManifest,
16
+ artifactMinUpdatedAtMs: expected?.startedAtMs ?? options.artifactRunStartedAtMs,
17
+ artifactMaxUpdatedAtMs: Date.now(),
18
+ artifactRequest: expected
19
+ ? {
20
+ path: expected.path,
21
+ absolutePath: expected.absolutePath,
22
+ status: terminalMeasurements ? undefined : "unverified",
23
+ }
24
+ : undefined,
25
+ commandInfo: { command: "record", subcommand: "stop" },
26
+ cwd: expected?.cwd ?? options.cwd,
27
+ envelope: { success: evidence.receipt?.success === true, data },
28
+ namespace: options.namespace,
29
+ sessionName: options.sessionName,
30
+ recordingPending: evidence.receipt
31
+ ? evidence.receipt.success === null
32
+ : options.processResult.timedOut,
33
+ });
34
+ }
35
+ export function classifyRecordingRecovery(evidence, plan, verified) {
36
+ const receipt = evidence.receipt;
37
+ if (!receipt) {
38
+ return { status: evidence.status, reason: evidence.reason };
39
+ }
40
+ if (verified) {
41
+ return {
42
+ status: "recovered",
43
+ reason: "Native terminal success and encoder measurements match the expected recording and the verified file.",
44
+ };
45
+ }
46
+ if (receipt.success === null) {
47
+ return {
48
+ status: "pending",
49
+ reason: "The matching native take is still pending; no terminal success was reported.",
50
+ };
51
+ }
52
+ if (!receipt.success) {
53
+ return {
54
+ status: "failed",
55
+ reason: `The matching native receipt reports failure: ${receipt.error ?? "unknown encoder/capture failure"}.`,
56
+ };
57
+ }
58
+ return {
59
+ status: "unverified",
60
+ reason: anotherTakeUsesPath(evidence, plan.expected)
61
+ ? "Another active recording uses this path. The previous receipt cannot verify the new take's file."
62
+ : "A matching receipt was found, but successful encoding and a matching fresh file could not both be verified.",
63
+ };
64
+ }
65
+ export function repairRecordingEnvelope(options, plan, data, verified) {
66
+ if (plan.rows) {
67
+ const rows = plan.rows.map((row, index) => index === plan.stopIndex && isRecord(row)
68
+ ? { ...row, result: data, success: verified, error: verified ? undefined : row.error }
69
+ : row);
70
+ const healed = verified &&
71
+ !options.processResult.timedOut &&
72
+ rows.every((row) => isRecord(row) && row.success === true);
73
+ return {
74
+ healed,
75
+ envelope: {
76
+ success: healed,
77
+ data: rows,
78
+ error: healed ? undefined : options.envelope?.error,
79
+ },
80
+ };
81
+ }
82
+ if (!plan.batch) {
83
+ return {
84
+ healed: verified,
85
+ envelope: { success: verified, data, error: verified ? undefined : plan.attempt.error },
86
+ };
87
+ }
88
+ return { healed: false, envelope: options.envelope };
89
+ }
90
+ function recordingSessionArgs(options, command) {
91
+ return [
92
+ "--namespace",
93
+ options.namespace ?? "",
94
+ "--session",
95
+ options.sessionName ?? "",
96
+ ...command,
97
+ ];
98
+ }
99
+ function pendingTakeIsCurrent(evidence, recovery) {
100
+ return (evidence.current !== undefined &&
101
+ evidence.receipt !== undefined &&
102
+ evidence.current.recordingId === evidence.receipt.recordingId &&
103
+ recovery.status === "pending");
104
+ }
105
+ function buildRecordingFollowups(options, evidence, recovery) {
106
+ if (options.sessionName === undefined || options.sessionName === "") {
107
+ return [];
108
+ }
109
+ const actions = recovery.healed
110
+ ? []
111
+ : [
112
+ {
113
+ id: "inspect-recording-receipt",
114
+ tool: "agent_browser",
115
+ params: { args: recordingSessionArgs(options, ["session", "info"]) },
116
+ reason: "Inspect the native current/last recording receipts for this exact session.",
117
+ safety: "Read-only status; does not launch or retarget the browser. Do not infer encoding success from an existing file.",
118
+ },
119
+ ];
120
+ if (pendingTakeIsCurrent(evidence, recovery)) {
121
+ actions.push({
122
+ id: "stop-pending-recording",
123
+ tool: "agent_browser",
124
+ params: { args: recordingSessionArgs(options, ["record", "stop"]) },
125
+ reason: `Finalize the still-current native recording ${evidence.receipt?.recordingId ?? "null"}; it has not reported a terminal outcome.`,
126
+ safety: "Run only while this same recording remains current. No repeated stop was dispatched during recovery.",
127
+ });
128
+ }
129
+ return actions;
130
+ }
131
+ export function finishRecordingPresentation(options, presentation, evidence, recovery) {
132
+ const content = [...presentation.content];
133
+ if (options.modelVisible !== false) {
134
+ content.unshift({
135
+ type: "text",
136
+ text: `Recording receipt recovery (${recovery.status}): ${recovery.reason}\nOriginal attempt: ${recovery.attempt.error}`,
137
+ });
138
+ }
139
+ const failure = recovery.healed
140
+ ? {}
141
+ : {
142
+ resultCategory: "failure",
143
+ failureCategory: options.processResult.timedOut ? "timeout" : "upstream-error",
144
+ successCategory: undefined,
145
+ summary: `${recovery.attempt.error} ${recovery.reason}`,
146
+ };
147
+ return {
148
+ ...presentation,
149
+ ...failure,
150
+ content,
151
+ nextActions: buildRecordingFollowups(options, evidence, recovery),
152
+ recordingRecovery: recovery,
153
+ };
154
+ }
@@ -1,163 +1,80 @@
1
- import { resolve } from "node:path";
2
- import { getAgentBrowserSessionIdentityKey } from "../../argv-grammar.js";
3
- import { getRecordCommandOperands } from "../../command-taxonomy.js";
4
- import { isRecord } from "../../parsing.js";
5
- import { isPendingRecordingArtifact, mergeSessionArtifactManifest } from "../../results/artifact-manifest.js";
6
- import { extractEnvelopeErrorText } from "../../results/envelope.js";
1
+ import { isPendingRecordingArtifact, mergeSessionArtifactManifest, } from "../../results/artifact-manifest.js";
7
2
  import { appendUniqueAgentBrowserNextActions } from "../../results/next-actions.js";
8
- import { buildToolPresentation } from "../../results/presentation.js";
9
- import { buildArtifactVerificationSummary, buildManifestEntriesForFileArtifacts } from "../../results/presentation/artifacts.js";
10
- import { getRecordingReceipt } from "../../results/recording.js";
11
- import { getUpstreamEffectiveBatchSteps } from "../batch-stdin.js";
12
- import { runSessionCommandData } from "./session-state.js";
13
- function isStop(tokens) {
14
- return tokens[0] === "record" && tokens[1] === "stop";
15
- }
16
- function receiptMatches(receipt, expected, nowMs) {
17
- if (resolve(expected.cwd, receipt.path) !== expected.absolutePath)
18
- return false;
19
- if (expected.recordingId)
20
- return receipt.recordingId === expected.recordingId;
21
- const startedAtMs = Date.parse(receipt.capture.startedAt ?? "");
22
- return expected.startedAtMs !== undefined && startedAtMs >= expected.startedAtMs && startedAtMs <= nowMs;
23
- }
3
+ import { buildArtifactVerificationSummary, buildManifestEntriesForFileArtifacts, } from "../../results/presentation/artifacts.js";
4
+ import { collectRecordingReceiptEvidence, isRecordingStop, planRecordingRecovery, recordingHasTerminalMeasurements, } from "./recording-receipt-reconciliation.js";
5
+ import { classifyRecordingRecovery, finishRecordingPresentation, presentRecordingReceipt, repairRecordingEnvelope, recordingRecoveryData, } from "./recording-recovery-presentation.js";
24
6
  export async function recoverRecordingStop(options) {
25
- const batch = options.commandTokens[0] === "batch";
26
- const steps = batch ? getUpstreamEffectiveBatchSteps(options.commandTokens, options.stdin) : [options.commandTokens];
27
- const rows = batch && Array.isArray(options.envelope?.data) ? options.envelope.data : undefined;
28
- const stopIndex = steps.reduce((last, step, index) => isStop(step) && (options.processResult.timedOut
29
- || /no recording in progress/i.test(extractEnvelopeErrorText(rows?.[index]?.error ?? options.envelope?.error) ?? "")) ? index : last, -1);
30
- if (stopIndex < 0 || options.processResult.aborted || options.signal?.aborted || !options.processResult.agentBrowserStarted)
7
+ const plan = planRecordingRecovery(options);
8
+ if (!plan) {
31
9
  return undefined;
32
- let expected = options.reservation;
33
- for (let index = 0; index < stopIndex; index += 1) {
34
- const step = steps[index];
35
- if (step[0] !== "record" || !["start", "restart"].includes(step[1]))
36
- continue;
37
- const row = rows?.[index];
38
- if (isRecord(row) && row.success === false)
39
- continue;
40
- const started = isRecord(row) && isRecord(row.result) ? row.result : undefined;
41
- const path = typeof started?.path === "string" ? started.path : getRecordCommandOperands(step).path;
42
- if (path && options.sessionName)
43
- expected = {
44
- absolutePath: resolve(options.cwd, path), cwd: options.cwd, path, namespace: options.namespace, sessionName: options.sessionName,
45
- recordingId: typeof started?.recordingId === "string" ? started.recordingId : undefined, startedAtMs: options.artifactRunStartedAtMs,
46
- };
47
10
  }
48
- const attemptError = options.processResult.timedOut
49
- ? `Record stop timed out after ${options.processResult.timeoutMs} ms.`
50
- : extractEnvelopeErrorText(rows?.[stopIndex]?.error ?? options.envelope?.error) ?? "Record stop did not return a receipt.";
11
+ const evidence = await collectRecordingReceiptEvidence(options, plan.expected);
12
+ const terminalMeasurements = recordingHasTerminalMeasurements(evidence, plan.expected);
13
+ const presentation = await presentRecordingReceipt(options, plan, evidence, terminalMeasurements);
14
+ const verified = terminalMeasurements &&
15
+ presentation.artifactVerification?.verified === true &&
16
+ presentation.artifacts?.at(0)?.sizeBytes === evidence.receipt?.file.sizeBytes;
17
+ const data = recordingRecoveryData(plan, evidence);
18
+ const repaired = repairRecordingEnvelope(options, plan, data, verified);
51
19
  const recovery = {
52
- attempt: { success: false, exitCode: options.processResult.exitCode, timedOut: options.processResult.timedOut, error: attemptError, parseError: options.parseError },
53
- expected, healed: false, namespace: options.namespace, sessionName: options.sessionName, source: "session-info", status: "unavailable",
54
- reason: "Native session info did not provide a matching recording receipt. File presence alone cannot prove successful recording finalization.",
20
+ attempt: plan.attempt,
21
+ expected: plan.expected,
22
+ healed: repaired.healed,
23
+ namespace: options.namespace,
24
+ sessionName: options.sessionName,
25
+ source: "session-info",
26
+ receipt: evidence.receipt,
27
+ ...classifyRecordingRecovery(evidence, plan, verified),
28
+ };
29
+ return {
30
+ batch: plan.batch,
31
+ envelope: repaired.envelope,
32
+ partialBatch: plan.batch && plan.rows === undefined,
33
+ stopIndex: plan.stopIndex,
34
+ presentation: finishRecordingPresentation(options, presentation, evidence, recovery),
35
+ recovery,
55
36
  };
56
- let info;
57
- try {
58
- info = await runSessionCommandData({ args: ["session", "info"], cwd: options.cwd, namespace: options.namespace, pinNamespace: true, sessionName: options.sessionName, signal: options.signal, timeoutMs: 2_000 });
59
- }
60
- catch (error) {
61
- recovery.reason = `Native session info was unavailable: ${error instanceof Error ? error.message : String(error)}. File presence alone cannot prove successful recording finalization.`;
62
- }
63
- const runtime = isRecord(info) && isRecord(info.runtime) ? info.runtime : undefined;
64
- const recordings = isRecord(runtime?.recording) ? runtime.recording : undefined;
65
- const sameSession = isRecord(info) && typeof info.session === "string" && options.sessionName !== undefined
66
- && getAgentBrowserSessionIdentityKey(info.session, typeof info.namespace === "string" ? info.namespace : undefined)
67
- === getAgentBrowserSessionIdentityKey(options.sessionName, options.namespace);
68
- const current = getRecordingReceipt(recordings?.current);
69
- let matchedData;
70
- if (recordings && sameSession && expected) {
71
- for (const candidate of [recordings.current, recordings.last]) {
72
- const receipt = getRecordingReceipt(candidate);
73
- if (!receipt || !receiptMatches(receipt, expected, Date.now()))
74
- continue;
75
- recovery.receipt = receipt;
76
- matchedData = candidate;
77
- break;
78
- }
79
- if (!recovery.receipt) {
80
- recovery.status = "mismatch";
81
- recovery.reason = "Native recording IDs, paths or capture windows did not match this attempt; unrelated receipt measurements were not used.";
82
- }
83
- }
84
- else if (recordings && !sameSession) {
85
- recovery.status = "mismatch";
86
- recovery.reason = "Native session info reported a different namespace/session; its recording receipt was not used.";
87
- }
88
- const receipt = recovery.receipt;
89
- const currentUsesSamePath = current && receipt && current.recordingId !== receipt.recordingId && expected
90
- && resolve(expected.cwd, current.path) === expected.absolutePath;
91
- const terminalMeasurements = receipt?.success === true && receipt.output.encoderSucceeded === true
92
- && receipt.output.encodedFrames !== null && receipt.output.encodedFrames > 0
93
- && receipt.file.exists === true && receipt.file.sizeBytes !== null && receipt.file.sizeBytes > 0
94
- && Number.isFinite(Date.parse(receipt.capture.startedAt ?? "")) && Number.isFinite(Date.parse(receipt.capture.endedAt ?? ""))
95
- && !currentUsesSamePath;
96
- const data = matchedData ?? (expected ? { path: expected.absolutePath, recordingId: expected.recordingId, success: null } : undefined);
97
- const presentation = await buildToolPresentation({
98
- modelVisible: options.modelVisible,
99
- artifactManifest: options.artifactManifest, artifactMinUpdatedAtMs: expected?.startedAtMs ?? options.artifactRunStartedAtMs, artifactMaxUpdatedAtMs: Date.now(),
100
- artifactRequest: expected ? { path: expected.path, absolutePath: expected.absolutePath, status: terminalMeasurements ? undefined : "unverified" } : undefined,
101
- commandInfo: { command: "record", subcommand: "stop" }, cwd: expected?.cwd ?? options.cwd,
102
- envelope: { success: receipt?.success === true, data }, namespace: options.namespace, sessionName: options.sessionName,
103
- recordingPending: receipt ? receipt.success === null : options.processResult.timedOut,
104
- });
105
- const file = presentation.artifacts?.[0];
106
- const stopVerified = terminalMeasurements && presentation.artifactVerification?.verified === true && file?.sizeBytes === receipt?.file.sizeBytes;
107
- if (receipt) {
108
- recovery.status = stopVerified ? "recovered" : receipt.success === null ? "pending" : receipt.success === false ? "failed" : "unverified";
109
- recovery.reason = stopVerified ? "Native terminal success and encoder measurements match the expected recording and the verified file."
110
- : receipt.success === null ? "The matching native take is still pending; no terminal success was reported."
111
- : receipt.success === false ? `The matching native receipt reports failure: ${receipt.error ?? "unknown encoder/capture failure"}.`
112
- : currentUsesSamePath ? "Another active recording uses this path. The previous receipt cannot verify the new take's file."
113
- : "A matching receipt was found, but successful encoding and a matching fresh file could not both be verified.";
114
- }
115
- let envelope = options.envelope;
116
- if (rows) {
117
- const updatedRows = rows.map((row, index) => index === stopIndex && isRecord(row) ? { ...row, result: data, success: stopVerified === true, error: stopVerified ? undefined : row.error } : row);
118
- recovery.healed = stopVerified === true && !options.processResult.timedOut && updatedRows.every(row => isRecord(row) && row.success === true);
119
- envelope = { success: recovery.healed, data: updatedRows, error: recovery.healed ? undefined : options.envelope?.error };
120
- }
121
- else if (!batch) {
122
- recovery.healed = stopVerified === true;
123
- envelope = { success: recovery.healed, data, error: recovery.healed ? undefined : attemptError };
124
- }
125
- if (!recovery.healed) {
126
- presentation.resultCategory = "failure";
127
- presentation.failureCategory = options.processResult.timedOut ? "timeout" : "upstream-error";
128
- presentation.successCategory = undefined;
129
- presentation.summary = `${attemptError} ${recovery.reason}`;
130
- }
131
- const followups = options.sessionName && !recovery.healed ? [{
132
- id: "inspect-recording-receipt", tool: "agent_browser", params: { args: ["--namespace", options.namespace ?? "", "--session", options.sessionName, "session", "info"] },
133
- reason: "Inspect the native current/last recording receipts for this exact session.", safety: "Read-only status; does not launch or retarget the browser. Do not infer encoding success from an existing file.",
134
- }] : [];
135
- if (current && receipt && current.recordingId === receipt.recordingId && recovery.status === "pending" && options.sessionName)
136
- followups.push({
137
- id: "stop-pending-recording", tool: "agent_browser", params: { args: ["--namespace", options.namespace ?? "", "--session", options.sessionName, "record", "stop"] },
138
- reason: `Finalize the still-current native recording ${receipt.recordingId}; it has not reported a terminal outcome.`, safety: "Run only while this same recording remains current. No repeated stop was dispatched during recovery.",
139
- });
140
- presentation.nextActions = followups;
141
- presentation.recordingRecovery = recovery;
142
- const text = `Recording receipt recovery (${recovery.status}): ${recovery.reason}\nOriginal attempt: ${attemptError}`;
143
- if (options.modelVisible !== false)
144
- presentation.content.unshift({ type: "text", text });
145
- return { batch, envelope, partialBatch: batch && !rows, stopIndex, presentation, recovery };
146
37
  }
147
- export function mergeRecordingRecoveryPresentation(base, result) {
148
- if (!result.batch)
149
- return result.presentation;
150
- const artifacts = result.partialBatch ? [...(base.artifacts ?? []), ...(result.presentation.artifacts ?? [])] : base.artifacts;
151
- const laterRecording = base.batchSteps?.slice(result.stopIndex + 1).some(step => step.artifacts?.some(isPendingRecordingArtifact));
152
- const unrelatedFailure = base.batchFailure && !isStop(base.batchFailure.failedStep.command ?? []);
153
- const nextActions = (base.nextActions ?? []).filter(action => action.id === "stop-pending-recording" ? laterRecording : unrelatedFailure);
38
+ function mergeRecoveryNextActions(base, result) {
39
+ const laterRecording = base.batchSteps
40
+ ?.slice(result.stopIndex + 1)
41
+ .some((step) => step.artifacts?.some(isPendingRecordingArtifact) === true) === true;
42
+ const unrelatedFailure = base.batchFailure !== undefined && !isRecordingStop(base.batchFailure.failedStep.command ?? []);
43
+ const nextActions = (base.nextActions ?? []).filter((action) => action.id === "stop-pending-recording" ? laterRecording : unrelatedFailure);
154
44
  appendUniqueAgentBrowserNextActions(nextActions, result.presentation.nextActions);
45
+ return nextActions;
46
+ }
47
+ export function mergeRecordingRecoveryPresentation(base, result) {
48
+ if (!result.batch) {
49
+ return { ...result.presentation, content: [...result.presentation.content] };
50
+ }
51
+ const artifacts = result.partialBatch
52
+ ? [...(base.artifacts ?? []), ...(result.presentation.artifacts ?? [])]
53
+ : base.artifacts;
155
54
  return {
156
- ...base, artifacts, artifactVerification: buildArtifactVerificationSummary(artifacts ?? []),
157
- batchSteps: base.batchSteps?.map((step) => step.index === result.stopIndex ? { ...step, artifacts: result.presentation.artifacts, artifactVerification: result.presentation.artifactVerification } : step),
158
- artifactManifest: result.partialBatch ? mergeSessionArtifactManifest({ base: base.artifactManifest, entries: buildManifestEntriesForFileArtifacts(result.presentation.artifacts ?? []) }) : base.artifactManifest,
159
- content: [...base.content, ...(result.partialBatch ? result.presentation.content : result.presentation.content.slice(0, 1))],
160
- nextActions,
55
+ ...base,
56
+ artifacts,
57
+ artifactVerification: buildArtifactVerificationSummary(artifacts ?? []),
58
+ batchSteps: base.batchSteps?.map((step) => step.index === result.stopIndex
59
+ ? {
60
+ ...step,
61
+ artifacts: result.presentation.artifacts,
62
+ artifactVerification: result.presentation.artifactVerification,
63
+ }
64
+ : step),
65
+ artifactManifest: result.partialBatch
66
+ ? mergeSessionArtifactManifest({
67
+ base: base.artifactManifest,
68
+ entries: buildManifestEntriesForFileArtifacts(result.presentation.artifacts ?? []),
69
+ })
70
+ : base.artifactManifest,
71
+ content: [
72
+ ...base.content,
73
+ ...(result.partialBatch
74
+ ? result.presentation.content
75
+ : result.presentation.content.slice(0, 1)),
76
+ ],
77
+ nextActions: mergeRecoveryNextActions(base, result),
161
78
  recordingRecovery: result.recovery,
162
79
  };
163
80
  }
@@ -0,0 +1,14 @@
1
+ import { getScreenshotPathTokenIndex, getScreenshotPositionalIndices } from "./artifact-paths.js";
2
+ export function getScreenshotCapture(command) {
3
+ if (command[0] !== "screenshot") {
4
+ return { kind: "unknown" };
5
+ }
6
+ if (command.includes("--full") || command.includes("-f")) {
7
+ return { kind: "full-page" };
8
+ }
9
+ const positional = getScreenshotPositionalIndices(command);
10
+ const selectorIndex = positional.find((index) => index !== getScreenshotPathTokenIndex(command));
11
+ return selectorIndex === undefined
12
+ ? { kind: "viewport" }
13
+ : { kind: "element", selector: command[selectorIndex] };
14
+ }