pi-agent-browser-native 0.9.3 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (394) hide show
  1. package/CHANGELOG.md +106 -5
  2. package/README.md +58 -791
  3. package/dist/extensions/agent-browser/index.js +43101 -2031
  4. package/dist/extensions/agent-browser/lib/argv-descriptor.js +49 -26
  5. package/dist/extensions/agent-browser/lib/argv-grammar.js +82 -93
  6. package/dist/extensions/agent-browser/lib/bash-guard.js +129 -126
  7. package/dist/extensions/agent-browser/lib/batch-lifecycle.js +112 -51
  8. package/dist/extensions/agent-browser/lib/browser-execution-claim-codec.js +61 -0
  9. package/dist/extensions/agent-browser/lib/browser-execution-claim-storage.js +232 -0
  10. package/dist/extensions/agent-browser/lib/browser-execution-claims.js +202 -0
  11. package/dist/extensions/agent-browser/lib/browser-execution-identity.js +77 -0
  12. package/dist/extensions/agent-browser/lib/browser-journal-branch.js +98 -0
  13. package/dist/extensions/agent-browser/lib/browser-journal-contracts.js +1 -0
  14. package/dist/extensions/agent-browser/lib/browser-journal-projection.js +221 -0
  15. package/dist/extensions/agent-browser/lib/browser-journal-reader.js +89 -0
  16. package/dist/extensions/agent-browser/lib/browser-journal-replay.js +246 -0
  17. package/dist/extensions/agent-browser/lib/browser-journal.js +103 -394
  18. package/dist/extensions/agent-browser/lib/browser-legacy-pages.js +220 -0
  19. package/dist/extensions/agent-browser/lib/browser-legacy-projection.js +282 -0
  20. package/dist/extensions/agent-browser/lib/browser-legacy-types.js +1 -0
  21. package/dist/extensions/agent-browser/lib/browser-session-conversion-stream.js +217 -0
  22. package/dist/extensions/agent-browser/lib/browser-session-conversion.js +80 -335
  23. package/dist/extensions/agent-browser/lib/browser-transcript-contracts.js +35 -0
  24. package/dist/extensions/agent-browser/lib/browser-transcript-validation.js +166 -0
  25. package/dist/extensions/agent-browser/lib/browser-transcript.js +137 -82
  26. package/dist/extensions/agent-browser/lib/browser-value-parsing.js +15 -0
  27. package/dist/extensions/agent-browser/lib/command-capabilities.js +340 -0
  28. package/dist/extensions/agent-browser/lib/command-policy.js +107 -88
  29. package/dist/extensions/agent-browser/lib/command-taxonomy.js +49 -322
  30. package/dist/extensions/agent-browser/lib/config-policy.js +138 -343
  31. package/dist/extensions/agent-browser/lib/config-providers.js +71 -0
  32. package/dist/extensions/agent-browser/lib/config-validation.js +231 -0
  33. package/dist/extensions/agent-browser/lib/config.js +20 -8
  34. package/dist/extensions/agent-browser/lib/electron/cdp.js +20 -8
  35. package/dist/extensions/agent-browser/lib/electron/cleanup.js +128 -83
  36. package/dist/extensions/agent-browser/lib/electron/discovery-darwin.js +109 -0
  37. package/dist/extensions/agent-browser/lib/electron/discovery-desktop.js +136 -0
  38. package/dist/extensions/agent-browser/lib/electron/discovery-evidence.js +90 -0
  39. package/dist/extensions/agent-browser/lib/electron/discovery-linux.js +93 -0
  40. package/dist/extensions/agent-browser/lib/electron/discovery-packages.js +162 -0
  41. package/dist/extensions/agent-browser/lib/electron/discovery-types.js +2 -0
  42. package/dist/extensions/agent-browser/lib/electron/discovery.js +140 -549
  43. package/dist/extensions/agent-browser/lib/electron/launch-monitor.js +102 -0
  44. package/dist/extensions/agent-browser/lib/electron/launch-process.js +209 -0
  45. package/dist/extensions/agent-browser/lib/electron/launch-types.js +2 -0
  46. package/dist/extensions/agent-browser/lib/electron/launch.js +261 -355
  47. package/dist/extensions/agent-browser/lib/executable-path.js +21 -12
  48. package/dist/extensions/agent-browser/lib/execution-cwd.js +35 -18
  49. package/dist/extensions/agent-browser/lib/fs-utils.js +1 -9
  50. package/dist/extensions/agent-browser/lib/input-modes/electron.js +162 -121
  51. package/dist/extensions/agent-browser/lib/input-modes/job.js +123 -317
  52. package/dist/extensions/agent-browser/lib/input-modes/lookup-network-evidence.js +116 -0
  53. package/dist/extensions/agent-browser/lib/input-modes/lookup-plan.js +132 -0
  54. package/dist/extensions/agent-browser/lib/input-modes/lookup-redaction.js +57 -0
  55. package/dist/extensions/agent-browser/lib/input-modes/lookup-source-evidence.js +151 -0
  56. package/dist/extensions/agent-browser/lib/input-modes/lookup-workspace.js +142 -0
  57. package/dist/extensions/agent-browser/lib/input-modes/lookups.js +58 -412
  58. package/dist/extensions/agent-browser/lib/input-modes/params.js +86 -40
  59. package/dist/extensions/agent-browser/lib/input-modes/qa-analysis.js +268 -0
  60. package/dist/extensions/agent-browser/lib/input-modes/qa-presentation.js +117 -0
  61. package/dist/extensions/agent-browser/lib/input-modes/script-child.js +396 -0
  62. package/dist/extensions/agent-browser/lib/input-modes/script-protocol.js +86 -0
  63. package/dist/extensions/agent-browser/lib/input-modes/script-types.js +1 -0
  64. package/dist/extensions/agent-browser/lib/input-modes/script-validation.js +60 -0
  65. package/dist/extensions/agent-browser/lib/input-modes/script.js +60 -409
  66. package/dist/extensions/agent-browser/lib/input-modes/semantic-action.js +218 -128
  67. package/dist/extensions/agent-browser/lib/input-modes/shared.js +15 -4
  68. package/dist/extensions/agent-browser/lib/input-modes/types.js +56 -7
  69. package/dist/extensions/agent-browser/lib/json-schema.js +22 -10
  70. package/dist/extensions/agent-browser/lib/launch-scoped-flags.js +17 -5
  71. package/dist/extensions/agent-browser/lib/managed-session-policy-lock.js +92 -425
  72. package/dist/extensions/agent-browser/lib/managed-session-posix-storage.js +58 -0
  73. package/dist/extensions/agent-browser/lib/managed-session-project-identity.js +244 -0
  74. package/dist/extensions/agent-browser/lib/managed-session-restore-context.js +84 -0
  75. package/dist/extensions/agent-browser/lib/managed-session-restore-policy.js +119 -0
  76. package/dist/extensions/agent-browser/lib/managed-session-restore-state.js +83 -0
  77. package/dist/extensions/agent-browser/lib/managed-session-restore.js +168 -300
  78. package/dist/extensions/agent-browser/lib/managed-session-snapshot-records.js +277 -0
  79. package/dist/extensions/agent-browser/lib/managed-session-snapshots.js +128 -305
  80. package/dist/extensions/agent-browser/lib/managed-session-storage.js +56 -253
  81. package/dist/extensions/agent-browser/lib/native-confirmation.js +140 -0
  82. package/dist/extensions/agent-browser/lib/native-output.js +43 -9
  83. package/dist/extensions/agent-browser/lib/orchestration/batch-stdin.js +106 -59
  84. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-merge.js +14 -6
  85. package/dist/extensions/agent-browser/lib/orchestration/browser-run/artifact-paths.js +109 -57
  86. package/dist/extensions/agent-browser/lib/orchestration/browser-run/browser-observation-result.js +82 -0
  87. package/dist/extensions/agent-browser/lib/orchestration/browser-run/click-dispatch.js +164 -60
  88. package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostic-values.js +31 -0
  89. package/dist/extensions/agent-browser/lib/orchestration/browser-run/diagnostics.js +152 -781
  90. package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-observation.js +203 -0
  91. package/dist/extensions/agent-browser/lib/orchestration/browser-run/electron-text-diagnostics.js +109 -0
  92. package/dist/extensions/agent-browser/lib/orchestration/browser-run/fill-diagnostics.js +119 -0
  93. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-action-recovery.js +147 -0
  94. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-actions.js +144 -0
  95. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-content.js +123 -0
  96. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-contracts.js +1 -0
  97. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-details.js +156 -0
  98. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-electron.js +187 -0
  99. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-evidence.js +39 -0
  100. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-missing-binary.js +89 -0
  101. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-recovery.js +97 -0
  102. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-redaction.js +106 -0
  103. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result-timeout.js +110 -0
  104. package/dist/extensions/agent-browser/lib/orchestration/browser-run/final-result.js +41 -538
  105. package/dist/extensions/agent-browser/lib/orchestration/browser-run/index.js +199 -154
  106. package/dist/extensions/agent-browser/lib/orchestration/browser-run/interaction-diagnostics.js +290 -0
  107. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-close.js +167 -0
  108. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-inspection.js +108 -0
  109. package/dist/extensions/agent-browser/lib/orchestration/browser-run/managed-session-daemon-policy.js +127 -205
  110. package/dist/extensions/agent-browser/lib/orchestration/browser-run/native-helper-observation.js +65 -0
  111. package/dist/extensions/agent-browser/lib/orchestration/browser-run/observation-types.js +1 -0
  112. package/dist/extensions/agent-browser/lib/orchestration/browser-run/overlay-diagnostics.js +120 -0
  113. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/network-page-filter.js +113 -30
  114. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/scroll-shims.js +109 -28
  115. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter-data.js +150 -0
  116. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-filter.js +147 -253
  117. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/snapshot-rendered-text.js +147 -0
  118. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare/wait-timeouts.js +59 -24
  119. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-artifacts.js +159 -0
  120. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-command.js +131 -0
  121. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-contracts.js +1 -0
  122. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-daemon.js +93 -0
  123. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-failure.js +42 -0
  124. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-guards.js +242 -0
  125. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-input.js +75 -0
  126. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-observations.js +92 -0
  127. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-selection.js +254 -0
  128. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-page-state.js +121 -0
  129. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-refs.js +130 -0
  130. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-resources.js +114 -0
  131. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-semantic.js +121 -0
  132. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-session-plan.js +222 -0
  133. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare-timeouts.js +68 -0
  134. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prepare.js +176 -1123
  135. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-analysis.js +191 -0
  136. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-confirmation.js +152 -0
  137. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-diagnostics.js +182 -0
  138. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-electron.js +150 -0
  139. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-contracts.js +1 -0
  140. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase-contracts.js +1 -0
  141. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle-phase.js +115 -0
  142. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-lifecycle.js +256 -0
  143. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed-contracts.js +1 -0
  144. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-managed.js +256 -0
  145. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase-contracts.js +1 -0
  146. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native-phase.js +93 -0
  147. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-native.js +113 -0
  148. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation-contracts.js +1 -0
  149. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-navigation.js +316 -0
  150. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-ownership.js +28 -0
  151. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase-contracts.js +1 -0
  152. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-page-phase.js +142 -0
  153. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation-contracts.js +1 -0
  154. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-presentation.js +333 -0
  155. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase-contracts.js +1 -0
  156. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication-phase.js +71 -0
  157. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-publication.js +201 -0
  158. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-receipts.js +183 -0
  159. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-refs.js +200 -0
  160. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output-tabs.js +142 -0
  161. package/dist/extensions/agent-browser/lib/orchestration/browser-run/process-output.js +18 -968
  162. package/dist/extensions/agent-browser/lib/orchestration/browser-run/prompt-guards.js +23 -13
  163. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-receipt-reconciliation.js +198 -0
  164. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-contracts.js +1 -0
  165. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery-presentation.js +154 -0
  166. package/dist/extensions/agent-browser/lib/orchestration/browser-run/recording-recovery.js +68 -151
  167. package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-capture.js +14 -0
  168. package/dist/extensions/agent-browser/lib/orchestration/browser-run/screenshot-observation.js +169 -46
  169. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-commands.js +130 -0
  170. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-electron.js +212 -0
  171. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-observations.js +61 -0
  172. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-outcomes.js +187 -0
  173. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-refs.js +169 -0
  174. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state-tabs.js +228 -0
  175. package/dist/extensions/agent-browser/lib/orchestration/browser-run/session-state.js +77 -765
  176. package/dist/extensions/agent-browser/lib/orchestration/browser-run/text-visibility-diagnostics.js +182 -0
  177. package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-diagnostics.js +256 -0
  178. package/dist/extensions/agent-browser/lib/orchestration/browser-run/timeout-progress.js +108 -0
  179. package/dist/extensions/agent-browser/lib/orchestration/code-artifact-observation.js +39 -0
  180. package/dist/extensions/agent-browser/lib/orchestration/code-image-observation.js +119 -0
  181. package/dist/extensions/agent-browser/lib/orchestration/electron-host/branch.js +93 -0
  182. package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup-result.js +58 -0
  183. package/dist/extensions/agent-browser/lib/orchestration/electron-host/cleanup.js +78 -0
  184. package/dist/extensions/agent-browser/lib/orchestration/electron-host/contracts.js +1 -0
  185. package/dist/extensions/agent-browser/lib/orchestration/electron-host/discovery.js +106 -0
  186. package/dist/extensions/agent-browser/lib/orchestration/electron-host/index.js +48 -821
  187. package/dist/extensions/agent-browser/lib/orchestration/electron-host/policy.js +86 -0
  188. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-collection.js +68 -0
  189. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-data.js +169 -0
  190. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe-presentation.js +182 -0
  191. package/dist/extensions/agent-browser/lib/orchestration/electron-host/probe.js +161 -0
  192. package/dist/extensions/agent-browser/lib/orchestration/electron-host/status.js +167 -0
  193. package/dist/extensions/agent-browser/lib/orchestration/execution-queue.js +22 -10
  194. package/dist/extensions/agent-browser/lib/orchestration/extension-artifact-preflight.js +211 -0
  195. package/dist/extensions/agent-browser/lib/orchestration/extension-artifacts.js +23 -0
  196. package/dist/extensions/agent-browser/lib/orchestration/extension-attachment-replay.js +99 -0
  197. package/dist/extensions/agent-browser/lib/orchestration/extension-branch-restore.js +275 -0
  198. package/dist/extensions/agent-browser/lib/orchestration/extension-code.js +280 -0
  199. package/dist/extensions/agent-browser/lib/orchestration/extension-command-admission.js +303 -0
  200. package/dist/extensions/agent-browser/lib/orchestration/extension-command-output.js +36 -0
  201. package/dist/extensions/agent-browser/lib/orchestration/extension-command-result.js +335 -0
  202. package/dist/extensions/agent-browser/lib/orchestration/extension-command-run.js +227 -0
  203. package/dist/extensions/agent-browser/lib/orchestration/extension-command-state.js +1 -0
  204. package/dist/extensions/agent-browser/lib/orchestration/extension-electron-ownership.js +204 -0
  205. package/dist/extensions/agent-browser/lib/orchestration/extension-execution-locks.js +139 -0
  206. package/dist/extensions/agent-browser/lib/orchestration/extension-execution-queue.js +24 -0
  207. package/dist/extensions/agent-browser/lib/orchestration/extension-host-coordination.js +98 -0
  208. package/dist/extensions/agent-browser/lib/orchestration/extension-host-run.js +295 -0
  209. package/dist/extensions/agent-browser/lib/orchestration/extension-intent-replay.js +41 -0
  210. package/dist/extensions/agent-browser/lib/orchestration/extension-invocation.js +7 -0
  211. package/dist/extensions/agent-browser/lib/orchestration/extension-lifecycle.js +102 -0
  212. package/dist/extensions/agent-browser/lib/orchestration/extension-managed-ownership.js +133 -0
  213. package/dist/extensions/agent-browser/lib/orchestration/extension-observation.js +120 -0
  214. package/dist/extensions/agent-browser/lib/orchestration/extension-prompt.js +180 -0
  215. package/dist/extensions/agent-browser/lib/orchestration/extension-recording.js +290 -0
  216. package/dist/extensions/agent-browser/lib/orchestration/extension-resource-contracts.js +1 -0
  217. package/dist/extensions/agent-browser/lib/orchestration/extension-resource-replay.js +269 -0
  218. package/dist/extensions/agent-browser/lib/orchestration/extension-result-state.js +113 -0
  219. package/dist/extensions/agent-browser/lib/orchestration/extension-runtime.js +146 -0
  220. package/dist/extensions/agent-browser/lib/orchestration/extension-script-leases.js +58 -0
  221. package/dist/extensions/agent-browser/lib/orchestration/extension-tool-boundary.js +62 -0
  222. package/dist/extensions/agent-browser/lib/orchestration/extension-version-check.js +54 -0
  223. package/dist/extensions/agent-browser/lib/orchestration/input-plan-types.js +1 -0
  224. package/dist/extensions/agent-browser/lib/orchestration/input-plan.js +261 -185
  225. package/dist/extensions/agent-browser/lib/orchestration/input-redaction.js +62 -0
  226. package/dist/extensions/agent-browser/lib/orchestration/native-config.js +144 -0
  227. package/dist/extensions/agent-browser/lib/orchestration/native-root-launch.js +77 -0
  228. package/dist/extensions/agent-browser/lib/orchestration/native-session-defaults.js +210 -157
  229. package/dist/extensions/agent-browser/lib/orchestration/operation-paths.js +124 -58
  230. package/dist/extensions/agent-browser/lib/orchestration/output-file.js +197 -99
  231. package/dist/extensions/agent-browser/lib/orchestration/script-mode.js +199 -96
  232. package/dist/extensions/agent-browser/lib/owned-managed-session-context.js +55 -0
  233. package/dist/extensions/agent-browser/lib/page-target-batch.js +118 -0
  234. package/dist/extensions/agent-browser/lib/page-target-guards.js +50 -0
  235. package/dist/extensions/agent-browser/lib/page-target-navigation.js +104 -0
  236. package/dist/extensions/agent-browser/lib/page-target-validation.js +55 -246
  237. package/dist/extensions/agent-browser/lib/parsing.js +13 -4
  238. package/dist/extensions/agent-browser/lib/pi-tool-rendering.js +133 -68
  239. package/dist/extensions/agent-browser/lib/playbook.js +16 -12
  240. package/dist/extensions/agent-browser/lib/process-child.js +284 -0
  241. package/dist/extensions/agent-browser/lib/process-environment.js +13 -6
  242. package/dist/extensions/agent-browser/lib/process-errors.js +23 -0
  243. package/dist/extensions/agent-browser/lib/process-identity.js +47 -15
  244. package/dist/extensions/agent-browser/lib/process-socket-storage.js +256 -0
  245. package/dist/extensions/agent-browser/lib/process-stdout.js +74 -0
  246. package/dist/extensions/agent-browser/lib/process.js +145 -536
  247. package/dist/extensions/agent-browser/lib/prompt-artifacts.js +287 -0
  248. package/dist/extensions/agent-browser/lib/prompt-policy.js +15 -194
  249. package/dist/extensions/agent-browser/lib/read-command.js +41 -0
  250. package/dist/extensions/agent-browser/lib/read-confirmation.js +131 -68
  251. package/dist/extensions/agent-browser/lib/recording-reservations.js +118 -45
  252. package/dist/extensions/agent-browser/lib/redaction-fields.js +75 -0
  253. package/dist/extensions/agent-browser/lib/redaction-json.js +149 -0
  254. package/dist/extensions/agent-browser/lib/redaction-url.js +88 -0
  255. package/dist/extensions/agent-browser/lib/results/action-contracts.js +1 -0
  256. package/dist/extensions/agent-browser/lib/results/action-recommendations.js +28 -271
  257. package/dist/extensions/agent-browser/lib/results/artifact-contracts.js +1 -0
  258. package/dist/extensions/agent-browser/lib/results/artifact-manifest-validation.js +133 -0
  259. package/dist/extensions/agent-browser/lib/results/artifact-manifest.js +96 -94
  260. package/dist/extensions/agent-browser/lib/results/artifact-recommendations.js +73 -0
  261. package/dist/extensions/agent-browser/lib/results/categories.js +111 -54
  262. package/dist/extensions/agent-browser/lib/results/confirmation.js +29 -13
  263. package/dist/extensions/agent-browser/lib/results/editable-ref-evidence.js +62 -27
  264. package/dist/extensions/agent-browser/lib/results/electron-recommendations.js +83 -0
  265. package/dist/extensions/agent-browser/lib/results/envelope-decoding.js +48 -0
  266. package/dist/extensions/agent-browser/lib/results/envelope.js +90 -67
  267. package/dist/extensions/agent-browser/lib/results/evidence-contracts.js +1 -0
  268. package/dist/extensions/agent-browser/lib/results/failure-recommendations.js +180 -0
  269. package/dist/extensions/agent-browser/lib/results/network-routes.js +86 -45
  270. package/dist/extensions/agent-browser/lib/results/network.js +35 -12
  271. package/dist/extensions/agent-browser/lib/results/next-actions.js +49 -19
  272. package/dist/extensions/agent-browser/lib/results/presentation/artifact-files.js +320 -0
  273. package/dist/extensions/agent-browser/lib/results/presentation/artifact-format.js +138 -0
  274. package/dist/extensions/agent-browser/lib/results/presentation/artifact-images.js +113 -0
  275. package/dist/extensions/agent-browser/lib/results/presentation/artifact-verification.js +145 -0
  276. package/dist/extensions/agent-browser/lib/results/presentation/artifacts.js +99 -555
  277. package/dist/extensions/agent-browser/lib/results/presentation/batch-contracts.js +1 -0
  278. package/dist/extensions/agent-browser/lib/results/presentation/batch-recording.js +118 -0
  279. package/dist/extensions/agent-browser/lib/results/presentation/batch-redaction.js +68 -0
  280. package/dist/extensions/agent-browser/lib/results/presentation/batch-rendering.js +135 -0
  281. package/dist/extensions/agent-browser/lib/results/presentation/batch-step.js +227 -0
  282. package/dist/extensions/agent-browser/lib/results/presentation/batch-summary.js +91 -0
  283. package/dist/extensions/agent-browser/lib/results/presentation/batch.js +91 -460
  284. package/dist/extensions/agent-browser/lib/results/presentation/browser-profile-recovery.js +9 -5
  285. package/dist/extensions/agent-browser/lib/results/presentation/command-presenters.js +216 -0
  286. package/dist/extensions/agent-browser/lib/results/presentation/common.js +26 -9
  287. package/dist/extensions/agent-browser/lib/results/presentation/content.js +86 -29
  288. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-a11y.js +67 -0
  289. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-health.js +79 -0
  290. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-identity.js +199 -0
  291. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-logs.js +75 -0
  292. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network-actions.js +216 -0
  293. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-network.js +124 -0
  294. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-redaction.js +64 -0
  295. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-storage.js +209 -0
  296. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-stream.js +69 -0
  297. package/dist/extensions/agent-browser/lib/results/presentation/diagnostic-summary.js +222 -0
  298. package/dist/extensions/agent-browser/lib/results/presentation/diagnostics.js +103 -1052
  299. package/dist/extensions/agent-browser/lib/results/presentation/early-result.js +70 -0
  300. package/dist/extensions/agent-browser/lib/results/presentation/errors.js +130 -60
  301. package/dist/extensions/agent-browser/lib/results/presentation/input-contracts.js +1 -0
  302. package/dist/extensions/agent-browser/lib/results/presentation/large-output.js +60 -145
  303. package/dist/extensions/agent-browser/lib/results/presentation/navigation.js +147 -88
  304. package/dist/extensions/agent-browser/lib/results/presentation/notices.js +75 -0
  305. package/dist/extensions/agent-browser/lib/results/presentation/observation-contracts.js +1 -0
  306. package/dist/extensions/agent-browser/lib/results/presentation/observation-rendering.js +127 -0
  307. package/dist/extensions/agent-browser/lib/results/presentation/outcomes.js +120 -0
  308. package/dist/extensions/agent-browser/lib/results/presentation/output-completion.js +77 -0
  309. package/dist/extensions/agent-browser/lib/results/presentation/output-spill.js +51 -0
  310. package/dist/extensions/agent-browser/lib/results/presentation/registry.js +116 -240
  311. package/dist/extensions/agent-browser/lib/results/presentation/semantic-action.js +35 -21
  312. package/dist/extensions/agent-browser/lib/results/presentation/skills.js +109 -73
  313. package/dist/extensions/agent-browser/lib/results/presentation/source.js +109 -0
  314. package/dist/extensions/agent-browser/lib/results/presentation.js +17 -261
  315. package/dist/extensions/agent-browser/lib/results/recommendation-contracts.js +1 -0
  316. package/dist/extensions/agent-browser/lib/results/recording.js +52 -14
  317. package/dist/extensions/agent-browser/lib/results/recovery-actions.js +14 -5
  318. package/dist/extensions/agent-browser/lib/results/recovery-next-actions.js +30 -22
  319. package/dist/extensions/agent-browser/lib/results/selector-recovery-target.js +83 -0
  320. package/dist/extensions/agent-browser/lib/results/selector-recovery.js +119 -119
  321. package/dist/extensions/agent-browser/lib/results/snapshot-compact.js +266 -0
  322. package/dist/extensions/agent-browser/lib/results/snapshot-content.js +32 -0
  323. package/dist/extensions/agent-browser/lib/results/snapshot-high-value-controls.js +104 -71
  324. package/dist/extensions/agent-browser/lib/results/snapshot-refs.js +31 -11
  325. package/dist/extensions/agent-browser/lib/results/snapshot-segments.js +125 -66
  326. package/dist/extensions/agent-browser/lib/results/snapshot-spill.js +26 -7
  327. package/dist/extensions/agent-browser/lib/results/snapshot.js +28 -248
  328. package/dist/extensions/agent-browser/lib/results/text.js +16 -5
  329. package/dist/extensions/agent-browser/lib/runtime-args-validation.js +133 -0
  330. package/dist/extensions/agent-browser/lib/runtime-compatibility.js +81 -0
  331. package/dist/extensions/agent-browser/lib/runtime-contracts.js +1 -0
  332. package/dist/extensions/agent-browser/lib/runtime-redaction.js +118 -0
  333. package/dist/extensions/agent-browser/lib/runtime-replay-events.js +144 -0
  334. package/dist/extensions/agent-browser/lib/runtime-session-identity.js +76 -0
  335. package/dist/extensions/agent-browser/lib/runtime-session-plan.js +114 -0
  336. package/dist/extensions/agent-browser/lib/runtime-session-replay.js +123 -0
  337. package/dist/extensions/agent-browser/lib/runtime-tab-correction.js +65 -0
  338. package/dist/extensions/agent-browser/lib/runtime-timeouts.js +28 -0
  339. package/dist/extensions/agent-browser/lib/runtime.js +137 -1041
  340. package/dist/extensions/agent-browser/lib/session-identity.js +51 -0
  341. package/dist/extensions/agent-browser/lib/session-page-observation.js +357 -0
  342. package/dist/extensions/agent-browser/lib/session-page-state.js +178 -333
  343. package/dist/extensions/agent-browser/lib/session-page-types.js +1 -0
  344. package/dist/extensions/agent-browser/lib/temp-artifact-budget.js +81 -0
  345. package/dist/extensions/agent-browser/lib/temp-mutation-queue.js +7 -0
  346. package/dist/extensions/agent-browser/lib/temp-root-ownership.js +234 -0
  347. package/dist/extensions/agent-browser/lib/temp-root.js +211 -0
  348. package/dist/extensions/agent-browser/lib/temp.js +33 -446
  349. package/dist/extensions/agent-browser/lib/tool-surface.js +94 -24
  350. package/dist/extensions/agent-browser/lib/upstream-version.js +3 -2
  351. package/dist/extensions/agent-browser/lib/web-search-providers.js +193 -0
  352. package/dist/extensions/agent-browser/lib/web-search-request.js +102 -0
  353. package/dist/extensions/agent-browser/lib/web-search-results.js +281 -0
  354. package/dist/extensions/agent-browser/lib/web-search-schema.js +82 -0
  355. package/dist/extensions/agent-browser/lib/web-search.js +124 -614
  356. package/dist/extensions/agent-browser/lib/webmcp-observation.js +13 -6
  357. package/dist/extensions/agent-browser/lib/windows-stock-launcher.js +63 -37
  358. package/dist/extensions/agent-browser/script-worker.js +80 -43
  359. package/dist/scripts/agent-browser-target.mjs +4 -2
  360. package/docs/ARCHITECTURE.md +19 -6
  361. package/docs/CODE_QUALITY.md +267 -0
  362. package/docs/COMMAND_REFERENCE.md +272 -241
  363. package/docs/ELECTRON.md +77 -46
  364. package/docs/REFERENCE.md +869 -0
  365. package/docs/RELEASE.md +25 -22
  366. package/docs/REQUIREMENTS.md +2 -1
  367. package/docs/SUPPORT_MATRIX.md +81 -79
  368. package/docs/TOOL_CONTRACT.md +158 -125
  369. package/docs/platform-smoke.md +8 -8
  370. package/package.json +144 -120
  371. package/scripts/agent-browser-capability-baseline.mjs +361 -957
  372. package/scripts/agent-browser-target.mjs +6 -2
  373. package/scripts/build.mjs +37 -8
  374. package/scripts/capability-core-commands.mjs +193 -0
  375. package/scripts/capability-options.mjs +283 -0
  376. package/scripts/capability-samples.mjs +133 -0
  377. package/scripts/capability-section.mjs +11 -0
  378. package/scripts/config.mjs +235 -132
  379. package/scripts/convert-browser-session.mjs +30 -9
  380. package/scripts/doctor-sources.mjs +195 -0
  381. package/scripts/doctor.mjs +94 -249
  382. package/scripts/platform-smoke/artifacts.mjs +38 -11
  383. package/scripts/platform-smoke/commands.mjs +104 -0
  384. package/scripts/platform-smoke/crabbox-runner.mjs +167 -80
  385. package/scripts/platform-smoke/doctor-support.mjs +157 -0
  386. package/scripts/platform-smoke/doctor-windows.mjs +230 -0
  387. package/scripts/platform-smoke/doctor.mjs +212 -320
  388. package/scripts/platform-smoke/lease-evidence.mjs +132 -0
  389. package/scripts/platform-smoke/linux-image/Dockerfile +8 -2
  390. package/scripts/platform-smoke/suite-checks.mjs +98 -0
  391. package/scripts/platform-smoke/suite-evidence.mjs +281 -0
  392. package/scripts/platform-smoke/targets.mjs +154 -472
  393. package/scripts/platform-smoke.mjs +55 -40
  394. package/scripts/prepare.mjs +16 -7
@@ -1,63 +1,52 @@
1
- import { spawn } from "node:child_process";
2
1
  import { randomUUID } from "node:crypto";
3
- import { open, readFile, rm } from "node:fs/promises";
4
- import { dirname, join } from "node:path";
5
- import { fetchCdpJson, parseCdpTargets, parseCdpVersion, } from "./cdp.js";
2
+ import { rm } from "node:fs/promises";
6
3
  import { discoverElectronApps, inspectElectronAppPath, inspectElectronExecutablePath, } from "./discovery.js";
7
4
  import { createSecureTempDirectory, preserveSecureTempDirectory } from "../temp.js";
8
- export const ELECTRON_LAUNCH_RECORD_VERSION = 1;
9
- const ELECTRON_LAUNCH_DEFAULT_TIMEOUT_MS = 15_000;
10
- const ELECTRON_LAUNCH_MAX_TIMEOUT_MS = 120_000;
11
- const DEVTOOLS_ACTIVE_PORT_FILE = "DevToolsActivePort";
12
- export const ELECTRON_PROFILE_DIR_PREFIX = "electron-profile-";
13
- const ELECTRON_DEFAULT_APP_ARGS = ["--disable-extensions", "--no-first-run", "--no-default-browser-check"];
14
- const ELECTRON_DEVTOOLS_POLL_INTERVAL_MS = 100;
15
- // ponytail: bound failure reads, not lifetime log growth; noisy long-lived apps need rotation if that becomes a problem.
16
- const ELECTRON_OUTPUT_TAIL_BYTES = 4096;
5
+ import { stringifyUnknown } from "../results/text.js";
6
+ import { readProcessStartIdentity } from "../process-identity.js";
7
+ import { isElectronLaunchAborted, pollCdpMetadata, pollDevToolsActivePort, } from "./launch-monitor.js";
8
+ import { ElectronLaunchProcess } from "./launch-process.js";
9
+ import { ELECTRON_LAUNCH_RECORD_VERSION, ELECTRON_PROFILE_DIR_PREFIX, } from "./launch-types.js";
10
+ export { ELECTRON_LAUNCH_RECORD_VERSION, ELECTRON_PROFILE_DIR_PREFIX } from "./launch-types.js";
11
+ const DEFAULT_TIMEOUT_MS = 15_000;
12
+ const MAX_TIMEOUT_MS = 120_000;
13
+ const DEFAULT_APP_ARGS = ["--disable-extensions", "--no-first-run", "--no-default-browser-check"];
17
14
  function normalizeTimeoutMs(timeoutMs) {
18
- if (!Number.isSafeInteger(timeoutMs) || (timeoutMs ?? 0) <= 0)
19
- return ELECTRON_LAUNCH_DEFAULT_TIMEOUT_MS;
20
- return Math.min(timeoutMs, ELECTRON_LAUNCH_MAX_TIMEOUT_MS);
21
- }
22
- function sleep(ms, signal) {
23
- if (signal?.aborted)
24
- return Promise.resolve();
25
- return new Promise((resolve) => {
26
- const timer = setTimeout(done, ms);
27
- function done() {
28
- clearTimeout(timer);
29
- signal?.removeEventListener("abort", done);
30
- resolve();
31
- }
32
- signal?.addEventListener("abort", done, { once: true });
33
- });
15
+ if (typeof timeoutMs !== "number" || !Number.isSafeInteger(timeoutMs) || timeoutMs <= 0) {
16
+ return DEFAULT_TIMEOUT_MS;
17
+ }
18
+ return Math.min(timeoutMs, MAX_TIMEOUT_MS);
34
19
  }
35
20
  function normalizeIdentifier(value) {
36
21
  const trimmed = value?.trim().toLowerCase();
37
- return trimmed && trimmed.length > 0 ? trimmed : undefined;
38
- }
39
- function appIdentifiers(app) {
40
- return [app.name, app.bundleId, app.desktopId, app.appPath, app.executablePath]
41
- .filter((value) => typeof value === "string" && value.trim().length > 0);
22
+ return trimmed !== undefined && trimmed.length > 0 ? trimmed : undefined;
42
23
  }
43
24
  function policyEntryMatchesApp(entry, app) {
44
- const normalizedEntry = normalizeIdentifier(entry);
45
- if (!normalizedEntry)
25
+ const normalized = normalizeIdentifier(entry);
26
+ if (normalized === undefined) {
46
27
  return false;
47
- return appIdentifiers(app).some((identifier) => identifier.toLowerCase().includes(normalizedEntry));
28
+ }
29
+ const identifiers = [
30
+ app.name,
31
+ app.bundleId,
32
+ app.desktopId,
33
+ app.appPath,
34
+ app.executablePath,
35
+ ].filter((value) => typeof value === "string" && value.trim().length > 0);
36
+ return identifiers.some((identifier) => identifier.toLowerCase().includes(normalized));
48
37
  }
49
- function evaluateElectronLaunchPolicy(options) {
50
- const denyEntry = options.deny?.find((entry) => policyEntryMatchesApp(entry, options.target));
51
- if (denyEntry) {
38
+ function evaluateLaunchPolicy(options, target) {
39
+ const denyEntry = options.deny?.find((entry) => policyEntryMatchesApp(entry, target));
40
+ if (denyEntry !== undefined && denyEntry.length > 0) {
52
41
  return {
53
42
  entry: denyEntry,
54
43
  list: "deny",
55
44
  message: `Electron launch blocked by caller deny policy: ${denyEntry}`,
56
45
  };
57
46
  }
58
- if (options.allow && options.allow.length > 0) {
59
- const allowEntry = options.allow.find((entry) => policyEntryMatchesApp(entry, options.target));
60
- if (!allowEntry) {
47
+ if (options.allow !== undefined && options.allow.length > 0) {
48
+ const allowEntry = options.allow.find((entry) => policyEntryMatchesApp(entry, target));
49
+ if (allowEntry === undefined || allowEntry.length === 0) {
61
50
  return {
62
51
  list: "allow",
63
52
  message: "Electron launch blocked because the resolved app did not match caller allow policy.",
@@ -66,157 +55,38 @@ function evaluateElectronLaunchPolicy(options) {
66
55
  }
67
56
  return undefined;
68
57
  }
69
- async function resolveElectronLaunchTarget(options) {
70
- if (options.appPath)
58
+ async function resolveLaunchTarget(options) {
59
+ if (options.appPath !== undefined && options.appPath.length > 0) {
71
60
  return inspectElectronAppPath(options.appPath);
72
- if (options.executablePath)
73
- return inspectElectronExecutablePath(options.executablePath);
74
- const query = options.bundleId ?? options.appName;
75
- const discovery = await discoverElectronApps({ maxResults: 200, query });
76
- if (options.bundleId) {
77
- const normalizedBundleId = normalizeIdentifier(options.bundleId);
78
- return discovery.apps.find((app) => normalizeIdentifier(app.bundleId) === normalizedBundleId);
79
- }
80
- if (options.appName) {
81
- const normalizedName = normalizeIdentifier(options.appName);
82
- return discovery.apps.find((app) => normalizeIdentifier(app.name) === normalizedName) ?? discovery.apps[0];
83
- }
84
- return undefined;
85
- }
86
- function targetMatchesType(target, targetType) {
87
- return targetType === undefined || targetType === "any" || target.type === targetType;
88
- }
89
- function selectElectronConnectArg(options) {
90
- const targetWebSocket = options.targets.find((target) => targetMatchesType(target, options.targetType) && target.webSocketDebuggerUrl)?.webSocketDebuggerUrl;
91
- return targetWebSocket ?? options.version.webSocketDebuggerUrl ?? String(options.port);
92
- }
93
- async function readDevToolsActivePort(userDataDir) {
94
- const path = `${userDataDir}/${DEVTOOLS_ACTIVE_PORT_FILE}`;
95
- try {
96
- const text = await readFile(path, "utf8");
97
- const [portLine] = text.split(/\r?\n/);
98
- const port = Number(portLine?.trim());
99
- return {
100
- found: true,
101
- path,
102
- port: Number.isSafeInteger(port) && port > 0 && port <= 65_535 ? port : undefined,
103
- ...(Number.isSafeInteger(port) && port > 0 && port <= 65_535 ? {} : { error: "DevToolsActivePort did not contain a valid TCP port." }),
104
- };
105
61
  }
106
- catch (error) {
107
- const code = error.code;
108
- return {
109
- error: code && code !== "ENOENT" ? `${code}: ${error instanceof Error ? error.message : String(error)}` : undefined,
110
- found: false,
111
- path,
112
- };
113
- }
114
- }
115
- async function pollDevToolsActivePort(options) {
116
- let devToolsActivePort;
117
- while (Date.now() <= options.deadlineMs) {
118
- if (options.signal?.aborted)
119
- return { devToolsActivePort, failure: "aborted" };
120
- const spawnError = options.getSpawnError();
121
- if (spawnError)
122
- return { devToolsActivePort, failure: "spawn-error", spawnError };
123
- devToolsActivePort = await readDevToolsActivePort(options.userDataDir);
124
- if (devToolsActivePort.port)
125
- return { devToolsActivePort, port: devToolsActivePort.port };
126
- const exit = options.getChildExit();
127
- if (exit.code !== null || exit.signal !== null) {
128
- return { devToolsActivePort, failure: exit.code === 0 ? "single-instance-conflict" : "spawn-error" };
129
- }
130
- await sleep(ELECTRON_DEVTOOLS_POLL_INTERVAL_MS, options.signal);
131
- }
132
- return { devToolsActivePort, failure: "timeout" };
133
- }
134
- async function pollCdpMetadata(port, deadlineMs, signal) {
135
- while (Date.now() <= deadlineMs) {
136
- if (signal?.aborted)
137
- return { aborted: true };
138
- const version = parseCdpVersion(await fetchCdpJson(`http://127.0.0.1:${port}/json/version`, signal));
139
- if (signal?.aborted)
140
- return { aborted: true };
141
- if (version) {
142
- const targets = parseCdpTargets(await fetchCdpJson(`http://127.0.0.1:${port}/json/list`, signal));
143
- return signal?.aborted ? { aborted: true } : { aborted: false, metadata: { targets, version } };
144
- }
145
- await sleep(ELECTRON_DEVTOOLS_POLL_INTERVAL_MS, signal);
146
- }
147
- return { aborted: false };
148
- }
149
- function buildLaunchArgs(userDataDir, appArgs) {
150
- return [
151
- ...appArgs,
152
- `--user-data-dir=${userDataDir}`,
153
- "--remote-debugging-port=0",
154
- ...ELECTRON_DEFAULT_APP_ARGS,
155
- ];
156
- }
157
- async function waitForLaunchChildExit(child, deadlineMs) {
158
- while (Date.now() <= deadlineMs) {
159
- if (child.exitCode !== null || child.signalCode !== null)
160
- return true;
161
- await sleep(50);
62
+ if (options.executablePath !== undefined && options.executablePath.length > 0) {
63
+ return inspectElectronExecutablePath(options.executablePath);
162
64
  }
163
- return child.exitCode !== null || child.signalCode !== null;
65
+ const discovery = await discoverElectronApps({
66
+ maxResults: 200,
67
+ query: options.bundleId ?? options.appName,
68
+ });
69
+ return selectDiscoveredTarget(discovery.apps, options);
164
70
  }
165
- function isLaunchChildPidAlive(child) {
166
- if (!child.pid)
167
- return undefined;
168
- if (child.exitCode !== null || child.signalCode !== null)
169
- return false;
170
- try {
171
- process.kill(child.pid, 0);
172
- return true;
71
+ function selectDiscoveredTarget(apps, options) {
72
+ if ((options.bundleId ?? "").length > 0) {
73
+ const bundleId = normalizeIdentifier(options.bundleId);
74
+ return apps.find((app) => normalizeIdentifier(app.bundleId) === bundleId);
173
75
  }
174
- catch (error) {
175
- return error.code === "EPERM";
76
+ if ((options.appName ?? "").length > 0) {
77
+ const name = normalizeIdentifier(options.appName);
78
+ return apps.find((app) => normalizeIdentifier(app.name) === name) ?? apps.at(0);
176
79
  }
80
+ return undefined;
177
81
  }
178
- async function terminateLaunchChild(child) {
179
- if (!child.pid || child.exitCode !== null || child.signalCode !== null)
180
- return undefined;
181
- try {
182
- child.kill("SIGTERM");
183
- }
184
- catch (error) {
185
- return error instanceof Error ? error.message : String(error);
186
- }
187
- if (await waitForLaunchChildExit(child, Date.now() + 1_000))
188
- return undefined;
189
- try {
190
- child.kill("SIGKILL");
191
- }
192
- catch (error) {
193
- return error instanceof Error ? error.message : String(error);
194
- }
195
- if (await waitForLaunchChildExit(child, Date.now() + 1_000))
196
- return undefined;
197
- return `PID ${child.pid} remained alive after failed Electron launch cleanup.`;
82
+ function targetMatchesType(target, type) {
83
+ return type === undefined || type === "any" || target.type === type;
198
84
  }
199
- function buildLaunchRecord(options) {
200
- return {
201
- appName: options.target.name,
202
- appPath: options.target.appPath,
203
- bundleId: options.target.bundleId,
204
- cleanupState: "active",
205
- createdAtMs: options.createdAtMs,
206
- desktopId: options.target.desktopId,
207
- executablePath: options.target.executablePath,
208
- launchId: `electron-${randomUUID()}`,
209
- launchedByWrapper: true,
210
- packageSource: options.target.packageSource,
211
- pid: options.pid,
212
- platform: options.target.platform,
213
- port: options.port,
214
- processGroupId: process.platform === "win32" ? undefined : options.pid,
215
- targetType: options.targetType,
216
- userDataDir: options.userDataDir,
217
- version: ELECTRON_LAUNCH_RECORD_VERSION,
218
- webSocketDebuggerUrl: options.version.webSocketDebuggerUrl,
219
- };
85
+ function selectConnectArg(port, metadata, type) {
86
+ const targetSocket = metadata.targets.find((target) => targetMatchesType(target, type) &&
87
+ target.webSocketDebuggerUrl !== undefined &&
88
+ target.webSocketDebuggerUrl.length > 0)?.webSocketDebuggerUrl;
89
+ return targetSocket ?? metadata.version.webSocketDebuggerUrl ?? String(port);
220
90
  }
221
91
  function launchFailureMessage(reason, target, detail) {
222
92
  const label = target ? `${target.name} (${target.appPath ?? target.executablePath})` : "target";
@@ -224,7 +94,7 @@ function launchFailureMessage(reason, target, detail) {
224
94
  case "aborted":
225
95
  return `Electron launch was aborted${target ? ` before ${label} finished starting` : " before the app started"}.`;
226
96
  case "non-electron-target":
227
- return `Electron launch rejected: ${label} does not have Electron framework evidence.`;
97
+ return `Electron launch rejected: ${label} does not have the required Electron runtime and app payload evidence.`;
228
98
  case "policy-blocked":
229
99
  return detail ?? `Electron launch blocked by caller policy for ${label}.`;
230
100
  case "single-instance-conflict":
@@ -232,203 +102,239 @@ function launchFailureMessage(reason, target, detail) {
232
102
  case "port-not-found":
233
103
  return `Electron launch found a DevToolsActivePort for ${label}, but /json/version never returned a valid CDP payload.`;
234
104
  case "spawn-error":
235
- return `Electron launch failed while starting ${label}${detail ? `: ${detail}` : "."}`;
105
+ return `Electron launch failed while starting ${label}${detail !== undefined && detail.length > 0 ? `: ${detail}` : "."}`;
236
106
  case "timeout":
237
107
  return `Electron launch timed out waiting for DevToolsActivePort for ${label}.`;
238
108
  }
239
109
  }
240
- export async function launchElectronApp(options) {
241
- const appArgs = options.appArgs ?? [];
242
- if (options.signal?.aborted)
243
- return { ok: false, failure: { appArgs, error: launchFailureMessage("aborted", undefined), reason: "aborted" } };
244
- const target = await resolveElectronLaunchTarget(options);
245
- if (options.signal?.aborted)
246
- return { ok: false, failure: { appArgs, error: launchFailureMessage("aborted", target), reason: "aborted", target } };
247
- if (!target) {
110
+ /** Owns one profile and process attempt; only a successful result transfers them to the host. */
111
+ class ElectronLaunchAttempt {
112
+ options;
113
+ target;
114
+ userDataDir;
115
+ process;
116
+ startedAtMs;
117
+ timeoutMs;
118
+ deadlineMs;
119
+ appArgs;
120
+ startIdentity;
121
+ constructor(options, target, userDataDir, timing) {
122
+ this.options = options;
123
+ this.target = target;
124
+ this.userDataDir = userDataDir;
125
+ this.process = new ElectronLaunchProcess(userDataDir);
126
+ this.startedAtMs = timing.startedAtMs;
127
+ this.timeoutMs = timing.timeoutMs;
128
+ this.deadlineMs = timing.startedAtMs + timing.timeoutMs;
129
+ this.appArgs = options.appArgs ?? [];
130
+ }
131
+ diagnostics(observation) {
248
132
  return {
249
- ok: false,
250
- failure: {
251
- appArgs,
252
- error: launchFailureMessage("non-electron-target", undefined),
253
- reason: "non-electron-target",
254
- },
133
+ ...observation,
134
+ elapsedMs: Math.max(0, Date.now() - this.startedAtMs),
135
+ exitCode: this.process.exitCode,
136
+ exitSignal: this.process.exitSignal,
137
+ outputCaptured: this.process.outputCaptured,
138
+ pid: this.process.child?.pid,
139
+ pidAlive: this.process.child === undefined ? undefined : this.process.pidAlive(),
140
+ port: observation.port ?? observation.devToolsActivePort?.port,
141
+ timeoutMs: this.timeoutMs,
142
+ userDataDir: this.userDataDir,
255
143
  };
256
144
  }
257
- const policy = evaluateElectronLaunchPolicy({ allow: options.allow, deny: options.deny, target });
258
- if (policy) {
145
+ async cleanupProfile(processError) {
146
+ try {
147
+ if (processError !== undefined && processError.length > 0) {
148
+ await preserveSecureTempDirectory(this.userDataDir);
149
+ }
150
+ else {
151
+ await rm(this.userDataDir, { force: true, recursive: true });
152
+ }
153
+ return undefined;
154
+ }
155
+ catch (error) {
156
+ const message = error instanceof Error ? error.message : stringifyUnknown(error);
157
+ return processError !== undefined && processError.length > 0
158
+ ? `Profile preservation failed: ${message}`
159
+ : message;
160
+ }
161
+ }
162
+ async fail(reason, detail, observation = {}) {
163
+ const diagnostics = this.diagnostics(observation);
164
+ const processError = await this.process.terminate();
165
+ const output = await this.process.readOutput();
166
+ const profileError = await this.cleanupProfile(processError);
167
+ const cleanupErrors = [processError, this.process.cleanupError, profileError].filter((value) => value !== undefined);
168
+ const cleanupError = cleanupErrors.join("; ");
259
169
  return {
260
170
  ok: false,
261
171
  failure: {
262
- appArgs,
263
- error: launchFailureMessage("policy-blocked", target, policy.message),
264
- policy,
265
- reason: "policy-blocked",
266
- target,
172
+ appArgs: this.appArgs,
173
+ cleanupError: cleanupError.length === 0 ? undefined : cleanupError,
174
+ diagnostics: { ...diagnostics, ...output.evidence },
175
+ error: [launchFailureMessage(reason, this.target, detail), ...output.lines].join("\n"),
176
+ reason,
177
+ target: this.target,
178
+ userDataDir: this.userDataDir,
267
179
  },
268
180
  };
269
181
  }
270
- const timeoutMs = normalizeTimeoutMs(options.timeoutMs);
271
- const startedAtMs = Date.now();
272
- const deadlineMs = startedAtMs + timeoutMs;
273
- const userDataDir = await createSecureTempDirectory(ELECTRON_PROFILE_DIR_PREFIX);
274
- if (options.signal?.aborted) {
275
- let cleanupError;
276
- try {
277
- await rm(userDataDir, { force: true, recursive: true });
182
+ record(port, version) {
183
+ const pid = this.process.child?.pid;
184
+ return {
185
+ appName: this.target.name,
186
+ appPath: this.target.appPath,
187
+ bundleId: this.target.bundleId,
188
+ cleanupState: "active",
189
+ createdAtMs: Date.now(),
190
+ desktopId: this.target.desktopId,
191
+ executablePath: this.target.executablePath,
192
+ launchId: `electron-${randomUUID()}`,
193
+ launchedByWrapper: true,
194
+ packageSource: this.target.packageSource,
195
+ pid,
196
+ platform: this.target.platform,
197
+ port,
198
+ processGroupId: process.platform === "win32" ? undefined : pid,
199
+ startIdentity: this.startIdentity,
200
+ targetType: this.options.targetType,
201
+ userDataDir: this.userDataDir,
202
+ version: ELECTRON_LAUNCH_RECORD_VERSION,
203
+ webSocketDebuggerUrl: version.webSocketDebuggerUrl,
204
+ };
205
+ }
206
+ async run() {
207
+ const args = [
208
+ ...this.appArgs,
209
+ `--user-data-dir=${this.userDataDir}`,
210
+ "--remote-debugging-port=0",
211
+ ...DEFAULT_APP_ARGS,
212
+ ];
213
+ await this.process.spawn(this.target.executablePath, args, this.options.signal);
214
+ if (this.process.child === undefined) {
215
+ return this.fail(isElectronLaunchAborted(this.options.signal) ? "aborted" : "spawn-error", this.process.spawnError?.message);
278
216
  }
279
- catch (error) {
280
- cleanupError = error instanceof Error ? error.message : String(error);
217
+ const pid = this.process.child.pid;
218
+ this.startIdentity =
219
+ pid === undefined
220
+ ? undefined
221
+ : await readProcessStartIdentity(pid, process.platform, {
222
+ deadline: this.deadlineMs,
223
+ signal: this.options.signal,
224
+ });
225
+ const portResult = await pollDevToolsActivePort({
226
+ deadlineMs: this.deadlineMs,
227
+ getChildExit: this.process.childExit,
228
+ getSpawnError: this.process.childSpawnError,
229
+ signal: this.options.signal,
230
+ userDataDir: this.userDataDir,
231
+ });
232
+ if (portResult.port === undefined) {
233
+ return this.fail(portResult.failure ?? "timeout", portResult.spawnError?.message, {
234
+ devToolsActivePort: portResult.devToolsActivePort,
235
+ });
236
+ }
237
+ return this.connect(portResult.port, portResult.devToolsActivePort);
238
+ }
239
+ async connect(port, devToolsActivePort) {
240
+ const metadataResult = await pollCdpMetadata(port, this.deadlineMs, this.options.signal);
241
+ if (metadataResult.aborted) {
242
+ return this.fail("aborted", undefined, { devToolsActivePort, port });
243
+ }
244
+ const metadata = metadataResult.metadata;
245
+ if (metadata === undefined) {
246
+ return this.fail("port-not-found", undefined, {
247
+ cdpVersionReached: false,
248
+ devToolsActivePort,
249
+ port,
250
+ });
251
+ }
252
+ const child = this.process.child;
253
+ if (child === undefined) {
254
+ throw new Error("Electron launch lost its child handle before handoff.");
281
255
  }
282
- return { ok: false, failure: { appArgs, cleanupError, error: launchFailureMessage("aborted", target), reason: "aborted", target, userDataDir } };
256
+ return {
257
+ ok: true,
258
+ value: {
259
+ appArgs: this.appArgs,
260
+ child,
261
+ connectArg: selectConnectArg(port, metadata, this.options.targetType),
262
+ record: this.record(port, metadata.version),
263
+ target: this.target,
264
+ targets: metadata.targets,
265
+ version: metadata.version,
266
+ },
267
+ };
283
268
  }
269
+ }
270
+ async function abortedProfileResult(userDataDir, options, target) {
284
271
  let cleanupError;
285
- let spawnError;
286
- let exitCode = null;
287
- let exitSignal = null;
288
- const args = buildLaunchArgs(userDataDir, appArgs);
289
- let child;
290
- let outputCaptured = false;
291
- const outputFiles = [];
292
272
  try {
293
- for (const stream of ["stdout", "stderr"])
294
- outputFiles.push(await open(join(userDataDir, `${stream}.log`), "wx", 0o600));
295
- options.signal?.throwIfAborted();
296
- child = spawn(target.executablePath, args, {
297
- cwd: dirname(target.executablePath),
298
- detached: process.platform !== "win32",
299
- stdio: ["ignore", outputFiles[0].fd, outputFiles[1].fd],
300
- });
301
- outputCaptured = true;
302
- child.once("error", (error) => {
303
- spawnError = error;
304
- });
305
- child.once("exit", (code, signal) => {
306
- exitCode = code;
307
- exitSignal = signal;
308
- });
309
- child.unref();
273
+ await rm(userDataDir, { force: true, recursive: true });
310
274
  }
311
275
  catch (error) {
312
- spawnError = error instanceof Error ? error : new Error(String(error));
276
+ cleanupError = error instanceof Error ? error.message : stringifyUnknown(error);
313
277
  }
314
- finally {
315
- for (const file of outputFiles) {
316
- await file.close().catch((error) => {
317
- cleanupError = [cleanupError, `Output handle close failed: ${error instanceof Error ? error.message : String(error)}`].filter(Boolean).join("; ");
318
- });
319
- }
278
+ return {
279
+ ok: false,
280
+ failure: {
281
+ appArgs: options.appArgs ?? [],
282
+ cleanupError,
283
+ error: launchFailureMessage("aborted", target),
284
+ reason: "aborted",
285
+ target,
286
+ userDataDir,
287
+ },
288
+ };
289
+ }
290
+ export async function launchElectronApp(options) {
291
+ const appArgs = options.appArgs ?? [];
292
+ if (isElectronLaunchAborted(options.signal)) {
293
+ return {
294
+ ok: false,
295
+ failure: { appArgs, error: launchFailureMessage("aborted", undefined), reason: "aborted" },
296
+ };
320
297
  }
321
- const buildFailureDiagnostics = (options = {}) => ({
322
- cdpVersionReached: options.cdpVersionReached,
323
- devToolsActivePort: options.devToolsActivePort,
324
- elapsedMs: Math.max(0, Date.now() - startedAtMs),
325
- exitCode,
326
- exitSignal,
327
- outputCaptured,
328
- pid: child?.pid,
329
- pidAlive: child ? isLaunchChildPidAlive(child) : undefined,
330
- port: options.port ?? options.devToolsActivePort?.port,
331
- timeoutMs,
332
- userDataDir,
333
- });
334
- const fail = async (reason, detail, diagnosticOptions) => {
335
- const diagnostics = buildFailureDiagnostics(diagnosticOptions);
336
- const processCleanupError = child ? await terminateLaunchChild(child) : undefined;
337
- const outputLines = [];
338
- if (outputCaptured) {
339
- for (const stream of ["stdout", "stderr"]) {
340
- let file;
341
- try {
342
- file = await open(join(userDataDir, `${stream}.log`), "r");
343
- const { size } = await file.stat();
344
- const buffer = Buffer.alloc(Math.min(size, ELECTRON_OUTPUT_TAIL_BYTES));
345
- const { bytesRead } = await file.read(buffer, 0, buffer.length, Math.max(0, size - buffer.length));
346
- diagnostics[`${stream}Tail`] = buffer.subarray(0, bytesRead).toString("utf8");
347
- diagnostics[`${stream}Truncated`] = size > buffer.length;
348
- }
349
- catch (error) {
350
- diagnostics[`${stream}Error`] = error instanceof Error ? error.message : String(error);
351
- }
352
- finally {
353
- await file?.close().catch((error) => {
354
- diagnostics[`${stream}Error`] = [diagnostics[`${stream}Error`], `Output reader close failed: ${error instanceof Error ? error.message : String(error)}`].filter(Boolean).join("; ");
355
- });
356
- }
357
- const tail = diagnostics[`${stream}Tail`];
358
- if (tail !== undefined)
359
- outputLines.push(`App ${stream}${diagnostics[`${stream}Truncated`] ? ` (last ${ELECTRON_OUTPUT_TAIL_BYTES} bytes)` : ""}: ${tail || "(empty)"}`);
360
- if (diagnostics[`${stream}Error`])
361
- outputLines.push(`App ${stream} capture error: ${diagnostics[`${stream}Error`]}`);
362
- }
363
- }
364
- try {
365
- if (processCleanupError)
366
- await preserveSecureTempDirectory(userDataDir);
367
- else
368
- await rm(userDataDir, { force: true, recursive: true });
369
- }
370
- catch (error) {
371
- const message = error instanceof Error ? error.message : String(error);
372
- cleanupError = [cleanupError, processCleanupError ? `Profile preservation failed: ${message}` : message].filter(Boolean).join("; ");
373
- }
374
- cleanupError = [processCleanupError, cleanupError].filter((value) => value !== undefined).join("; ") || undefined;
298
+ const target = await resolveLaunchTarget(options);
299
+ if (isElectronLaunchAborted(options.signal)) {
375
300
  return {
376
301
  ok: false,
377
302
  failure: {
378
303
  appArgs,
379
- cleanupError,
380
- diagnostics,
381
- error: [launchFailureMessage(reason, target, detail), ...outputLines].join("\n"),
382
- reason,
304
+ error: launchFailureMessage("aborted", target),
305
+ reason: "aborted",
383
306
  target,
384
- userDataDir,
385
307
  },
386
308
  };
387
- };
388
- if (!child)
389
- return fail(options.signal?.aborted ? "aborted" : "spawn-error", spawnError?.message);
390
- const portResult = await pollDevToolsActivePort({
391
- deadlineMs,
392
- getChildExit: () => ({ code: exitCode, signal: exitSignal }),
393
- getSpawnError: () => spawnError,
394
- signal: options.signal,
395
- userDataDir,
396
- });
397
- if (!portResult.port) {
398
- return fail(portResult.failure ?? "timeout", portResult.spawnError?.message, { devToolsActivePort: portResult.devToolsActivePort });
399
309
  }
400
- const metadataResult = await pollCdpMetadata(portResult.port, deadlineMs, options.signal);
401
- if (metadataResult.aborted)
402
- return fail("aborted", undefined, { devToolsActivePort: portResult.devToolsActivePort, port: portResult.port });
403
- if (!metadataResult.metadata) {
404
- return fail("port-not-found", undefined, { cdpVersionReached: false, devToolsActivePort: portResult.devToolsActivePort, port: portResult.port });
310
+ if (target === undefined) {
311
+ return {
312
+ ok: false,
313
+ failure: {
314
+ appArgs,
315
+ error: launchFailureMessage("non-electron-target", undefined),
316
+ reason: "non-electron-target",
317
+ },
318
+ };
405
319
  }
406
- const metadata = metadataResult.metadata;
407
- const record = buildLaunchRecord({
408
- createdAtMs: Date.now(),
409
- pid: child.pid,
410
- port: portResult.port,
411
- target,
412
- targetType: options.targetType,
413
- userDataDir,
414
- version: metadata.version,
415
- });
416
- const connectArg = selectElectronConnectArg({
417
- port: portResult.port,
418
- targets: metadata.targets,
419
- targetType: options.targetType,
420
- version: metadata.version,
421
- });
422
- return {
423
- ok: true,
424
- value: {
425
- appArgs,
426
- child,
427
- connectArg,
428
- record,
429
- target,
430
- targets: metadata.targets,
431
- version: metadata.version,
432
- },
433
- };
320
+ const policy = evaluateLaunchPolicy(options, target);
321
+ if (policy !== undefined) {
322
+ return {
323
+ ok: false,
324
+ failure: {
325
+ appArgs,
326
+ error: launchFailureMessage("policy-blocked", target, policy.message),
327
+ policy,
328
+ reason: "policy-blocked",
329
+ target,
330
+ },
331
+ };
332
+ }
333
+ const timeoutMs = normalizeTimeoutMs(options.timeoutMs);
334
+ const startedAtMs = Date.now();
335
+ const userDataDir = await createSecureTempDirectory(ELECTRON_PROFILE_DIR_PREFIX);
336
+ if (isElectronLaunchAborted(options.signal)) {
337
+ return abortedProfileResult(userDataDir, options, target);
338
+ }
339
+ return new ElectronLaunchAttempt(options, target, userDataDir, { timeoutMs, startedAtMs }).run();
434
340
  }