pi-agent-browser-native 0.9.3 → 0.9.4

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