pi-agent-browser-native 0.9.2 → 0.9.4

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