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
@@ -11,46 +11,61 @@ import { execFile as execFileCallback } from "node:child_process";
11
11
  import { realpathSync } from "node:fs";
12
12
  import { access, readFile } from "node:fs/promises";
13
13
  import { homedir } from "node:os";
14
- import { dirname, isAbsolute, resolve, sep } from "node:path";
14
+ import { resolve } from "node:path";
15
15
  import { fileURLToPath } from "node:url";
16
16
  import { promisify } from "node:util";
17
17
 
18
18
  import { CAPABILITY_BASELINE_SOURCE } from "./agent-browser-capability-baseline.mjs";
19
- import { MINIMUM_AGENT_BROWSER_VERSION, TARGET_AGENT_BROWSER_SOURCE, TARGET_AGENT_BROWSER_VERSION, isSupportedAgentBrowserVersion } from "./agent-browser-target.mjs";
19
+ import { checkPiSources } from "./doctor-sources.mjs";
20
+ import {
21
+ MINIMUM_AGENT_BROWSER_VERSION,
22
+ TARGET_AGENT_BROWSER_SOURCE,
23
+ TARGET_AGENT_BROWSER_VERSION,
24
+ isSupportedAgentBrowserVersion,
25
+ } from "./agent-browser-target.mjs";
20
26
 
21
27
  const execFile = promisify(execFileCallback);
22
- const PACKAGE_NAME = "pi-agent-browser-native";
23
- const REPO_URL_FRAGMENT = "github.com/fitchmultz/pi-agent-browser-native";
24
- const EXTENSION_ENTRYPOINTS = Object.freeze([
25
- "extensions/agent-browser/index.ts",
26
- "dist/extensions/agent-browser/index.js",
27
- ]);
28
28
  const RECOMMENDED_VERSION = TARGET_AGENT_BROWSER_VERSION;
29
29
  export const MINIMUM_PI_VERSION = "1.0.0";
30
30
  const DEFAULT_AGENT_DIR = resolve(homedir(), ".pi/agent");
31
- const THIS_PACKAGE_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..");
32
31
 
33
- export function normalizeAgentBrowserVersion(output) {
34
- return String(output ?? "").trim().replace(/^agent-browser\s+/, "");
32
+ /** @typedef {{readonly status: "pass" | "warn" | "fail", readonly title: string, readonly lines: readonly string[], readonly warnings?: readonly string[]}} DoctorCheck */
33
+ /** @typedef {{readonly checks: readonly DoctorCheck[], readonly failures: readonly DoctorCheck[], readonly warnings: readonly string[]}} DoctorReport */
34
+ /** @typedef {{readonly cwd?: string, readonly agentDir?: string, readonly settingsPaths?: readonly string[], readonly skipSourceCheck?: boolean, readonly readText?: (path: string) => Promise<string | undefined>, readonly pathExists?: (path: string) => Promise<boolean>, readonly runAgentBrowser?: (args: readonly string[]) => Promise<string>, readonly runPi?: (args: readonly string[]) => Promise<string>}} DoctorOptions */
35
+
36
+ function normalizeAgentBrowserVersion(output) {
37
+ return String(output ?? "")
38
+ .trim()
39
+ .replace(/^agent-browser\s+/, "");
35
40
  }
36
41
 
37
- export function normalizePiVersion(output) {
38
- return String(output ?? "").trim().replace(/^pi\s+/, "");
42
+ function normalizePiVersion(output) {
43
+ return String(output ?? "")
44
+ .trim()
45
+ .replace(/^pi\s+/, "");
39
46
  }
40
47
 
41
48
  function parseVersionParts(version) {
42
49
  const match = String(version ?? "").match(/^(\d+)\.(\d+)\.(\d+)(?:\b|[-+])/);
43
- if (!match) return undefined;
50
+ if (!match) {
51
+ return;
52
+ }
44
53
  return match.slice(1).map((part) => Number.parseInt(part, 10));
45
54
  }
46
55
 
47
56
  export function versionAtLeast(actual, minimum) {
48
57
  const actualParts = parseVersionParts(actual);
49
58
  const minimumParts = parseVersionParts(minimum);
50
- if (!actualParts || !minimumParts) return undefined;
59
+ if (!actualParts || !minimumParts) {
60
+ return;
61
+ }
51
62
  for (let index = 0; index < minimumParts.length; index += 1) {
52
- if (actualParts[index] > minimumParts[index]) return true;
53
- if (actualParts[index] < minimumParts[index]) return false;
63
+ if (actualParts[index] > minimumParts[index]) {
64
+ return true;
65
+ }
66
+ if (actualParts[index] < minimumParts[index]) {
67
+ return false;
68
+ }
54
69
  }
55
70
  return true;
56
71
  }
@@ -98,7 +113,7 @@ export function parseCliArgs(argv = process.argv.slice(2)) {
98
113
 
99
114
  for (let index = 0; index < argv.length; index += 1) {
100
115
  const arg = argv[index];
101
- if (arg === "-h" || arg === "--help") {
116
+ if (["-h", "--help"].includes(arg)) {
102
117
  parsed.showHelp = true;
103
118
  continue;
104
119
  }
@@ -106,15 +121,17 @@ export function parseCliArgs(argv = process.argv.slice(2)) {
106
121
  parsed.skipSourceCheck = true;
107
122
  continue;
108
123
  }
109
- if (arg === "--cwd" || arg === "--agent-dir" || arg === "--settings") {
124
+ if (["--cwd", "--agent-dir", "--settings"].includes(arg)) {
110
125
  const value = argv[index + 1];
111
126
  if (value === undefined || value.startsWith("--")) {
112
127
  throw new Error(`${arg} requires a value. Run with --help for usage.`);
113
128
  }
114
129
  index += 1;
115
- if (arg === "--cwd") parsed.cwd = value;
116
- if (arg === "--agent-dir") parsed.agentDir = value;
117
- if (arg === "--settings") parsed.settingsPaths.push(value);
130
+ if (arg === "--settings") {
131
+ parsed.settingsPaths.push(value);
132
+ } else {
133
+ parsed[arg === "--cwd" ? "cwd" : "agentDir"] = value;
134
+ }
118
135
  continue;
119
136
  }
120
137
  throw new Error(`Unknown option: ${arg}. Run with --help for usage.`);
@@ -124,12 +141,18 @@ export function parseCliArgs(argv = process.argv.slice(2)) {
124
141
  }
125
142
 
126
143
  async function defaultRunAgentBrowser(args) {
127
- const { stdout, stderr } = await execFile("agent-browser", args, { maxBuffer: 1024 * 1024, ...buildNpmShimExecOptions(process.platform) });
144
+ const { stdout, stderr } = await execFile("agent-browser", args, {
145
+ maxBuffer: 1024 * 1024,
146
+ ...buildNpmShimExecOptions(process.platform),
147
+ });
128
148
  return `${stdout}${stderr}`;
129
149
  }
130
150
 
131
151
  async function defaultRunPi(args) {
132
- const { stdout, stderr } = await execFile("pi", args, { maxBuffer: 1024 * 1024, ...buildNpmShimExecOptions(process.platform) });
152
+ const { stdout, stderr } = await execFile("pi", args, {
153
+ maxBuffer: 1024 * 1024,
154
+ ...buildNpmShimExecOptions(process.platform),
155
+ });
133
156
  return `${stdout}${stderr}`;
134
157
  }
135
158
 
@@ -150,164 +173,6 @@ async function defaultPathExists(path) {
150
173
  }
151
174
  }
152
175
 
153
- function isInsidePath(childPath, parentPath) {
154
- const child = resolve(childPath);
155
- const parent = resolve(parentPath);
156
- return child === parent || child.startsWith(`${parent}${sep}`);
157
- }
158
-
159
- function expandUserPath(path) {
160
- if (path === "~") return homedir();
161
- if (path.startsWith("~/")) return resolve(homedir(), path.slice(2));
162
- return path;
163
- }
164
-
165
- function isPathLikeSource(source) {
166
- return isAbsolute(source) || source.startsWith("./") || source.startsWith("../") || source.startsWith("~");
167
- }
168
-
169
- function sourceLooksLikeThisPackage(source, cwd, sourceBaseDir = cwd) {
170
- const text = String(source ?? "").trim();
171
- if (text.length === 0) return false;
172
- if (/^npm:pi-agent-browser-native(?:@|$)/.test(text)) return true;
173
- if (text === PACKAGE_NAME) return true;
174
- if (text.includes(REPO_URL_FRAGMENT)) return true;
175
-
176
- if (!isPathLikeSource(text)) return false;
177
- const resolvedSource = resolve(sourceBaseDir, expandUserPath(text));
178
- const cwdEntrypoints = EXTENSION_ENTRYPOINTS.map((entrypoint) => resolve(cwd, entrypoint));
179
- const packageEntrypoints = EXTENSION_ENTRYPOINTS.map((entrypoint) => resolve(THIS_PACKAGE_ROOT, entrypoint));
180
- return (
181
- resolvedSource === cwd ||
182
- resolvedSource === THIS_PACKAGE_ROOT ||
183
- cwdEntrypoints.some((entrypoint) => resolvedSource === entrypoint || isInsidePath(entrypoint, resolvedSource)) ||
184
- packageEntrypoints.some((entrypoint) => resolvedSource === entrypoint || isInsidePath(entrypoint, resolvedSource))
185
- );
186
- }
187
-
188
- function stripJsonComments(text) {
189
- let result = "";
190
- let inString = false;
191
- let quote = "";
192
- let escaped = false;
193
- let inLineComment = false;
194
- let inBlockComment = false;
195
-
196
- for (let index = 0; index < text.length; index += 1) {
197
- const char = text[index];
198
- const next = text[index + 1];
199
-
200
- if (inLineComment) {
201
- if (char === "\n") {
202
- inLineComment = false;
203
- result += char;
204
- }
205
- continue;
206
- }
207
- if (inBlockComment) {
208
- if (char === "*" && next === "/") {
209
- inBlockComment = false;
210
- index += 1;
211
- }
212
- continue;
213
- }
214
- if (inString) {
215
- result += char;
216
- if (escaped) {
217
- escaped = false;
218
- continue;
219
- }
220
- if (char === "\\") {
221
- escaped = true;
222
- continue;
223
- }
224
- if (char === quote) {
225
- inString = false;
226
- }
227
- continue;
228
- }
229
- if (char === '"' || char === "'") {
230
- inString = true;
231
- quote = char;
232
- result += char;
233
- continue;
234
- }
235
- if (char === "/" && next === "/") {
236
- inLineComment = true;
237
- index += 1;
238
- continue;
239
- }
240
- if (char === "/" && next === "*") {
241
- inBlockComment = true;
242
- index += 1;
243
- continue;
244
- }
245
- result += char;
246
- }
247
- return result;
248
- }
249
-
250
- function parseSettingsText(text, path) {
251
- return JSON.parse(stripJsonComments(text));
252
- }
253
-
254
- function arrayEntries(value) {
255
- return Array.isArray(value) ? value.entries() : [];
256
- }
257
-
258
- function entrySource(entry) {
259
- if (typeof entry === "string") return entry;
260
- if (entry && typeof entry === "object") return entry.source ?? entry.path ?? entry.package;
261
- return undefined;
262
- }
263
-
264
- function collectSettingsSources(settings, settingsPath, cwd) {
265
- const sources = [];
266
- const sourceBaseDir = dirname(settingsPath);
267
- for (const [index, entry] of arrayEntries(settings?.packages)) {
268
- const source = entrySource(entry);
269
- if (sourceLooksLikeThisPackage(source, cwd, sourceBaseDir)) {
270
- sources.push({ kind: "package", source: String(source), location: `${settingsPath} packages[${index}]` });
271
- }
272
- }
273
- for (const [index, entry] of arrayEntries(settings?.extensions)) {
274
- const source = entrySource(entry);
275
- if (sourceLooksLikeThisPackage(source, cwd, sourceBaseDir)) {
276
- sources.push({ kind: "extension", source: String(source), location: `${settingsPath} extensions[${index}]` });
277
- }
278
- }
279
- return sources;
280
- }
281
-
282
- function dedupe(paths) {
283
- return [...new Set(paths.map((path) => resolve(path)))];
284
- }
285
-
286
- async function inspectSettingsPath({ path, cwd, readText }) {
287
- try {
288
- const text = await readText(path);
289
- if (text === undefined) return { sources: [], warnings: [] };
290
- const settings = parseSettingsText(text, path);
291
- return { sources: collectSettingsSources(settings, path, cwd), warnings: [] };
292
- } catch (error) {
293
- return {
294
- sources: [],
295
- warnings: [`Could not inspect Pi settings ${path}: ${error instanceof Error ? error.message : String(error)}`],
296
- };
297
- }
298
- }
299
-
300
- async function collectRepoLocalSources({ cwd, pathExists }) {
301
- const candidates = [resolve(cwd, ".pi/extensions/agent-browser.ts"), resolve(cwd, ".pi/extensions/agent-browser/index.ts")];
302
- const sources = [];
303
- for (const candidate of candidates) {
304
- if (await pathExists(candidate)) {
305
- sources.push({ kind: "repo-local", source: candidate, location: `${candidate} repo-local autoload` });
306
- }
307
- }
308
- return sources;
309
- }
310
-
311
176
  async function checkPiVersion({ runPi }) {
312
177
  try {
313
178
  const rawOutput = await runPi(["--version"]);
@@ -327,10 +192,16 @@ async function checkPiVersion({ runPi }) {
327
192
  return {
328
193
  status: "warn",
329
194
  title: `Could not parse pi --version output: ${version || "<empty>"}.`,
330
- lines: [`Pi ${MINIMUM_PI_VERSION} or newer is required for this release; run this doctor from the same shell that launches Pi so the setup gate can verify the host runtime.`],
195
+ lines: [
196
+ `Pi ${MINIMUM_PI_VERSION} or newer is required for this release; run this doctor from the same shell that launches Pi so the setup gate can verify the host runtime.`,
197
+ ],
331
198
  };
332
199
  }
333
- return { status: "pass", title: `Pi version satisfies the minimum runtime floor: ${version}`, lines: [] };
200
+ return {
201
+ status: "pass",
202
+ title: `Pi version satisfies the minimum runtime floor: ${version}`,
203
+ lines: [],
204
+ };
334
205
  } catch (error) {
335
206
  const code = error && typeof error === "object" ? error.code : undefined;
336
207
  return {
@@ -361,9 +232,10 @@ async function checkAgentBrowserVersion({ runAgentBrowser }) {
361
232
  }
362
233
  return {
363
234
  status: "pass",
364
- title: version === RECOMMENDED_VERSION
365
- ? `agent-browser version matches recommended baseline: ${version}`
366
- : `agent-browser version meets supported floor: ${version} (recommended ${RECOMMENDED_VERSION})`,
235
+ title:
236
+ version === RECOMMENDED_VERSION
237
+ ? `agent-browser version matches recommended baseline: ${version}`
238
+ : `agent-browser version meets supported floor: ${version} (recommended ${RECOMMENDED_VERSION})`,
367
239
  lines: [],
368
240
  };
369
241
  } catch (error) {
@@ -383,89 +255,52 @@ async function checkAgentBrowserVersion({ runAgentBrowser }) {
383
255
  }
384
256
  }
385
257
 
386
- async function checkPiSources({ cwd, agentDir, settingsPaths, readText, pathExists }) {
387
- const defaultSettingsPaths = [resolve(agentDir, "settings.json"), resolve(cwd, ".pi/settings.json")];
388
- const allSettingsPaths = dedupe([...defaultSettingsPaths, ...settingsPaths]);
389
- const sources = [];
390
- const warnings = [];
391
-
392
- for (const path of allSettingsPaths) {
393
- if (await pathExists(path)) {
394
- const result = await inspectSettingsPath({ path, cwd, readText });
395
- sources.push(...result.sources);
396
- warnings.push(...result.warnings);
397
- }
398
- }
399
- sources.push(...(await collectRepoLocalSources({ cwd, pathExists })));
400
-
401
- if (sources.length > 1) {
402
- return {
403
- status: "fail",
404
- title: "Duplicate pi-agent-browser-native sources detected.",
405
- lines: [
406
- "Pi may register multiple `agent_browser` tools when a checkout source and a package source are both active.",
407
- "Detected sources:",
408
- ...sources.map((source) => `- ${source.source} from ${source.location}`),
409
- "Keep exactly one active source:",
410
- "- for normal use: keep `pi install npm:pi-agent-browser-native` and remove/disable checkout paths from Pi settings",
411
- "- for temporary package or checkout trials: use `pi --approve --no-extensions -e <source>` when you intentionally trust the current project, or omit `--approve` to let Pi prompt in interactive mode",
412
- "- for configured-source lifecycle validation: keep exactly one checkout or package source, then launch plain `pi`",
413
- ],
414
- warnings,
415
- };
416
- }
417
- if (sources.length === 1) {
418
- return {
419
- status: "pass",
420
- title: "No duplicate pi-agent-browser-native sources detected.",
421
- lines: [`Detected source: ${sources[0].source} from ${sources[0].location}`],
422
- warnings,
423
- };
424
- }
258
+ function doctorIo(options) {
425
259
  return {
426
- status: "warn",
427
- title: "No configured pi-agent-browser-native source was found in inspected Pi settings.",
428
- lines: [
429
- "This is OK for isolated runs such as `pi --no-extensions -e npm:pi-agent-browser-native`, but normal package use should install exactly one source with `pi install npm:pi-agent-browser-native`.",
430
- ],
431
- warnings,
260
+ readText: options.readText ?? ((path) => readFile(path, "utf8")),
261
+ pathExists: options.pathExists ?? defaultPathExists,
262
+ runAgentBrowser: options.runAgentBrowser ?? defaultRunAgentBrowser,
263
+ runPi: options.runPi ?? defaultRunPi,
432
264
  };
433
265
  }
434
266
 
267
+ /** @param {DoctorOptions} [options] @returns {Promise<DoctorReport>} */
435
268
  export async function evaluateDoctor(options = {}) {
436
269
  const cwd = resolve(options.cwd ?? process.cwd());
437
270
  const agentDir = resolve(options.agentDir ?? DEFAULT_AGENT_DIR);
438
- const settingsPaths = (options.settingsPaths ?? []).map((path) => resolve(cwd, path));
439
- const readText = options.readText ?? ((path) => readFile(path, "utf8"));
440
- const pathExists = options.pathExists ?? defaultPathExists;
441
- const runAgentBrowser = options.runAgentBrowser ?? defaultRunAgentBrowser;
442
- const runPi = options.runPi ?? defaultRunPi;
271
+ const settingsPaths = Array.from(options.settingsPaths ?? [], (path) => resolve(cwd, path));
272
+ const { readText, pathExists, runAgentBrowser, runPi } = doctorIo(options);
443
273
  const checks = [];
444
- const failures = [];
274
+
445
275
  const warnings = [];
446
276
 
447
277
  const versionCheck = await checkAgentBrowserVersion({ runAgentBrowser });
448
278
  checks.push(versionCheck);
449
- if (versionCheck.status === "fail") failures.push(versionCheck);
450
279
 
451
280
  const piVersionCheck = await checkPiVersion({ runPi });
452
281
  checks.push(piVersionCheck);
453
- if (piVersionCheck.status === "fail") failures.push(piVersionCheck);
454
282
 
455
283
  if (!options.skipSourceCheck) {
456
- const sourceCheck = await checkPiSources({ cwd, agentDir, settingsPaths, readText, pathExists });
284
+ const sourceCheck = await checkPiSources({
285
+ cwd,
286
+ agentDir,
287
+ settingsPaths,
288
+ readText,
289
+ pathExists,
290
+ });
457
291
  checks.push(sourceCheck);
458
- if (sourceCheck.status === "fail") failures.push(sourceCheck);
292
+
459
293
  warnings.push(...(sourceCheck.warnings ?? []));
460
294
  }
461
295
 
462
- return { checks, failures, warnings };
296
+ return { checks, failures: checks.filter((check) => check.status === "fail"), warnings };
463
297
  }
464
298
 
299
+ /** @param {DoctorReport} report @returns {string} */
465
300
  export function formatDoctorReport(report) {
466
301
  const lines = ["pi-agent-browser-native doctor", ""];
467
302
  for (const check of report.checks) {
468
- const prefix = check.status === "pass" ? "✓" : check.status === "warn" ? "!" : "✗";
303
+ const prefix = { pass: "✓", warn: "!", fail: "✗" }[check.status];
469
304
  lines.push(`${prefix} ${check.title}`);
470
305
  for (const line of check.lines ?? []) {
471
306
  lines.push(` ${line}`);
@@ -475,7 +310,9 @@ export function formatDoctorReport(report) {
475
310
  for (const warning of report.warnings ?? []) {
476
311
  lines.push(`! ${warning}`);
477
312
  }
478
- if ((report.warnings ?? []).length > 0) lines.push("");
313
+ if ((report.warnings ?? []).length > 0) {
314
+ lines.push("");
315
+ }
479
316
  lines.push(report.failures.length > 0 ? "Doctor found setup failures." : "Doctor passed.");
480
317
  return lines.join("\n");
481
318
  }
@@ -502,8 +339,11 @@ export async function main(argv = process.argv.slice(2)) {
502
339
  return 0;
503
340
  }
504
341
 
342
+ /** @param {string} metaUrl @param {string | undefined} [argv1] @param {(path: string) => string} [resolveRealPath] @returns {boolean} */
505
343
  export function isDirectRun(metaUrl, argv1 = process.argv[1], resolveRealPath = realpathSync) {
506
- if (!argv1) return false;
344
+ if (!argv1) {
345
+ return false;
346
+ }
507
347
  try {
508
348
  return resolveRealPath(argv1) === fileURLToPath(metaUrl);
509
349
  } catch {
@@ -512,7 +352,12 @@ export function isDirectRun(metaUrl, argv1 = process.argv[1], resolveRealPath =
512
352
  }
513
353
 
514
354
  if (isDirectRun(import.meta.url)) {
515
- main().then((exitCode) => {
516
- process.exitCode = exitCode;
517
- });
355
+ main()
356
+ .then((exitCode) => {
357
+ process.exitCode = exitCode;
358
+ })
359
+ .catch((error) => {
360
+ console.error(error instanceof Error ? error.message : error);
361
+ process.exitCode = 1;
362
+ });
518
363
  }
@@ -18,7 +18,10 @@ export function writeExitCode(dir, code, signal) {
18
18
  }
19
19
 
20
20
  export function writeSummary(dir, data) {
21
- writeFileSync(resolve(dir, "summary.json"), JSON.stringify({ ...data, writtenAt: new Date().toISOString() }, null, 2));
21
+ writeFileSync(
22
+ resolve(dir, "summary.json"),
23
+ JSON.stringify({ ...data, writtenAt: new Date().toISOString() }, null, 2),
24
+ );
22
25
  }
23
26
 
24
27
  export function writeManifest(dir, expectedFiles) {
@@ -26,11 +29,16 @@ export function writeManifest(dir, expectedFiles) {
26
29
  function walk(current) {
27
30
  for (const entry of readdirSync(current, { withFileTypes: true })) {
28
31
  const path = resolve(current, entry.name);
29
- if (entry.isDirectory()) walk(path);
30
- else if (entry.isFile()) present.push(relative(dir, path));
32
+ if (entry.isDirectory()) {
33
+ walk(path);
34
+ } else if (entry.isFile()) {
35
+ present.push(relative(dir, path));
36
+ }
31
37
  }
32
38
  }
33
- if (existsSync(dir)) walk(dir);
39
+ if (existsSync(dir)) {
40
+ walk(dir);
41
+ }
34
42
  const allPresent = [...new Set([...present, "artifact-manifest.json"])].sort();
35
43
  const manifest = {
36
44
  expected: expectedFiles,
@@ -43,7 +51,13 @@ export function writeManifest(dir, expectedFiles) {
43
51
  }
44
52
 
45
53
  export function collectSecretValues(envNames, env = process.env) {
46
- return [...new Set(envNames.map((name) => env[name]).filter((value) => typeof value === "string" && value.length >= 8))];
54
+ return [
55
+ ...new Set(
56
+ envNames
57
+ .map((name) => env[name])
58
+ .filter((value) => typeof value === "string" && value.length >= 8),
59
+ ),
60
+ ];
47
61
  }
48
62
 
49
63
  export function redactSecrets(text, secretValues = []) {
@@ -58,14 +72,21 @@ export function scanForSecrets(text, secretValues = []) {
58
72
  const content = String(text ?? "");
59
73
  const violations = [];
60
74
  for (const secret of secretValues) {
61
- if (secret && content.includes(secret)) violations.push("raw forwarded secret value");
75
+ if (secret && content.includes(secret)) {
76
+ violations.push("raw forwarded secret value");
77
+ }
62
78
  }
63
79
  for (const [pattern, label] of [
64
80
  [/bearer\s+[A-Za-z0-9\-._~+/]{20,}=*/gi, "bearer token"],
65
81
  [/Authorization:\s*Bearer\s+[A-Za-z0-9\-._~+/]{20,}=*/gi, "authorization header"],
66
- [/(?:api[_-]?key|access[_-]?token|refresh[_-]?token|cookie)\s*[:=]\s*["']?[A-Za-z0-9_./+\-=]{20,}/gi, "token-like field"],
82
+ [
83
+ /(?:api[_-]?key|access[_-]?token|refresh[_-]?token|cookie)\s*[:=]\s*["']?[A-Za-z0-9_./+\-=]{20,}/gi,
84
+ "token-like field",
85
+ ],
67
86
  ]) {
68
- if (pattern.test(content)) violations.push(label);
87
+ if (pattern.test(content)) {
88
+ violations.push(label);
89
+ }
69
90
  }
70
91
  return [...new Set(violations)];
71
92
  }
@@ -79,11 +100,17 @@ export function scanArtifactTextFiles(dir, secretValues = []) {
79
100
  walk(path);
80
101
  continue;
81
102
  }
82
- if (!entry.isFile()) continue;
83
- if (!/\.(?:txt|json|jsonl|md|log|ps1|mjs|js)$/i.test(entry.name)) continue;
103
+ if (!entry.isFile()) {
104
+ continue;
105
+ }
106
+ if (!/\.(?:txt|json|jsonl|md|log|ps1|mjs|js)$/i.test(entry.name)) {
107
+ continue;
108
+ }
84
109
  try {
85
110
  const text = readFileSync(path, "utf8");
86
- for (const violation of scanForSecrets(text, secretValues)) findings.push({ file: relative(dir, path), violation });
111
+ for (const violation of scanForSecrets(text, secretValues)) {
112
+ findings.push({ file: relative(dir, path), violation });
113
+ }
87
114
  } catch {
88
115
  // Ignore unreadable or non-text files.
89
116
  }
@@ -0,0 +1,104 @@
1
+ /** Native POSIX/PowerShell platform command rendering; every required gate contributes to the final exit. */
2
+ import { CAPABILITY_BASELINE } from "../agent-browser-capability-baseline.mjs";
3
+ import { platformFor } from "./suite-evidence.mjs";
4
+
5
+ function shellQuote(value) {
6
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
7
+ }
8
+
9
+ function psSingleQuote(value) {
10
+ return `'${String(value).replace(/'/g, "''")}'`;
11
+ }
12
+
13
+ export function buildPlatformBuildCommand(targetName, packageName, nodeValidationVersion) {
14
+ if (platformFor(targetName) === "powershell") {
15
+ return `powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File .\\scripts\\platform-smoke\\platform-build-windows.ps1 -PackageName ${psSingleQuote(packageName)} -NodeValidationVersion ${psSingleQuote(nodeValidationVersion)}`;
16
+ }
17
+ return [
18
+ `echo "Starting platform-build in $(pwd) at $(date -u +%Y-%m-%dT%H:%M:%SZ)"`,
19
+ `RUN_ROOT=".platform-smoke-runs/platform-build-$(date -u +%Y%m%dT%H%M%SZ)-$$"`,
20
+ `SOURCE_ROOT="$(pwd)"`,
21
+ `PACK_DIR="$SOURCE_ROOT/$RUN_ROOT/pack"`,
22
+ `PI_PROJECT="$SOURCE_ROOT/$RUN_ROOT/pi-project"`,
23
+ `mkdir -p "$PACK_DIR" "$PI_PROJECT"`,
24
+ `echo "PLATFORM_RUN_ROOT=$RUN_ROOT"`,
25
+ `NODE_VERSION=$(node --version)`,
26
+ `echo "PLATFORM_NODE_VERSION=$NODE_VERSION"`,
27
+ `if node -e 'process.exit(process.versions.node.localeCompare(process.argv[1], undefined, { numeric: true }) < 0 ? 1 : 0)' ${shellQuote(nodeValidationVersion)}; then NODE_VERSION_EXIT=0; else NODE_VERSION_EXIT=1; fi`,
28
+ `echo "PLATFORM_NODE_VERSION_EXIT=$NODE_VERSION_EXIT"`,
29
+ `npm ci 2>&1`,
30
+ `NPM_CI_EXIT=$?`,
31
+ `echo "PLATFORM_NPM_CI_EXIT=$NPM_CI_EXIT"`,
32
+ `npm run verify -- platform-target 2>&1`,
33
+ `VERIFY_EXIT=$?`,
34
+ `echo "PLATFORM_VERIFY_EXIT=$VERIFY_EXIT"`,
35
+ `PACK_TARBALL=$(npm pack --silent --pack-destination "$PACK_DIR" 2>"$PACK_DIR/npm-pack.stderr.txt")`,
36
+ `PACK_EXIT=$?`,
37
+ `cat "$PACK_DIR/npm-pack.stderr.txt"`,
38
+ `PACK_FILE="$PACK_DIR/$PACK_TARBALL"`,
39
+ `echo "PLATFORM_NPM_PACK_EXIT=$PACK_EXIT"`,
40
+ `echo "PLATFORM_PACKED_TARBALL=$PACK_FILE"`,
41
+ `PI_CLI="$SOURCE_ROOT/node_modules/.bin/pi"`,
42
+ `if [ ! -x "$PI_CLI" ]; then PI_CLI="$(command -v pi || true)"; fi`,
43
+ `echo "PLATFORM_PI_CLI=$PI_CLI"`,
44
+ `if [ -n "$PACK_TARBALL" ] && [ -f "$PACK_FILE" ]; then (cd "$PI_PROJECT" && npm init -y >"$PACK_DIR/packed-node-install.stdout.txt" 2>"$PACK_DIR/packed-node-install.stderr.txt" && npm install --no-save "$PACK_FILE" >>"$PACK_DIR/packed-node-install.stdout.txt" 2>>"$PACK_DIR/packed-node-install.stderr.txt"); PACKED_NODE_INSTALL_EXIT=$?; else echo "missing tarball" >"$PACK_DIR/packed-node-install.stderr.txt"; PACKED_NODE_INSTALL_EXIT=1; fi`,
45
+ `echo "PLATFORM_PACKED_NODE_INSTALL_EXIT=$PACKED_NODE_INSTALL_EXIT"`,
46
+ `echo "--- PACKED_NODE_INSTALL_STDOUT START ---"; cat "$PACK_DIR/packed-node-install.stdout.txt" 2>/dev/null || true; echo "--- PACKED_NODE_INSTALL_STDOUT END ---"`,
47
+ `echo "--- PACKED_NODE_INSTALL_STDERR START ---"; cat "$PACK_DIR/packed-node-install.stderr.txt" 2>/dev/null || true; echo "--- PACKED_NODE_INSTALL_STDERR END ---"`,
48
+ `if [ "$PACKED_NODE_INSTALL_EXIT" -eq 0 ] && [ -n "$PI_CLI" ]; then (cd "$PI_PROJECT" && PI_OFFLINE=1 "$PI_CLI" install -l --approve ./node_modules/${packageName} >"$PACK_DIR/pi-install.stdout.txt" 2>"$PACK_DIR/pi-install.stderr.txt"); PI_INSTALL_EXIT=$?; else echo "missing pi cli or packed install" >"$PACK_DIR/pi-install.stderr.txt"; PI_INSTALL_EXIT=1; fi`,
49
+ `echo "PLATFORM_PI_INSTALL_EXIT=$PI_INSTALL_EXIT"`,
50
+ `echo "--- PI_INSTALL_STDOUT START ---"; cat "$PACK_DIR/pi-install.stdout.txt" 2>/dev/null || true; echo "--- PI_INSTALL_STDOUT END ---"`,
51
+ `echo "--- PI_INSTALL_STDERR START ---"; cat "$PACK_DIR/pi-install.stderr.txt" 2>/dev/null || true; echo "--- PI_INSTALL_STDERR END ---"`,
52
+ `if [ -n "$PI_CLI" ]; then (cd "$PI_PROJECT" && PI_OFFLINE=1 "$PI_CLI" list --approve >"$PACK_DIR/pi-list.stdout.txt" 2>"$PACK_DIR/pi-list.stderr.txt"); PI_LIST_EXIT=$?; else echo "missing pi cli" >"$PACK_DIR/pi-list.stderr.txt"; PI_LIST_EXIT=1; fi`,
53
+ `echo "PLATFORM_PI_LIST_EXIT=$PI_LIST_EXIT"`,
54
+ `echo "--- PI_LIST_STDOUT START ---"; cat "$PACK_DIR/pi-list.stdout.txt" 2>/dev/null || true; echo "--- PI_LIST_STDOUT END ---"`,
55
+ `echo "--- PI_LIST_STDERR START ---"; cat "$PACK_DIR/pi-list.stderr.txt" 2>/dev/null || true; echo "--- PI_LIST_STDERR END ---"`,
56
+ `if [ "$NODE_VERSION_EXIT" -ne 0 ] || [ "$NPM_CI_EXIT" -ne 0 ] || [ "$VERIFY_EXIT" -ne 0 ] || [ "$PACK_EXIT" -ne 0 ] || [ "$PACKED_NODE_INSTALL_EXIT" -ne 0 ] || [ "$PI_INSTALL_EXIT" -ne 0 ] || [ "$PI_LIST_EXIT" -ne 0 ]; then echo "PLATFORM_BUILD_FAILED"; exit 1; fi`,
57
+ `echo "PLATFORM_BUILD_OK"`,
58
+ ].join("\n");
59
+ }
60
+
61
+ export function buildBrowserDogfoodCommand(
62
+ targetName,
63
+ agentBrowserVersion = CAPABILITY_BASELINE.targetVersion,
64
+ dependenciesReady = false,
65
+ ) {
66
+ if (platformFor(targetName) === "powershell") {
67
+ return `powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File .\\scripts\\platform-smoke\\browser-dogfood-windows.ps1 -AgentBrowserVersion ${psSingleQuote(agentBrowserVersion)}${dependenciesReady ? " -SkipNpmCi" : ""}`;
68
+ }
69
+ return [
70
+ `echo "Starting browser-dogfood-smoke in $(pwd) at $(date -u +%Y-%m-%dT%H:%M:%SZ)"`,
71
+ `RUN_ROOT=".platform-smoke-runs/browser-dogfood-$(date -u +%Y%m%dT%H%M%SZ)-$$"`,
72
+ `SOURCE_ROOT="$(pwd)"`,
73
+ `DOGFOOD_DIR="$SOURCE_ROOT/$RUN_ROOT/dogfood"`,
74
+ `DOGFOOD_ARTIFACT_DIR="$DOGFOOD_DIR/artifacts"`,
75
+ `mkdir -p "$DOGFOOD_ARTIFACT_DIR"`,
76
+ `echo "PLATFORM_RUN_ROOT=$RUN_ROOT"`,
77
+ `echo "PLATFORM_DOGFOOD_ARTIFACT_DIR=$DOGFOOD_ARTIFACT_DIR"`,
78
+ `NODE_VERSION=$(node --version)`,
79
+ `NODE_MAJOR="${"${NODE_VERSION#v}"}"`,
80
+ `NODE_MAJOR="${"${NODE_MAJOR%%.*}"}"`,
81
+ `echo "PLATFORM_NODE_VERSION=$NODE_VERSION"`,
82
+ `EXPECTED_AGENT_BROWSER_VERSION=${shellQuote(`agent-browser ${agentBrowserVersion}`)}`,
83
+ `AGENT_BROWSER_VERSION_OUTPUT=$(agent-browser --version 2>&1)`,
84
+ `AGENT_BROWSER_VERSION_COMMAND_EXIT=$?`,
85
+ `echo "PLATFORM_AGENT_BROWSER_VERSION=$AGENT_BROWSER_VERSION_OUTPUT"`,
86
+ `if [ "$AGENT_BROWSER_VERSION_COMMAND_EXIT" -eq 0 ] && [ "$AGENT_BROWSER_VERSION_OUTPUT" = "$EXPECTED_AGENT_BROWSER_VERSION" ]; then AGENT_BROWSER_READY_EXIT=0; else AGENT_BROWSER_READY_EXIT=1; fi`,
87
+ `echo "PLATFORM_AGENT_BROWSER_READY_EXIT=$AGENT_BROWSER_READY_EXIT"`,
88
+ ...(dependenciesReady
89
+ ? [
90
+ `if [ -d node_modules ]; then echo "PLATFORM_NPM_CI_SKIPPED=1"; NPM_CI_EXIT=0; else npm ci 2>&1; NPM_CI_EXIT=$?; fi`,
91
+ ]
92
+ : [`npm ci 2>&1`, `NPM_CI_EXIT=$?`]),
93
+ `echo "PLATFORM_NPM_CI_EXIT=$NPM_CI_EXIT"`,
94
+ `TSX_CLI="$SOURCE_ROOT/node_modules/.bin/tsx"`,
95
+ `if [ ! -x "$TSX_CLI" ]; then TSX_CLI="$(command -v tsx || true)"; fi`,
96
+ `echo "PLATFORM_TSX_CLI=$TSX_CLI"`,
97
+ `if [ "$NPM_CI_EXIT" -eq 0 ] && [ "$AGENT_BROWSER_READY_EXIT" -eq 0 ] && [ -n "$TSX_CLI" ]; then "$TSX_CLI" scripts/verify-agent-browser-dogfood.ts --artifact-dir "$DOGFOOD_ARTIFACT_DIR" --json >"$DOGFOOD_DIR/dogfood.stdout.txt" 2>"$DOGFOOD_DIR/dogfood.stderr.txt"; DOGFOOD_EXIT=$?; else echo "missing tsx, npm ci failed, or agent-browser baseline mismatch" >"$DOGFOOD_DIR/dogfood.stderr.txt"; DOGFOOD_EXIT=1; fi`,
98
+ `echo "PLATFORM_DOGFOOD_EXIT=$DOGFOOD_EXIT"`,
99
+ `echo "--- DOGFOOD_STDOUT START ---"; cat "$DOGFOOD_DIR/dogfood.stdout.txt" 2>/dev/null || true; echo "--- DOGFOOD_STDOUT END ---"`,
100
+ `echo "--- DOGFOOD_STDERR START ---"; cat "$DOGFOOD_DIR/dogfood.stderr.txt" 2>/dev/null || true; echo "--- DOGFOOD_STDERR END ---"`,
101
+ `if [ "$NPM_CI_EXIT" -ne 0 ] || [ "$AGENT_BROWSER_READY_EXIT" -ne 0 ] || [ "$DOGFOOD_EXIT" -ne 0 ]; then echo "PLATFORM_BROWSER_DOGFOOD_FAILED"; exit 1; fi`,
102
+ `echo "PLATFORM_BROWSER_DOGFOOD_OK"`,
103
+ ].join("\n");
104
+ }