harnery 0.40.0 → 0.42.0

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 (595) hide show
  1. package/README.md +1 -1
  2. package/dist/commander.js +4 -0
  3. package/dist/commands/agents.d.ts.map +1 -1
  4. package/dist/commands/agents.js +34 -20
  5. package/dist/commands/artifacts.d.ts.map +1 -1
  6. package/dist/commands/artifacts.js +113 -12
  7. package/dist/commands/browse-ai.d.ts.map +1 -1
  8. package/dist/commands/browse-ai.js +4 -0
  9. package/dist/commands/browse.d.ts +164 -0
  10. package/dist/commands/browse.d.ts.map +1 -1
  11. package/dist/commands/browse.js +388 -45
  12. package/dist/commands/checkpoint.js +8 -12
  13. package/dist/commands/claude-desktop.d.ts.map +1 -1
  14. package/dist/commands/claude-desktop.js +52 -0
  15. package/dist/commands/deinit.d.ts +1 -1
  16. package/dist/commands/deinit.d.ts.map +1 -1
  17. package/dist/commands/deinit.js +8 -4
  18. package/dist/commands/disk.d.ts +6 -0
  19. package/dist/commands/disk.d.ts.map +1 -0
  20. package/dist/commands/disk.js +80 -0
  21. package/dist/commands/docs.d.ts.map +1 -1
  22. package/dist/commands/docs.js +2 -0
  23. package/dist/commands/doctor.d.ts +8 -0
  24. package/dist/commands/doctor.d.ts.map +1 -1
  25. package/dist/commands/doctor.js +58 -3
  26. package/dist/commands/fetch.d.ts.map +1 -1
  27. package/dist/commands/fetch.js +10 -0
  28. package/dist/commands/files.d.ts +16 -0
  29. package/dist/commands/files.d.ts.map +1 -1
  30. package/dist/commands/files.js +54 -2
  31. package/dist/commands/init.d.ts +21 -5
  32. package/dist/commands/init.d.ts.map +1 -1
  33. package/dist/commands/init.js +271 -109
  34. package/dist/commands/instructions.js +5 -4
  35. package/dist/commands/ledger-v3.d.ts.map +1 -1
  36. package/dist/commands/ledger-v3.js +2 -1
  37. package/dist/commands/rm.d.ts +4 -0
  38. package/dist/commands/rm.d.ts.map +1 -0
  39. package/dist/commands/rm.js +87 -0
  40. package/dist/commands/servers.d.ts +7 -0
  41. package/dist/commands/servers.d.ts.map +1 -0
  42. package/dist/commands/servers.js +394 -0
  43. package/dist/commands/tunnel.d.ts.map +1 -1
  44. package/dist/commands/tunnel.js +82 -2
  45. package/dist/commands/webview.d.ts +4 -0
  46. package/dist/commands/webview.d.ts.map +1 -0
  47. package/dist/commands/webview.js +94 -0
  48. package/dist/core/adapter.d.ts +50 -1
  49. package/dist/core/adapter.d.ts.map +1 -1
  50. package/dist/core/adapter.js +59 -1
  51. package/dist/core/adapters/attestation.d.ts.map +1 -1
  52. package/dist/core/adapters/attestation.js +3 -2
  53. package/dist/core/adapters/profiles.d.ts +29 -3
  54. package/dist/core/adapters/profiles.d.ts.map +1 -1
  55. package/dist/core/adapters/profiles.js +53 -1
  56. package/dist/core/adapters/registry.d.ts.map +1 -1
  57. package/dist/core/adapters/registry.js +33 -0
  58. package/dist/core/adapters/types.d.ts +9 -0
  59. package/dist/core/adapters/types.d.ts.map +1 -1
  60. package/dist/core/agents/canonical-emit.d.ts +1 -1
  61. package/dist/core/agents/canonical-emit.d.ts.map +1 -1
  62. package/dist/core/agents/canonical-emit.js +2 -7
  63. package/dist/core/agents/cli.js +25 -16
  64. package/dist/core/agents/coord-client.d.ts.map +1 -1
  65. package/dist/core/agents/coord-client.js +7 -2
  66. package/dist/core/agents/render/session-context.d.ts.map +1 -1
  67. package/dist/core/agents/render/session-context.js +2 -0
  68. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
  69. package/dist/core/agents/rules/claim-conflict.js +3 -9
  70. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
  71. package/dist/core/agents/rules/commit-conflict.js +2 -8
  72. package/dist/core/agents/rules/stop-hook.d.ts +2 -0
  73. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
  74. package/dist/core/agents/rules/stop-hook.js +1 -1
  75. package/dist/core/agents/session-events.d.ts +6 -2
  76. package/dist/core/agents/session-events.d.ts.map +1 -1
  77. package/dist/core/agents/session-events.js +105 -26
  78. package/dist/core/agents/session-finalization-state-v3.d.ts.map +1 -1
  79. package/dist/core/agents/session-finalization-state-v3.js +2 -1
  80. package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
  81. package/dist/core/agents/session-finalizer-v3.js +5 -4
  82. package/dist/core/agents/session-name-display.d.ts +28 -0
  83. package/dist/core/agents/session-name-display.d.ts.map +1 -1
  84. package/dist/core/agents/session-name-display.js +43 -0
  85. package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
  86. package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
  87. package/dist/core/agents/state/heartbeat-writer.d.ts +10 -0
  88. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
  89. package/dist/core/agents/state/heartbeat-writer.js +21 -2
  90. package/dist/core/agents/state/live-coordination-view.d.ts +20 -0
  91. package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
  92. package/dist/core/agents/state/live-coordination-view.js +61 -0
  93. package/dist/core/agents/state/live-coordination-writer.js +3 -0
  94. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
  95. package/dist/core/agents/state/stale-sweep.js +2 -10
  96. package/dist/core/agents/turn-changes.d.ts +17 -0
  97. package/dist/core/agents/turn-changes.d.ts.map +1 -0
  98. package/dist/core/agents/turn-changes.js +76 -0
  99. package/dist/core/artifacts/delivery-card.d.ts.map +1 -1
  100. package/dist/core/artifacts/delivery-card.js +11 -3
  101. package/dist/core/artifacts/index.d.ts +140 -4
  102. package/dist/core/artifacts/index.d.ts.map +1 -1
  103. package/dist/core/artifacts/index.js +526 -52
  104. package/dist/core/config.d.ts +73 -11
  105. package/dist/core/config.d.ts.map +1 -1
  106. package/dist/core/config.js +142 -3
  107. package/dist/core/context/index.d.ts.map +1 -1
  108. package/dist/core/context/index.js +2 -1
  109. package/dist/core/conversations/archive.d.ts.map +1 -1
  110. package/dist/core/conversations/archive.js +4 -3
  111. package/dist/core/diagnostics/bundle.d.ts.map +1 -1
  112. package/dist/core/diagnostics/bundle.js +5 -4
  113. package/dist/core/events/legacy-storage/canary.d.ts.map +1 -1
  114. package/dist/core/events/legacy-storage/canary.js +5 -4
  115. package/dist/core/events/legacy-storage/compression.d.ts.map +1 -1
  116. package/dist/core/events/legacy-storage/compression.js +2 -1
  117. package/dist/core/events/v3/adapter-id.d.ts +10 -2
  118. package/dist/core/events/v3/adapter-id.d.ts.map +1 -1
  119. package/dist/core/events/v3/adapter-id.js +16 -0
  120. package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
  121. package/dist/core/events/v3/authority-outbox.js +2 -1
  122. package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
  123. package/dist/core/events/v3/bootstrap.js +5 -4
  124. package/dist/core/events/v3/capabilities.d.ts.map +1 -1
  125. package/dist/core/events/v3/capabilities.js +17 -0
  126. package/dist/core/events/v3/contract.d.ts +5 -0
  127. package/dist/core/events/v3/contract.d.ts.map +1 -1
  128. package/dist/core/events/v3/contract.js +7 -1
  129. package/dist/core/events/v3/control-witness.d.ts.map +1 -1
  130. package/dist/core/events/v3/control-witness.js +3 -2
  131. package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -1
  132. package/dist/core/events/v3/coordination-transaction-recovery.js +4 -3
  133. package/dist/core/events/v3/fingerprint-keys.d.ts.map +1 -1
  134. package/dist/core/events/v3/fingerprint-keys.js +7 -6
  135. package/dist/core/events/v3/generated.d.ts +1 -1
  136. package/dist/core/events/v3/generated.js +1 -1
  137. package/dist/core/events/v3/live-feed.d.ts.map +1 -1
  138. package/dist/core/events/v3/live-feed.js +5 -4
  139. package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
  140. package/dist/core/events/v3/producers/command-recorder.js +8 -7
  141. package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
  142. package/dist/core/events/v3/producers/coordination-recorder.js +8 -7
  143. package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -1
  144. package/dist/core/events/v3/producers/diagnostic-summaries.js +5 -4
  145. package/dist/core/events/v3/producers/hook-base.d.ts +1 -0
  146. package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
  147. package/dist/core/events/v3/producers/hook-base.js +10 -4
  148. package/dist/core/events/v3/producers/hook.d.ts +2 -0
  149. package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
  150. package/dist/core/events/v3/producers/hook.js +16 -1
  151. package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
  152. package/dist/core/events/v3/producers/intake.js +16 -6
  153. package/dist/core/events/v3/producers/recorder.d.ts +2 -4
  154. package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
  155. package/dist/core/events/v3/producers/recorder.js +125 -101
  156. package/dist/core/events/v3/projection.js +9 -1
  157. package/dist/core/events/v3/recovery.d.ts.map +1 -1
  158. package/dist/core/events/v3/recovery.js +4 -3
  159. package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -1
  160. package/dist/core/events/v3/support-storage/inventory.js +2 -1
  161. package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -1
  162. package/dist/core/events/v3/support-storage/maintenance.js +4 -3
  163. package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -1
  164. package/dist/core/events/v3/support-storage/pack-reader.js +4 -3
  165. package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -1
  166. package/dist/core/events/v3/support-storage/pack-writer.js +6 -5
  167. package/dist/core/events/v3/tool-line-changes.d.ts +8 -0
  168. package/dist/core/events/v3/tool-line-changes.d.ts.map +1 -0
  169. package/dist/core/events/v3/tool-line-changes.js +135 -0
  170. package/dist/core/events/v3/writer.d.ts.map +1 -1
  171. package/dist/core/events/v3/writer.js +8 -7
  172. package/dist/core/governor/planning.d.ts.map +1 -1
  173. package/dist/core/governor/planning.js +6 -5
  174. package/dist/core/governor/service.d.ts.map +1 -1
  175. package/dist/core/governor/service.js +12 -11
  176. package/dist/core/governor/state.d.ts.map +1 -1
  177. package/dist/core/governor/state.js +7 -6
  178. package/dist/core/guard/evaluator.js +1 -0
  179. package/dist/core/guard/storage.d.ts.map +1 -1
  180. package/dist/core/guard/storage.js +3 -2
  181. package/dist/core/hooks/adapter/behaviors/claude-code.d.ts +4 -0
  182. package/dist/core/hooks/adapter/behaviors/claude-code.d.ts.map +1 -0
  183. package/dist/core/hooks/adapter/behaviors/claude-code.js +31 -0
  184. package/dist/core/hooks/adapter/behaviors/codex.d.ts +15 -0
  185. package/dist/core/hooks/adapter/behaviors/codex.d.ts.map +1 -0
  186. package/dist/core/hooks/adapter/behaviors/codex.js +82 -0
  187. package/dist/core/hooks/adapter/behaviors/cursor.d.ts +7 -0
  188. package/dist/core/hooks/adapter/behaviors/cursor.d.ts.map +1 -0
  189. package/dist/core/hooks/adapter/behaviors/cursor.js +35 -0
  190. package/dist/core/hooks/adapter/behaviors/index.d.ts +11 -0
  191. package/dist/core/hooks/adapter/behaviors/index.d.ts.map +1 -0
  192. package/dist/core/hooks/adapter/behaviors/index.js +20 -0
  193. package/dist/core/hooks/adapter/behaviors/openclaw.d.ts +7 -0
  194. package/dist/core/hooks/adapter/behaviors/openclaw.d.ts.map +1 -0
  195. package/dist/core/hooks/adapter/behaviors/openclaw.js +34 -0
  196. package/dist/core/hooks/adapter/behaviors/opencode.d.ts +7 -0
  197. package/dist/core/hooks/adapter/behaviors/opencode.d.ts.map +1 -0
  198. package/dist/core/hooks/adapter/behaviors/opencode.js +34 -0
  199. package/dist/core/hooks/adapter/behaviors/types.d.ts +89 -0
  200. package/dist/core/hooks/adapter/behaviors/types.d.ts.map +1 -0
  201. package/dist/core/hooks/adapter/behaviors/types.js +1 -0
  202. package/dist/core/hooks/adapter/detect.d.ts +1 -1
  203. package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
  204. package/dist/core/hooks/adapter/detect.js +2 -3
  205. package/dist/core/hooks/adapter/events.d.ts +46 -1
  206. package/dist/core/hooks/adapter/events.d.ts.map +1 -1
  207. package/dist/core/hooks/adapter/events.js +36 -0
  208. package/dist/core/hooks/adapter/opencode-plugin.d.ts +60 -0
  209. package/dist/core/hooks/adapter/opencode-plugin.d.ts.map +1 -0
  210. package/dist/core/hooks/adapter/opencode-plugin.js +129 -0
  211. package/dist/core/hooks/adapter/output.d.ts +7 -0
  212. package/dist/core/hooks/adapter/output.d.ts.map +1 -1
  213. package/dist/core/hooks/adapter/output.js +8 -1
  214. package/dist/core/hooks/adapter/runtime-telemetry.js +3 -1
  215. package/dist/core/hooks/adapter/wiring.d.ts +52 -8
  216. package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
  217. package/dist/core/hooks/adapter/wiring.js +133 -12
  218. package/dist/core/hooks/cli.js +676 -531
  219. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
  220. package/dist/core/hooks/effects/image-capture.js +2 -1
  221. package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -1
  222. package/dist/core/hooks/prompt-context/contract.js +1 -0
  223. package/dist/core/hooks/resolve/transcript.d.ts +1 -1
  224. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
  225. package/dist/core/hooks/resolve/transcript.js +35 -4
  226. package/dist/core/hooks/run-markers.d.ts +37 -0
  227. package/dist/core/hooks/run-markers.d.ts.map +1 -0
  228. package/dist/core/hooks/run-markers.js +109 -0
  229. package/dist/core/hooks/session-name-presence.d.ts +3 -1
  230. package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
  231. package/dist/core/hooks/session-name-presence.js +7 -2
  232. package/dist/core/hooks/shell-waiter.d.ts +2 -0
  233. package/dist/core/hooks/shell-waiter.d.ts.map +1 -0
  234. package/dist/core/hooks/shell-waiter.js +173 -0
  235. package/dist/core/resources/service.d.ts.map +1 -1
  236. package/dist/core/resources/service.js +5 -4
  237. package/dist/core/semantic/review.d.ts.map +1 -1
  238. package/dist/core/semantic/review.js +5 -4
  239. package/dist/core/semantic/service.d.ts.map +1 -1
  240. package/dist/core/semantic/service.js +15 -14
  241. package/dist/core/semantic/storage.d.ts.map +1 -1
  242. package/dist/core/semantic/storage.js +5 -4
  243. package/dist/core/servers/index.d.ts +211 -0
  244. package/dist/core/servers/index.d.ts.map +1 -0
  245. package/dist/core/servers/index.js +560 -0
  246. package/dist/core/servers/net.d.ts +58 -0
  247. package/dist/core/servers/net.d.ts.map +1 -0
  248. package/dist/core/servers/net.js +270 -0
  249. package/dist/core/servers/tunnels.d.ts +14 -0
  250. package/dist/core/servers/tunnels.d.ts.map +1 -0
  251. package/dist/core/servers/tunnels.js +33 -0
  252. package/dist/core/storage/atomic-json.d.ts.map +1 -1
  253. package/dist/core/storage/atomic-json.js +7 -3
  254. package/dist/core/storage/builtins.js +1 -0
  255. package/dist/core/storage/durable-history.d.ts.map +1 -1
  256. package/dist/core/storage/durable-history.js +6 -5
  257. package/dist/core/storage/maintenance-providers.d.ts.map +1 -1
  258. package/dist/core/storage/maintenance-providers.js +2 -1
  259. package/dist/core/storage/maintenance.d.ts.map +1 -1
  260. package/dist/core/storage/maintenance.js +7 -6
  261. package/dist/core/storage/metrics.d.ts.map +1 -1
  262. package/dist/core/storage/metrics.js +5 -1
  263. package/dist/core/storage/modes.d.ts +17 -0
  264. package/dist/core/storage/modes.d.ts.map +1 -0
  265. package/dist/core/storage/modes.js +47 -0
  266. package/dist/core/storage/process-log.d.ts.map +1 -1
  267. package/dist/core/storage/process-log.js +3 -2
  268. package/dist/core/storage/receipts.d.ts.map +1 -1
  269. package/dist/core/storage/receipts.js +4 -3
  270. package/dist/core/storage/segments.d.ts.map +1 -1
  271. package/dist/core/storage/segments.js +7 -6
  272. package/dist/core/supervisor/hook-health.d.ts +2 -1
  273. package/dist/core/supervisor/hook-health.d.ts.map +1 -1
  274. package/dist/core/supervisor/hook-health.js +4 -3
  275. package/dist/core/supervisor/service.d.ts.map +1 -1
  276. package/dist/core/supervisor/service.js +7 -6
  277. package/dist/core/work/state.d.ts.map +1 -1
  278. package/dist/core/work/state.js +8 -7
  279. package/dist/core/workflow/adapters.d.ts +7 -0
  280. package/dist/core/workflow/adapters.d.ts.map +1 -1
  281. package/dist/core/workflow/adapters.js +9 -0
  282. package/dist/core/workflow/approvals.d.ts.map +1 -1
  283. package/dist/core/workflow/approvals.js +6 -5
  284. package/dist/core/workflow/billing.d.ts.map +1 -1
  285. package/dist/core/workflow/billing.js +33 -4
  286. package/dist/core/workflow/durable-record.d.ts.map +1 -1
  287. package/dist/core/workflow/durable-record.js +4 -3
  288. package/dist/core/workflow/engine.d.ts.map +1 -1
  289. package/dist/core/workflow/engine.js +30 -1
  290. package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
  291. package/dist/core/workflow/live-session-v3.js +2 -3
  292. package/dist/core/workflow/run-state.d.ts.map +1 -1
  293. package/dist/core/workflow/run-state.js +3 -2
  294. package/dist/core/workflow/sandbox-projection.d.ts +13 -2
  295. package/dist/core/workflow/sandbox-projection.d.ts.map +1 -1
  296. package/dist/core/workflow/sandbox-projection.js +23 -0
  297. package/dist/core/workflow/spawn-claude.d.ts.map +1 -1
  298. package/dist/core/workflow/spawn-claude.js +6 -1
  299. package/dist/core/workflow/spawn-codex.d.ts +2 -0
  300. package/dist/core/workflow/spawn-codex.d.ts.map +1 -1
  301. package/dist/core/workflow/spawn-codex.js +20 -1
  302. package/dist/core/workflow/spawn-cursor.d.ts.map +1 -1
  303. package/dist/core/workflow/spawn-cursor.js +6 -1
  304. package/dist/core/workflow/spawn-opencode.d.ts +36 -0
  305. package/dist/core/workflow/spawn-opencode.d.ts.map +1 -0
  306. package/dist/core/workflow/spawn-opencode.js +135 -0
  307. package/dist/core/workflow/transcript.d.ts.map +1 -1
  308. package/dist/core/workflow/transcript.js +3 -2
  309. package/dist/core/workflow/types.d.ts +47 -2
  310. package/dist/core/workflow/types.d.ts.map +1 -1
  311. package/dist/core/workflow/worker-access.d.ts +92 -0
  312. package/dist/core/workflow/worker-access.d.ts.map +1 -0
  313. package/dist/core/workflow/worker-access.js +450 -0
  314. package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
  315. package/dist/core/workflow/workspaces/leases.js +5 -4
  316. package/dist/core/workflow/workspaces/local-git.d.ts.map +1 -1
  317. package/dist/core/workflow/workspaces/local-git.js +3 -2
  318. package/dist/core/workflow/workspaces/paths.d.ts.map +1 -1
  319. package/dist/core/workflow/workspaces/paths.js +2 -1
  320. package/dist/core/workflow/workspaces/state.d.ts.map +1 -1
  321. package/dist/core/workflow/workspaces/state.js +10 -9
  322. package/dist/lazy-commands.js +8 -1
  323. package/dist/lib/agent-browser/client.d.ts +9 -0
  324. package/dist/lib/agent-browser/client.d.ts.map +1 -1
  325. package/dist/lib/agent-browser/client.js +13 -0
  326. package/dist/lib/browser/batch-steps.d.ts +18 -0
  327. package/dist/lib/browser/batch-steps.d.ts.map +1 -0
  328. package/dist/lib/browser/batch-steps.js +82 -0
  329. package/dist/lib/browser/client.d.ts +35 -1
  330. package/dist/lib/browser/client.d.ts.map +1 -1
  331. package/dist/lib/browser/client.js +117 -8
  332. package/dist/lib/browser/collect/collector.d.ts +99 -0
  333. package/dist/lib/browser/collect/collector.d.ts.map +1 -0
  334. package/dist/lib/browser/collect/collector.js +202 -0
  335. package/dist/lib/browser/collect/fields.d.ts +31 -0
  336. package/dist/lib/browser/collect/fields.d.ts.map +1 -0
  337. package/dist/lib/browser/collect/fields.js +75 -0
  338. package/dist/lib/browser/collect/index.d.ts +6 -0
  339. package/dist/lib/browser/collect/index.d.ts.map +1 -0
  340. package/dist/lib/browser/collect/index.js +5 -0
  341. package/dist/lib/browser/collect/page-driver.d.ts +14 -0
  342. package/dist/lib/browser/collect/page-driver.d.ts.map +1 -0
  343. package/dist/lib/browser/collect/page-driver.js +306 -0
  344. package/dist/lib/browser/collect/presets.d.ts +52 -0
  345. package/dist/lib/browser/collect/presets.d.ts.map +1 -0
  346. package/dist/lib/browser/collect/presets.js +176 -0
  347. package/dist/lib/browser/collect/scroll-plan.d.ts +85 -0
  348. package/dist/lib/browser/collect/scroll-plan.d.ts.map +1 -0
  349. package/dist/lib/browser/collect/scroll-plan.js +118 -0
  350. package/dist/lib/browser/identity.d.ts +25 -0
  351. package/dist/lib/browser/identity.d.ts.map +1 -0
  352. package/dist/lib/browser/identity.js +66 -0
  353. package/dist/lib/browser/index.d.ts +3 -2
  354. package/dist/lib/browser/index.d.ts.map +1 -1
  355. package/dist/lib/browser/index.js +2 -1
  356. package/dist/lib/browser/launch-args.d.ts +26 -0
  357. package/dist/lib/browser/launch-args.d.ts.map +1 -1
  358. package/dist/lib/browser/launch-args.js +41 -1
  359. package/dist/lib/browser/page-review-judge.d.ts +2 -0
  360. package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
  361. package/dist/lib/browser/page-review-judge.js +13 -0
  362. package/dist/lib/browser/qa-run-contracts.d.ts +10 -0
  363. package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
  364. package/dist/lib/browser/qa-run.d.ts.map +1 -1
  365. package/dist/lib/browser/qa-run.js +1 -0
  366. package/dist/lib/browser/user-agent.d.ts +53 -0
  367. package/dist/lib/browser/user-agent.d.ts.map +1 -0
  368. package/dist/lib/browser/user-agent.js +79 -0
  369. package/dist/lib/browser/windows-chrome.d.ts +59 -0
  370. package/dist/lib/browser/windows-chrome.d.ts.map +1 -0
  371. package/dist/lib/browser/windows-chrome.js +179 -0
  372. package/dist/lib/claude-desktop-share.d.ts +136 -0
  373. package/dist/lib/claude-desktop-share.d.ts.map +1 -0
  374. package/dist/lib/claude-desktop-share.js +394 -0
  375. package/dist/lib/disk-usage.d.ts +50 -0
  376. package/dist/lib/disk-usage.d.ts.map +1 -0
  377. package/dist/lib/disk-usage.js +303 -0
  378. package/dist/lib/docs-lint.d.ts +6 -0
  379. package/dist/lib/docs-lint.d.ts.map +1 -1
  380. package/dist/lib/docs-lint.js +8 -3
  381. package/dist/lib/docs-metadata-managed.d.ts +1 -0
  382. package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
  383. package/dist/lib/docs-metadata-managed.js +17 -1
  384. package/dist/lib/guarded-remove.d.ts +34 -0
  385. package/dist/lib/guarded-remove.d.ts.map +1 -0
  386. package/dist/lib/guarded-remove.js +310 -0
  387. package/dist/lib/identities/assume.d.ts.map +1 -1
  388. package/dist/lib/identities/assume.js +4 -9
  389. package/dist/lib/instructions/apply.d.ts.map +1 -1
  390. package/dist/lib/instructions/apply.js +2 -0
  391. package/dist/lib/instructions/templates.js +8 -8
  392. package/dist/lib/pace/index.d.ts +2 -0
  393. package/dist/lib/pace/index.d.ts.map +1 -0
  394. package/dist/lib/pace/index.js +1 -0
  395. package/dist/lib/pace/pace.d.ts +95 -0
  396. package/dist/lib/pace/pace.d.ts.map +1 -0
  397. package/dist/lib/pace/pace.js +313 -0
  398. package/dist/lib/tunnel/error-page.d.ts +1 -1
  399. package/dist/lib/tunnel/error-page.d.ts.map +1 -1
  400. package/dist/lib/tunnel/error-page.js +19 -8
  401. package/dist/lib/tunnel/forward-headers.d.ts +11 -0
  402. package/dist/lib/tunnel/forward-headers.d.ts.map +1 -0
  403. package/dist/lib/tunnel/forward-headers.js +17 -0
  404. package/dist/lib/tunnel/gate.js +34 -10
  405. package/dist/lib/tunnel/path-scope.d.ts +22 -0
  406. package/dist/lib/tunnel/path-scope.d.ts.map +1 -0
  407. package/dist/lib/tunnel/path-scope.js +62 -0
  408. package/dist/lib/tunnel/state.d.ts +5 -0
  409. package/dist/lib/tunnel/state.d.ts.map +1 -1
  410. package/dist/lib/tunnel/state.js +17 -3
  411. package/dist/lib/webview/index.d.ts +2 -0
  412. package/dist/lib/webview/index.d.ts.map +1 -0
  413. package/dist/lib/webview/index.js +1 -0
  414. package/dist/lib/webview/webview.d.ts +116 -0
  415. package/dist/lib/webview/webview.d.ts.map +1 -0
  416. package/dist/lib/webview/webview.js +289 -0
  417. package/opencode-plugin/package.json +19 -0
  418. package/opencode-plugin/src/index.ts +791 -0
  419. package/package.json +16 -4
  420. package/schemas/config.schema.json +104 -0
  421. package/schemas/event-v3.schema.json +164 -0
  422. package/src/commander.ts +26 -0
  423. package/src/commands/agents.ts +47 -18
  424. package/src/commands/artifacts.ts +171 -19
  425. package/src/commands/browse-ai.ts +8 -0
  426. package/src/commands/browse.ts +570 -48
  427. package/src/commands/checkpoint.ts +7 -9
  428. package/src/commands/claude-desktop.ts +61 -0
  429. package/src/commands/deinit.ts +9 -4
  430. package/src/commands/disk.ts +114 -0
  431. package/src/commands/docs.ts +2 -0
  432. package/src/commands/doctor.ts +63 -3
  433. package/src/commands/fetch.ts +14 -0
  434. package/src/commands/files.ts +93 -2
  435. package/src/commands/init.ts +334 -122
  436. package/src/commands/instructions.ts +8 -4
  437. package/src/commands/ledger-v3.ts +2 -1
  438. package/src/commands/rm.ts +115 -0
  439. package/src/commands/servers.ts +506 -0
  440. package/src/commands/tunnel.ts +102 -2
  441. package/src/commands/webview.ts +159 -0
  442. package/src/core/adapter.ts +102 -1
  443. package/src/core/adapters/attestation.ts +3 -2
  444. package/src/core/adapters/profiles.ts +63 -1
  445. package/src/core/adapters/registry.ts +37 -0
  446. package/src/core/adapters/types.ts +10 -0
  447. package/src/core/agents/canonical-emit.ts +2 -5
  448. package/src/core/agents/cli.ts +26 -17
  449. package/src/core/agents/coord-client.ts +9 -3
  450. package/src/core/agents/render/session-context.ts +1 -0
  451. package/src/core/agents/rules/claim-conflict.ts +3 -8
  452. package/src/core/agents/rules/commit-conflict.ts +2 -7
  453. package/src/core/agents/rules/stop-hook.ts +3 -1
  454. package/src/core/agents/session-events.ts +120 -26
  455. package/src/core/agents/session-finalization-state-v3.ts +2 -1
  456. package/src/core/agents/session-finalizer-v3.ts +5 -4
  457. package/src/core/agents/session-name-display.ts +48 -0
  458. package/src/core/agents/state/heartbeat-reader.ts +7 -0
  459. package/src/core/agents/state/heartbeat-writer.ts +24 -2
  460. package/src/core/agents/state/live-coordination-view.ts +74 -0
  461. package/src/core/agents/state/live-coordination-writer.ts +3 -0
  462. package/src/core/agents/state/stale-sweep.ts +2 -9
  463. package/src/core/agents/turn-changes.ts +97 -0
  464. package/src/core/artifacts/delivery-card.ts +12 -3
  465. package/src/core/artifacts/index.ts +701 -47
  466. package/src/core/config.ts +206 -4
  467. package/src/core/context/index.ts +2 -1
  468. package/src/core/conversations/archive.ts +4 -3
  469. package/src/core/diagnostics/bundle.ts +5 -3
  470. package/src/core/events/legacy-storage/canary.ts +5 -4
  471. package/src/core/events/legacy-storage/compression.ts +2 -1
  472. package/src/core/events/v3/adapter-id.ts +29 -1
  473. package/src/core/events/v3/authority-outbox.ts +2 -1
  474. package/src/core/events/v3/bootstrap.ts +5 -4
  475. package/src/core/events/v3/capabilities.ts +17 -0
  476. package/src/core/events/v3/contract.ts +9 -1
  477. package/src/core/events/v3/control-witness.ts +3 -2
  478. package/src/core/events/v3/coordination-transaction-recovery.ts +4 -3
  479. package/src/core/events/v3/fingerprint-keys.ts +7 -6
  480. package/src/core/events/v3/generated.ts +1 -1
  481. package/src/core/events/v3/live-feed.ts +5 -4
  482. package/src/core/events/v3/producers/command-recorder.ts +8 -6
  483. package/src/core/events/v3/producers/coordination-recorder.ts +8 -7
  484. package/src/core/events/v3/producers/diagnostic-summaries.ts +5 -4
  485. package/src/core/events/v3/producers/hook-base.ts +11 -4
  486. package/src/core/events/v3/producers/hook.ts +19 -1
  487. package/src/core/events/v3/producers/intake.ts +18 -6
  488. package/src/core/events/v3/producers/recorder.ts +139 -114
  489. package/src/core/events/v3/projection.ts +11 -1
  490. package/src/core/events/v3/recovery.ts +4 -3
  491. package/src/core/events/v3/support-storage/inventory.ts +2 -1
  492. package/src/core/events/v3/support-storage/maintenance.ts +8 -3
  493. package/src/core/events/v3/support-storage/pack-reader.ts +4 -3
  494. package/src/core/events/v3/support-storage/pack-writer.ts +6 -5
  495. package/src/core/events/v3/tool-line-changes.ts +139 -0
  496. package/src/core/events/v3/writer.ts +8 -7
  497. package/src/core/governor/planning.ts +6 -5
  498. package/src/core/governor/service.ts +12 -11
  499. package/src/core/governor/state.ts +7 -6
  500. package/src/core/guard/evaluator.ts +1 -0
  501. package/src/core/guard/storage.ts +3 -2
  502. package/src/core/hooks/adapter/behaviors/claude-code.ts +33 -0
  503. package/src/core/hooks/adapter/behaviors/codex.ts +96 -0
  504. package/src/core/hooks/adapter/behaviors/cursor.ts +37 -0
  505. package/src/core/hooks/adapter/behaviors/index.ts +31 -0
  506. package/src/core/hooks/adapter/behaviors/openclaw.ts +36 -0
  507. package/src/core/hooks/adapter/behaviors/opencode.ts +36 -0
  508. package/src/core/hooks/adapter/behaviors/types.ts +110 -0
  509. package/src/core/hooks/adapter/detect.ts +2 -3
  510. package/src/core/hooks/adapter/events.ts +72 -1
  511. package/src/core/hooks/adapter/opencode-plugin.ts +177 -0
  512. package/src/core/hooks/adapter/output.ts +8 -1
  513. package/src/core/hooks/adapter/runtime-telemetry.ts +3 -1
  514. package/src/core/hooks/adapter/wiring.ts +198 -16
  515. package/src/core/hooks/cli.ts +776 -539
  516. package/src/core/hooks/effects/image-capture.ts +2 -1
  517. package/src/core/hooks/prompt-context/contract.ts +1 -0
  518. package/src/core/hooks/resolve/transcript.ts +42 -5
  519. package/src/core/hooks/run-markers.ts +132 -0
  520. package/src/core/hooks/session-name-presence.ts +10 -3
  521. package/src/core/hooks/shell-waiter.ts +166 -0
  522. package/src/core/resources/service.ts +5 -4
  523. package/src/core/semantic/review.ts +5 -4
  524. package/src/core/semantic/service.ts +15 -14
  525. package/src/core/semantic/storage.ts +5 -4
  526. package/src/core/servers/index.ts +712 -0
  527. package/src/core/servers/net.ts +283 -0
  528. package/src/core/servers/tunnels.ts +39 -0
  529. package/src/core/storage/atomic-json.ts +7 -3
  530. package/src/core/storage/builtins.ts +1 -0
  531. package/src/core/storage/durable-history.ts +6 -5
  532. package/src/core/storage/maintenance-providers.ts +2 -1
  533. package/src/core/storage/maintenance.ts +7 -6
  534. package/src/core/storage/metrics.ts +5 -1
  535. package/src/core/storage/modes.ts +53 -0
  536. package/src/core/storage/process-log.ts +3 -2
  537. package/src/core/storage/receipts.ts +4 -3
  538. package/src/core/storage/segments.ts +7 -6
  539. package/src/core/supervisor/hook-health.ts +4 -4
  540. package/src/core/supervisor/service.ts +7 -6
  541. package/src/core/work/state.ts +8 -7
  542. package/src/core/workflow/adapters.ts +15 -0
  543. package/src/core/workflow/approvals.ts +6 -5
  544. package/src/core/workflow/billing.ts +34 -4
  545. package/src/core/workflow/durable-record.ts +4 -3
  546. package/src/core/workflow/engine.ts +38 -1
  547. package/src/core/workflow/live-session-v3.ts +2 -3
  548. package/src/core/workflow/run-state.ts +3 -2
  549. package/src/core/workflow/sandbox-projection.ts +38 -2
  550. package/src/core/workflow/spawn-claude.ts +5 -1
  551. package/src/core/workflow/spawn-codex.ts +18 -1
  552. package/src/core/workflow/spawn-cursor.ts +5 -1
  553. package/src/core/workflow/spawn-opencode.ts +153 -0
  554. package/src/core/workflow/transcript.ts +3 -2
  555. package/src/core/workflow/types.ts +62 -2
  556. package/src/core/workflow/worker-access.ts +525 -0
  557. package/src/core/workflow/workspaces/leases.ts +5 -4
  558. package/src/core/workflow/workspaces/local-git.ts +3 -2
  559. package/src/core/workflow/workspaces/paths.ts +2 -1
  560. package/src/core/workflow/workspaces/state.ts +10 -9
  561. package/src/lazy-commands.ts +11 -1
  562. package/src/lib/agent-browser/client.ts +18 -0
  563. package/src/lib/browser/batch-steps.ts +79 -0
  564. package/src/lib/browser/client.ts +147 -9
  565. package/src/lib/browser/collect/collector.ts +306 -0
  566. package/src/lib/browser/collect/fields.ts +87 -0
  567. package/src/lib/browser/collect/index.ts +47 -0
  568. package/src/lib/browser/collect/page-driver.ts +327 -0
  569. package/src/lib/browser/collect/presets.ts +237 -0
  570. package/src/lib/browser/collect/scroll-plan.ts +179 -0
  571. package/src/lib/browser/identity.ts +64 -0
  572. package/src/lib/browser/index.ts +16 -1
  573. package/src/lib/browser/launch-args.ts +53 -1
  574. package/src/lib/browser/page-review-judge.ts +16 -0
  575. package/src/lib/browser/qa-run-contracts.ts +11 -0
  576. package/src/lib/browser/qa-run.ts +1 -0
  577. package/src/lib/browser/user-agent.ts +130 -0
  578. package/src/lib/browser/windows-chrome.ts +227 -0
  579. package/src/lib/claude-desktop-share.ts +511 -0
  580. package/src/lib/disk-usage.ts +347 -0
  581. package/src/lib/docs-lint.ts +8 -3
  582. package/src/lib/docs-metadata-managed.ts +21 -0
  583. package/src/lib/guarded-remove.ts +376 -0
  584. package/src/lib/identities/assume.ts +7 -7
  585. package/src/lib/instructions/apply.ts +2 -0
  586. package/src/lib/instructions/templates.ts +8 -8
  587. package/src/lib/pace/index.ts +14 -0
  588. package/src/lib/pace/pace.ts +370 -0
  589. package/src/lib/tunnel/error-page.ts +25 -9
  590. package/src/lib/tunnel/forward-headers.ts +16 -0
  591. package/src/lib/tunnel/gate.ts +39 -10
  592. package/src/lib/tunnel/path-scope.ts +73 -0
  593. package/src/lib/tunnel/state.ts +20 -3
  594. package/src/lib/webview/index.ts +13 -0
  595. package/src/lib/webview/webview.ts +457 -0
@@ -1,10 +1,15 @@
1
+ import { spawn } from "node:child_process";
1
2
  import { existsSync, mkdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
2
3
  import { homedir } from "node:os";
3
4
  import { dirname, isAbsolute, resolve } from "node:path";
5
+ import { chromium } from "playwright";
4
6
  import { PNG } from "pngjs";
5
7
  import { resolveBinName } from "../core/config.js";
8
+ import { splitBatchSteps } from "../lib/browser/batch-steps.js";
6
9
  import { CAPTURE_FIDELITY_MISMATCH_THRESHOLD, compareBand, cropNativePng, decideFidelity, pngDimensions, } from "../lib/browser/capture-fidelity.js";
7
- import { Browser, browserProxyFromEnv, browserProxyGateFromEnv, captureDevOverlay, DEFAULT_CRITIQUE_RUBRIC, extractObservedIp, parseAssertSpec, runCritique, tilesFromFullPage, WEBRTC_PROXY_ONLY_ARG, writeNetscapeCookieFile, wslHeadedLaunchArgs, } from "../lib/browser/index.js";
10
+ import { createPageDriver, createRng, DEFAULT_COLLECT_LIMITS, PACING_LIMITS, parseProbability, parseRange, presetNames, randomSeed, resolveCollectSpec, runCollect, scrollPacingFromEnv, } from "../lib/browser/collect/index.js";
11
+ import { Browser, browserProxyFromEnv, browserProxyGateFromEnv, captureDevOverlay, chromeMajorFromExecutable, DEFAULT_CRITIQUE_RUBRIC, extractObservedIp, installedChromeChannel, installedChromePath, parseAssertSpec, resolveUserAgent, runCritique, tilesFromFullPage, WEBRTC_PROXY_ONLY_ARG, writeNetscapeCookieFile, wslHeadedLaunchArgs, } from "../lib/browser/index.js";
12
+ import { isWSL } from "../lib/browser/launch-args.js";
8
13
  import { allocateTileBudget, validatePageReviewAllocation, } from "../lib/browser/page-review-budget.js";
9
14
  import { PAGE_REVIEW_CAPTURE_PLAN_SCHEMA, } from "../lib/browser/page-review-contracts.js";
10
15
  import { findPackTile, gateHitsFromEnvelope, readPackContext, tileId, writePackContext, writePackExpandedTile, } from "../lib/browser/page-review-pack.js";
@@ -17,7 +22,9 @@ import { startBrowserSessionServer, } from "../lib/browser/session-control.js";
17
22
  import { captureThumbnailFingerprint, registerCaptureThumbnail, } from "../lib/browser/thumbnail-association.js";
18
23
  import { reviewCandidateRects } from "../lib/browser/tiling.js";
19
24
  import { diffAgainstBaseline, saveBaseline, } from "../lib/browser/visual-diff.js";
20
- import { applyExtraCookies, CookieJar } from "../lib/cookies/index.js";
25
+ import { harvestDomain, harvestWindowsChromeCookies, stopWindowsChromeProfile, windowsChromePath, windowsLocalAppData, windowsPlainProfile, wslPathToWindows, } from "../lib/browser/windows-chrome.js";
26
+ import { applyExtraCookies, CookieJar, mergeCookies } from "../lib/cookies/index.js";
27
+ import { commandPaceGate } from "../lib/pace/index.js";
21
28
  /**
22
29
  * `harn browse <url>`: Playwright-backed page navigation with shared
23
30
  * cookie jar + persistent profile + diagnostics capture for LLM
@@ -70,26 +77,66 @@ export function registerBrowseCommand(program, emitParam, context, binName = res
70
77
  .option("--capture-evaluate <js>", "In trio mode, evaluate JS inside the exact screenshot viewport immediately before capture; result is written as captureEval")
71
78
  .option("--batch <steps>", "Run multiple steps in one session, semicolon-separated. Each step is one of: " +
72
79
  "`click <selector>`, `fill <selector=>value>`, `press <key>`, `wait <selector|ms>`, `eval <js>`, `reload`. " +
73
- 'Example: `--batch "click button; wait 1500; reload; wait 3000"`. `reload` preserves sessionStorage + cookies, which is how to repro sessionStorage-restored UI state.')
80
+ 'Example: `--batch "click button; wait 1500; reload; wait 3000"`. `reload` preserves sessionStorage + cookies, which is how to repro sessionStorage-restored UI state. ' +
81
+ "An `eval` step keeps semicolons inside JS quotes and (), [], {}; `\\;` is always a literal semicolon.")
82
+ .option("--collect [preset]", "Scroll an infinite feed like a reader and collect every item that passes through the DOM, " +
83
+ `de-duplicated, as JSON. Presets: ${presetNames().join(", ")} (default generic). ` +
84
+ "Skips the trio, checks and --evaluate; runs after --wait-for and --batch.")
85
+ .option("--collect-item <css>", "Item selector (overrides the preset's).")
86
+ .option("--collect-key <extractor>", "Dedupe key extractor, <selector>[@attr] inside the item. Default: the preset key, else the " +
87
+ "first permalink-like link, else a hash of the item text.")
88
+ .option("--collect-key-pattern <regex>", "Regex a link must match to count as a permalink key.")
89
+ .option("--collect-field <name=extractor>", "Add or override a field: name=<selector>[@attr]. name[]= collects every match. Empty selector " +
90
+ "or :scope is the item itself; no @attr reads visible text (repeatable).", (value, previous = []) => [...previous, value], [])
91
+ .option("--collect-expand [selector]", "Click 'show more' buttons inside visible items before harvesting (preset selector by default). " +
92
+ "At most 3 per step and 50 per run; links and action buttons are never clicked.")
93
+ .option("--collect-max-items <n>", "Stop after this many unique items.")
94
+ .option("--collect-max-scrolls <n>", "Stop after this many scroll steps (default 60).", "60")
95
+ .option("--collect-max-seconds <n>", "Stop after this much wall time (default 300).", "300")
96
+ .option("--collect-idle <n>", "Stop after this many steps with no new items and no page growth (default 5).", "5")
97
+ .option("--collect-step <min-max>", "Scroll distance per step as a viewport fraction (default 0.6-1.1; env HARNERY_COLLECT_STEP).")
98
+ .option("--collect-pause <min-max>", "Pause after each step in ms (default 1200-3500; env HARNERY_COLLECT_PAUSE_MS).")
99
+ .option("--collect-read-chance <p>", "Chance of a longer reading pause per step (default 0.12).")
100
+ .option("--collect-read-pause <min-max>", "Reading pause in ms (default 4000-9000).")
101
+ .option("--collect-back-chance <p>", "Chance a step starts with a small scroll back up (default 0.08).")
102
+ .option("--collect-seed <n>", "Seed for the scroll schedule; the envelope reports the seed used.")
103
+ .option("--collect-format <format>", "json (envelope, default) or jsonl (one item per line).", "json")
104
+ .option("--collect-out <path>", "Write the collection to this file instead of stdout.")
74
105
  .option("--network-har <path>", "Record network traffic to a HAR file (finalized on close)")
75
- .option("--viewport <preset|WxH>", "Viewport: mobile (390x844), tablet (820x1180), desktop (1280x800), hd (1920x1080), or explicit '1920x1080'", "desktop")
106
+ .option("--viewport <preset|WxH>", "Viewport: mobile (390x844), tablet (820x1180), desktop (1280x800), hd (1920x1080), or explicit '1920x1080'. Default: real window in headed mode, desktop in headless mode")
76
107
  .option("--color-scheme <scheme>", "Emulate prefers-color-scheme for the whole session: light | dark. " +
77
108
  "Renders theme-aware pages in that scheme without page-specific toggles. " +
78
109
  "Absent = browser default (unchanged behavior).")
79
- .option("--login", "Headed mode for one-time auth flow (cookies persist in profile)")
110
+ .option("--login", "Open the URL in the installed Google Chrome with nothing attached (no DevTools protocol, no " +
111
+ "Playwright) so a person can sign in; under WSL this is the Windows host's Chrome. Sign in, then " +
112
+ "close the window or create the --login-close-file; later browse and browse-session runs reuse " +
113
+ "the cookies. Sites cannot tell this window from the person's own browser.")
114
+ .option("--attached", "With --login: open an automation-controlled Chrome that this process and --control-file can drive. " +
115
+ "Sites can detect it and may lock the account, so use it only for agent-driven headed sessions on " +
116
+ "sites you own. Never use it to sign in to a third-party account.")
80
117
  .option("--login-close-file <path>", "With --login, wait for this file instead of terminal Enter, then remove it and close cleanly")
81
- .option("--control-file <path>", "With --login, publish an owner-only descriptor for repeated browse-session control")
82
- .option("--headed", "Headed mode for one-off (no auth-flow framing)")
118
+ .option("--control-file <path>", "With --login --attached, publish an owner-only descriptor for repeated browse-session control")
119
+ .option("--headed", "Automation-controlled headed window for one-off visual checks. Not for signing in; use --login.")
120
+ .option("--browser-channel <name>", "Browser to launch: chrome | chrome-beta | msedge | chromium. Headed launches (--login, --headed) " +
121
+ "default to the installed Google Chrome with the automation signals removed, because the bundled " +
122
+ '"Chrome for Testing" build advertises itself and sign-in flows refuse clicks; chromium forces the ' +
123
+ "bundled build. HARNERY_BROWSER_CHANNEL sets the default machine-wide.")
124
+ .option("--user-agent <ua|auto|native>", "User agent to present. Default: a normal Windows (or macOS on a Mac) Chrome user agent at the launched " +
125
+ "Chrome's major version, stored at ~/.cache/harnery/user-agent.json and reused by every surface; never " +
126
+ "Linux, never HeadlessChrome. A string rewrites the store, auto refreshes it, native uses the browser's own. " +
127
+ "HARNERY_BROWSER_UA overrides for one environment.")
83
128
  .option("--browser-arg <flag>", "Extra Chromium launch flag, passed straight to the browser (repeatable). " +
84
129
  "e.g. --browser-arg --disable-gpu. Also settable machine-wide via the " +
85
- "HARNERY_BROWSER_ARGS env var (whitespace-separated). Under WSL, headed " +
86
- "launches auto-add --disable-gpu to fix blank-window paint; opt out with " +
87
- "HARNERY_BROWSER_NO_WSL_DEFAULTS=1.", (value, prev = []) => [...prev, value], [])
130
+ "HARNERY_BROWSER_ARGS env var (whitespace-separated). Under WSL, set " +
131
+ "HARNERY_BROWSER_WSL_DISABLE_GPU=1 to add --disable-gpu when a headed window paints blank; " +
132
+ "it is off by default because software WebGL is a bot tell.", (value, prev = []) => [...prev, value], [])
88
133
  .option("--proxy-from-env", "Pass HTTP(S)_PROXY to Playwright as an authenticated browser proxy. " +
89
134
  "Credentials stay in the child environment, never command arguments. " +
90
135
  "When the host also injects the HARNERY_BROWSER_PROXY_* gate variables, " +
91
136
  "the expected IP is verified before the requested URL opens.")
92
137
  .option("--no-cookies", "Skip cookie-jar attach and persist")
138
+ .option("--no-pace", "Skip the human-pace gap (3 to 9 s) between page loads of the same site for this run. " +
139
+ "HARNERY_PACE=off disables it machine-wide; local and private hosts never wait.")
93
140
  .option("--store <path>", `Cookie store path (default ${DEFAULT_STORE})`)
94
141
  .option("--profile <dir>", `Persistent Chromium profile dir (default ${DEFAULT_PROFILE})`)
95
142
  .option("--export-cookies <path>", "Write live profile cookies as an owner-only Netscape cookies.txt file on close")
@@ -296,7 +343,8 @@ async function runBrowse(url, opts, context) {
296
343
  : new CookieJar({ path: opts.store ?? DEFAULT_STORE, source: "harn-browse" });
297
344
  if (jar)
298
345
  applyExtraCookies(url, jar, context?.extraCookies);
299
- const headed = opts.login || opts.headed;
346
+ const loginMode = resolveLoginMode(opts);
347
+ const headed = loginMode === "attached" || opts.headed;
300
348
  const viewport = parseViewport(opts.viewport ?? "desktop");
301
349
  const deviceScaleFactor = parseDeviceScaleFactor(opts.deviceScaleFactor);
302
350
  if (opts.reviewPackAllocation && !opts.reviewPack) {
@@ -322,30 +370,58 @@ async function runBrowse(url, opts, context) {
322
370
  }
323
371
  const proxy = opts.proxyFromEnv ? browserProxyFromEnv() : undefined;
324
372
  const proxyGate = opts.proxyFromEnv ? browserProxyGateFromEnv() : null;
325
- if (opts.loginCloseFile && !opts.login) {
326
- throw new Error("--login-close-file requires --login.");
327
- }
328
- if (opts.controlFile && !opts.login) {
329
- throw new Error("--control-file requires --login.");
330
- }
331
373
  const loginCloseFile = opts.loginCloseFile ? resolve(opts.loginCloseFile) : null;
332
374
  if (loginCloseFile && existsSync(loginCloseFile)) {
333
375
  throw new Error(`Login close signal already exists at ${loginCloseFile}. Remove the stale file before launching.`);
334
376
  }
377
+ const collectPlan = opts.collect ? buildCollectPlan(opts) : null;
378
+ const pace = commandPaceGate(opts.pace !== false, (message) => emit.log(message, "info"));
379
+ if (loginMode === "plain") {
380
+ const plainExecutable = installedChromePath();
381
+ const plainUa = resolveUserAgent({
382
+ requested: opts.userAgent,
383
+ env: process.env.HARNERY_BROWSER_UA,
384
+ chromeMajor: plainExecutable ? chromeMajorFromExecutable(plainExecutable) : undefined,
385
+ });
386
+ await pace?.before(url);
387
+ if (useWindowsPlainLogin()) {
388
+ await runWindowsPlainLogin(url, opts.store ?? DEFAULT_STORE, loginCloseFile, emit);
389
+ return;
390
+ }
391
+ await runPlainLogin(url, opts.profile ?? DEFAULT_PROFILE, loginCloseFile, plainUa, emit);
392
+ return;
393
+ }
394
+ const channel = resolveBrowserChannel(opts, Boolean(headed));
395
+ const userAgent = resolveUserAgent({
396
+ requested: opts.userAgent,
397
+ env: process.env.HARNERY_BROWSER_UA,
398
+ chromeMajor: launchedChromeMajor(channel),
399
+ });
335
400
  const browser = new Browser({
336
401
  profileDir: opts.profile ?? DEFAULT_PROFILE,
337
402
  headed,
338
403
  jar,
339
- viewport,
404
+ viewport: headed && !opts.viewport ? null : viewport,
340
405
  ...(deviceScaleFactor !== undefined ? { deviceScaleFactor } : {}),
341
406
  ...(colorScheme ? { colorScheme } : {}),
342
407
  navigationTimeout: Number.parseInt(opts.timeout, 10),
343
408
  waitUntil: opts.waitUntil,
344
409
  recordHarPath: opts.networkHar ? resolve(opts.networkHar) : undefined,
345
410
  extraHeaders: context?.extraHeaders,
411
+ pace,
346
412
  launchArgs: resolveLaunchArgs(opts, Boolean(headed), Boolean(proxy)),
413
+ ...(channel ? { channel } : {}),
414
+ hideAutomation: Boolean(headed),
415
+ ...(userAgent ? { userAgent } : {}),
347
416
  proxy,
348
417
  });
418
+ if (userAgent)
419
+ emit.log(`Presenting as: ${userAgent}`, "debug");
420
+ if (headed) {
421
+ emit.log(channel && channel !== "chromium"
422
+ ? `Headed session uses the installed ${channel} channel with automation signals hidden.`
423
+ : "Headed session uses Playwright's bundled Chromium (no Google Chrome found); automation signals hidden.", "info");
424
+ }
349
425
  // Print mode: --snapshot / --html / --json all suppress file writes.
350
426
  const printMode = opts.snapshot || opts.html || opts.json;
351
427
  let controlServer = null;
@@ -382,6 +458,10 @@ async function runBrowse(url, opts, context) {
382
458
  if (opts.batch) {
383
459
  batchResult = await runBatch(browser, opts.batch, Number.parseInt(opts.timeout, 10));
384
460
  }
461
+ if (collectPlan) {
462
+ await runCollectMode(browser, collectPlan);
463
+ return;
464
+ }
385
465
  let evalResult;
386
466
  if (opts.evaluate) {
387
467
  evalResult = await browser.evaluate(opts.evaluate);
@@ -772,11 +852,11 @@ async function runBrowse(url, opts, context) {
772
852
  const lifecycleAbort = new AbortController();
773
853
  const closeWaits = [];
774
854
  if (loginCloseFile) {
775
- emit.log(`[--login] Headed Chromium is open. Drive the visible window now. Create ${loginCloseFile} to close cleanly.`, "info");
855
+ emit.log(`[--login --attached] Automation-controlled Chrome is open. Drive the visible window now. Create ${loginCloseFile} to close cleanly.`, "info");
776
856
  closeWaits.push(waitForLoginCloseFile(loginCloseFile, lifecycleAbort.signal));
777
857
  }
778
858
  else {
779
- emit.log("[--login] Headed Chromium is open. Walk through your auth flow now. Press Enter here to close + persist cookies into the profile.", "info");
859
+ emit.log("[--login --attached] Automation-controlled Chrome is open. Drive the visible window now. Press Enter here to close + persist cookies into the profile.", "info");
780
860
  closeWaits.push(waitForTerminalEnter(lifecycleAbort.signal));
781
861
  }
782
862
  if (controlServer) {
@@ -912,6 +992,137 @@ async function runBrowse(url, opts, context) {
912
992
  process.exitCode = receivedSignal === "SIGINT" ? 130 : 143;
913
993
  }
914
994
  }
995
+ function parsePositiveInt(raw, flag) {
996
+ if (!/^\d+$/.test(raw.trim()) || Number.parseInt(raw, 10) < 1) {
997
+ throw new Error(`${flag} must be a positive integer (got "${raw}").`);
998
+ }
999
+ return Number.parseInt(raw, 10);
1000
+ }
1001
+ function buildCollectPlan(opts) {
1002
+ if (opts.login)
1003
+ throw new Error("--collect cannot run with --login.");
1004
+ if (opts.snapshot || opts.html || opts.json) {
1005
+ throw new Error("--collect prints its own JSON; drop --snapshot, --html and --json.");
1006
+ }
1007
+ const presetName = typeof opts.collect === "string" ? opts.collect : "generic";
1008
+ const spec = resolveCollectSpec(presetName, {
1009
+ item: opts.collectItem,
1010
+ key: opts.collectKey,
1011
+ keyPattern: opts.collectKeyPattern,
1012
+ fields: opts.collectField,
1013
+ expand: opts.collectExpand,
1014
+ });
1015
+ const limits = {
1016
+ ...DEFAULT_COLLECT_LIMITS,
1017
+ maxItems: opts.collectMaxItems === undefined
1018
+ ? null
1019
+ : parsePositiveInt(opts.collectMaxItems, "--collect-max-items"),
1020
+ maxScrolls: parsePositiveInt(opts.collectMaxScrolls ?? "60", "--collect-max-scrolls"),
1021
+ maxMs: parsePositiveInt(opts.collectMaxSeconds ?? "300", "--collect-max-seconds") * 1_000,
1022
+ idleSteps: parsePositiveInt(opts.collectIdle ?? "5", "--collect-idle"),
1023
+ expandPerStep: spec.expand ? 3 : 0,
1024
+ };
1025
+ const pacing = scrollPacingFromEnv();
1026
+ const msBounds = { min: 0, max: PACING_LIMITS.maxPauseMs };
1027
+ if (opts.collectStep) {
1028
+ pacing.step = parseRange(opts.collectStep, "--collect-step", {
1029
+ min: 0.05,
1030
+ max: PACING_LIMITS.maxStepFraction,
1031
+ });
1032
+ }
1033
+ if (opts.collectPause)
1034
+ pacing.pauseMs = parseRange(opts.collectPause, "--collect-pause", msBounds);
1035
+ if (opts.collectReadPause) {
1036
+ pacing.readPauseMs = parseRange(opts.collectReadPause, "--collect-read-pause", msBounds);
1037
+ }
1038
+ if (opts.collectReadChance !== undefined) {
1039
+ pacing.readChance = parseProbability(opts.collectReadChance, "--collect-read-chance");
1040
+ }
1041
+ if (opts.collectBackChance !== undefined) {
1042
+ pacing.backChance = parseProbability(opts.collectBackChance, "--collect-back-chance");
1043
+ }
1044
+ let seed = randomSeed();
1045
+ if (opts.collectSeed !== undefined) {
1046
+ if (!/^\d+$/.test(opts.collectSeed.trim())) {
1047
+ throw new Error(`--collect-seed must be a non-negative integer (got "${opts.collectSeed}").`);
1048
+ }
1049
+ seed = Number(BigInt(opts.collectSeed.trim()) % 4294967296n);
1050
+ }
1051
+ const format = opts.collectFormat ?? "json";
1052
+ if (format !== "json" && format !== "jsonl") {
1053
+ throw new Error(`--collect-format must be json or jsonl (got "${format}").`);
1054
+ }
1055
+ return {
1056
+ spec,
1057
+ limits,
1058
+ pacing,
1059
+ seed,
1060
+ format,
1061
+ out: opts.collectOut ? resolve(opts.collectOut) : null,
1062
+ };
1063
+ }
1064
+ async function runCollectMode(browser, plan) {
1065
+ const page = browser.currentPage;
1066
+ const rng = createRng(plan.seed);
1067
+ let interrupted = false;
1068
+ const onSignal = () => {
1069
+ interrupted = true;
1070
+ };
1071
+ process.on("SIGINT", onSignal);
1072
+ process.on("SIGTERM", onSignal);
1073
+ let result;
1074
+ try {
1075
+ emit.log(`collect: preset ${plan.spec.preset}, item ${plan.spec.item}, seed ${plan.seed}`, "info");
1076
+ const driver = createPageDriver(page, plan.spec, {
1077
+ rng,
1078
+ log: (message) => emit.log(message, "warn"),
1079
+ });
1080
+ result = await runCollect(driver, {
1081
+ limits: plan.limits,
1082
+ pacing: plan.pacing,
1083
+ rng,
1084
+ shouldStop: () => interrupted,
1085
+ onStep: ({ step, items, added }) => emit.log(`collect: step ${step}, ${items} items (+${added})`, "debug"),
1086
+ });
1087
+ }
1088
+ finally {
1089
+ process.removeListener("SIGINT", onSignal);
1090
+ process.removeListener("SIGTERM", onSignal);
1091
+ }
1092
+ const { items, stats } = result;
1093
+ emit.log(`collect: ${items.length} items in ${stats.steps} steps, stopped on ${stats.stopReason}` +
1094
+ (stats.stopDetail ? ` (${stats.stopDetail})` : ""), "info");
1095
+ const envelope = {
1096
+ url: page.url(),
1097
+ preset: plan.spec.preset,
1098
+ itemSelector: plan.spec.item,
1099
+ seed: plan.seed,
1100
+ stopReason: stats.stopReason,
1101
+ stats,
1102
+ items,
1103
+ };
1104
+ if (plan.format === "jsonl") {
1105
+ const body = items.map((item) => JSON.stringify(item)).join("\n");
1106
+ if (plan.out) {
1107
+ mkdirSync(dirname(plan.out), { recursive: true });
1108
+ writeFileSync(plan.out, body ? `${body}\n` : "");
1109
+ emit.file(plan.out, { items: items.length, stopReason: stats.stopReason, stats });
1110
+ }
1111
+ else if (body) {
1112
+ process.stdout.write(`${body}\n`);
1113
+ }
1114
+ }
1115
+ else if (plan.out) {
1116
+ mkdirSync(dirname(plan.out), { recursive: true });
1117
+ writeFileSync(plan.out, `${JSON.stringify(envelope, null, 2)}\n`);
1118
+ emit.file(plan.out, { items: items.length, stopReason: stats.stopReason, stats });
1119
+ }
1120
+ else {
1121
+ emit.data(envelope);
1122
+ }
1123
+ if (interrupted)
1124
+ process.exitCode = 130;
1125
+ }
915
1126
  async function runBatch(browser, batch, defaultTimeoutMs) {
916
1127
  const result = { clipboardReads: [] };
917
1128
  const steps = splitBatchSteps(batch);
@@ -982,27 +1193,6 @@ async function runBatch(browser, batch, defaultTimeoutMs) {
982
1193
  }
983
1194
  return result;
984
1195
  }
985
- function splitBatchSteps(input) {
986
- const steps = [];
987
- let buf = "";
988
- for (let i = 0; i < input.length; i++) {
989
- const ch = input[i];
990
- if (ch === "\\" && input[i + 1] === ";") {
991
- buf += ";";
992
- i++;
993
- continue;
994
- }
995
- if (ch === ";") {
996
- steps.push(buf);
997
- buf = "";
998
- continue;
999
- }
1000
- buf += ch;
1001
- }
1002
- if (buf.trim())
1003
- steps.push(buf);
1004
- return steps;
1005
- }
1006
1196
  // ---------------------------------------------------------------------------
1007
1197
  // Print mode (--snapshot / --html / --json): stdout, no file writes
1008
1198
  // ---------------------------------------------------------------------------
@@ -2035,15 +2225,50 @@ function summarizeDiagnostics(diag) {
2035
2225
  }
2036
2226
  /**
2037
2227
  * Merge Chromium launch flags from three sources, in order, de-duped:
2038
- * 1. WSLg headed default (`--disable-gpu`) — auto-applied for headed launches
2039
- * under WSL so the window actually paints. Opt out with
2040
- * HARNERY_BROWSER_NO_WSL_DEFAULTS=1.
2228
+ * 1. WSLg `--disable-gpu`, only when HARNERY_BROWSER_WSL_DISABLE_GPU=1. It
2229
+ * was the default for headed launches, but software WebGL (SwiftShader)
2230
+ * is a bot tell that sign-in flows screen for, and current WSLg exposes
2231
+ * the host GPU through D3D12, so the flag is now opt-in for machines
2232
+ * that still paint a blank headed window without it.
2041
2233
  * 2. HARNERY_BROWSER_ARGS env (whitespace-separated) — a machine-wide default.
2042
2234
  * 3. --browser-arg flags on this invocation (repeatable).
2043
2235
  */
2236
+ const BROWSER_CHANNELS = new Set(["chrome", "chrome-beta", "msedge", "chromium"]);
2237
+ /**
2238
+ * Pick the browser channel: `--browser-channel`, then `HARNERY_BROWSER_CHANNEL`,
2239
+ * then (headed only) the installed Google Chrome when one exists. Headless runs
2240
+ * keep the bundled Chromium unless told otherwise, so QA renders stay stable.
2241
+ */
2242
+ function resolveBrowserChannel(opts, headed) {
2243
+ const requested = (opts.browserChannel ?? process.env.HARNERY_BROWSER_CHANNEL)?.trim();
2244
+ if (requested) {
2245
+ if (!BROWSER_CHANNELS.has(requested)) {
2246
+ throw new Error(`Unknown --browser-channel "${requested}". Use chrome, chrome-beta, msedge, or chromium.`);
2247
+ }
2248
+ return requested;
2249
+ }
2250
+ return headed ? installedChromeChannel() : undefined;
2251
+ }
2252
+ /**
2253
+ * Major version of the Chrome that will launch: the installed Chrome for the
2254
+ * `chrome` channel, else Playwright's bundled Chromium. Unknown when neither
2255
+ * answers `--version`; the user-agent store then keeps its last value.
2256
+ */
2257
+ function launchedChromeMajor(channel) {
2258
+ if (channel === "chrome") {
2259
+ const exe = installedChromePath();
2260
+ return exe ? chromeMajorFromExecutable(exe) : undefined;
2261
+ }
2262
+ try {
2263
+ return chromeMajorFromExecutable(chromium.executablePath());
2264
+ }
2265
+ catch {
2266
+ return undefined;
2267
+ }
2268
+ }
2044
2269
  function resolveLaunchArgs(opts, headed, proxyEnabled) {
2045
2270
  const args = [];
2046
- if (headed && !process.env.HARNERY_BROWSER_NO_WSL_DEFAULTS) {
2271
+ if (headed && process.env.HARNERY_BROWSER_WSL_DISABLE_GPU === "1") {
2047
2272
  args.push(...wslHeadedLaunchArgs());
2048
2273
  }
2049
2274
  const envArgs = process.env.HARNERY_BROWSER_ARGS?.trim();
@@ -2067,6 +2292,124 @@ async function verifyBrowserProxyGate(browser, gate) {
2067
2292
  }
2068
2293
  emit.log(`browser proxy gate: ${observedIp} · expected IP confirmed`, "info");
2069
2294
  }
2295
+ /**
2296
+ * How a `browse` run handles sign-in. `--login` opens the installed Google
2297
+ * Chrome with nothing attached, because sites can detect an
2298
+ * automation-controlled browser and disable the account that signed in with
2299
+ * it. The attached window is reachable only through an explicit `--attached`.
2300
+ */
2301
+ export function resolveLoginMode(opts) {
2302
+ if (opts.attached && !opts.login)
2303
+ throw new Error("--attached requires --login.");
2304
+ if (opts.loginCloseFile && !opts.login)
2305
+ throw new Error("--login-close-file requires --login.");
2306
+ if (opts.controlFile && !(opts.login && opts.attached)) {
2307
+ throw new Error("--control-file requires --login --attached. A sign-in to a third-party account uses plain " +
2308
+ "--login, which nothing can drive.");
2309
+ }
2310
+ if (!opts.login)
2311
+ return "none";
2312
+ return opts.attached ? "attached" : "plain";
2313
+ }
2314
+ /**
2315
+ * `--login`: spawn the installed Google Chrome directly on the shared
2316
+ * persistent profile, with no DevTools protocol attached. Playwright enables
2317
+ * its runtime hooks in every frame it drives, and sign-in verification vendors
2318
+ * (X's is the reported case) detect that and fail the flow with no explanation.
2319
+ * The person signs in here; cookies land in the same profile that later
2320
+ * `browse` and `browse-session` runs open, so read-only captures inherit the
2321
+ * session without ever repeating the sign-in under automation.
2322
+ */
2323
+ async function runPlainLogin(url, profileDir, loginCloseFile, userAgent, emit) {
2324
+ const executable = installedChromePath();
2325
+ if (!executable) {
2326
+ throw new Error("--login needs an installed Google Chrome at a standard path; none was found on this machine. " +
2327
+ "Install Google Chrome; do not fall back to --attached for a third-party sign-in.");
2328
+ }
2329
+ mkdirSync(profileDir, { recursive: true });
2330
+ const child = spawn(executable, [
2331
+ `--user-data-dir=${profileDir}`,
2332
+ "--no-first-run",
2333
+ "--no-default-browser-check",
2334
+ ...(userAgent ? [`--user-agent=${userAgent}`] : []),
2335
+ url,
2336
+ ], { stdio: "ignore" });
2337
+ const exited = new Promise((resolveExit) => {
2338
+ child.once("exit", () => resolveExit());
2339
+ child.once("error", () => resolveExit());
2340
+ });
2341
+ const lifecycleAbort = new AbortController();
2342
+ const waits = [exited];
2343
+ if (loginCloseFile) {
2344
+ emit.log(`[--login] Plain Google Chrome is open with nothing attached. Sign in, then close the window or create ${loginCloseFile}.`, "info");
2345
+ waits.push(waitForLoginCloseFile(loginCloseFile, lifecycleAbort.signal));
2346
+ }
2347
+ else {
2348
+ emit.log("[--login] Plain Google Chrome is open with nothing attached. Sign in, then close the window or press Enter here.", "info");
2349
+ waits.push(waitForTerminalEnter(lifecycleAbort.signal));
2350
+ }
2351
+ await Promise.race(waits);
2352
+ lifecycleAbort.abort();
2353
+ if (child.exitCode === null && child.signalCode === null) {
2354
+ child.kill("SIGTERM");
2355
+ await Promise.race([exited, new Promise((r) => setTimeout(r, 5000))]);
2356
+ }
2357
+ emit.log(`[--login] Chrome closed; cookies persisted in ${profileDir}.`, "info");
2358
+ }
2359
+ /**
2360
+ * Under WSL, `--login` opens the Windows host's Google Chrome when one
2361
+ * is installed. Some sign-in flows reject every browser running inside WSL,
2362
+ * even a plain Linux Chrome, while the Windows desktop Chrome signs in
2363
+ * normally. `HARNERY_BROWSER_WSL_PLAIN=linux` keeps the Linux Chrome.
2364
+ */
2365
+ function useWindowsPlainLogin() {
2366
+ if (!isWSL())
2367
+ return false;
2368
+ if ((process.env.HARNERY_BROWSER_WSL_PLAIN ?? "").toLowerCase() === "linux")
2369
+ return false;
2370
+ return windowsChromePath() !== undefined;
2371
+ }
2372
+ /**
2373
+ * The WSL form of `--login`: the person signs in through the Windows
2374
+ * Chrome on a dedicated Windows profile with nothing attached. When the window
2375
+ * closes, the profile's cookies for the sign-in site are read and merged into
2376
+ * the shared cookie store, which later `browse` runs attach.
2377
+ */
2378
+ async function runWindowsPlainLogin(url, storePath, loginCloseFile, emit) {
2379
+ const chromeLinux = windowsChromePath();
2380
+ const localAppData = windowsLocalAppData();
2381
+ if (!chromeLinux || !localAppData) {
2382
+ throw new Error("--login under WSL needs the Windows Google Chrome and %LOCALAPPDATA%; neither was readable.");
2383
+ }
2384
+ const chromeWindows = wslPathToWindows(chromeLinux);
2385
+ const profileWindows = windowsPlainProfile(localAppData);
2386
+ const child = spawn(chromeLinux, [`--user-data-dir=${profileWindows}`, "--no-first-run", "--no-default-browser-check", url], { stdio: "ignore" });
2387
+ const exited = new Promise((resolveExit) => {
2388
+ child.once("exit", () => resolveExit());
2389
+ child.once("error", () => resolveExit());
2390
+ });
2391
+ const lifecycleAbort = new AbortController();
2392
+ const waits = [exited];
2393
+ const how = loginCloseFile ? `create ${loginCloseFile}` : "press Enter here";
2394
+ emit.log(`[--login] Windows Google Chrome is open with nothing attached (profile ${profileWindows}). Sign in, then close the window or ${how}.`, "info");
2395
+ waits.push(loginCloseFile
2396
+ ? waitForLoginCloseFile(loginCloseFile, lifecycleAbort.signal)
2397
+ : waitForTerminalEnter(lifecycleAbort.signal));
2398
+ await Promise.race(waits);
2399
+ lifecycleAbort.abort();
2400
+ stopWindowsChromeProfile(profileWindows);
2401
+ await Promise.race([exited, new Promise((r) => setTimeout(r, 5000))]);
2402
+ const domain = harvestDomain(url);
2403
+ const cookies = harvestWindowsChromeCookies({ chromeWindows, profileWindows, domain });
2404
+ if (cookies.length === 0) {
2405
+ emit.log(`[--login] No ${domain} cookies were found in the Windows profile; the sign-in may not have completed.`, "warn");
2406
+ return;
2407
+ }
2408
+ const jar = new CookieJar({ path: storePath, source: "harn-browse" });
2409
+ jar.save(mergeCookies(jar.load(), cookies));
2410
+ const names = [...new Set(cookies.map((cookie) => cookie.name))].sort().join(", ");
2411
+ emit.log(`[--login] Copied ${cookies.length} ${domain} cookies into ${storePath}: ${names}.`, "info");
2412
+ }
2070
2413
  async function waitForLoginCloseFile(path, signal) {
2071
2414
  while (!existsSync(path) && !signal?.aborted) {
2072
2415
  await new Promise((resolve) => setTimeout(resolve, 250));
@@ -1,3 +1,4 @@
1
+ import { ADAPTERS, normalizeAdapter } from "../core/adapter.js";
1
2
  import { monorepoRoot, resolveOwner } from "../core/agents/index.js";
2
3
  import { readLiveCoordinationRow } from "../core/agents/state/live-coordination-view.js";
3
4
  import { checkpointContext, readContextState, readLatestCapsule, } from "../core/context/index.js";
@@ -58,7 +59,7 @@ export function registerCheckpointCommand(program, emit, context) {
58
59
  .description("Create a durable context-continuity capsule for the current work")
59
60
  .option("--session <id>", "Session id (defaults to the current agent heartbeat)")
60
61
  .option("--instance <id>", "Agent instance id (defaults to the current owner)")
61
- .option("--adapter <id>", "claude-code, codex, or cursor (inferred from heartbeat)")
62
+ .option("--adapter <id>", `${ADAPTERS.join(", ")} (inferred from heartbeat)`)
62
63
  .option("--reason <reason>", "manual, pressure, pre_compact, or session_end", "manual")
63
64
  .option("--note <text>", "Short continuation note for the recovered agent")
64
65
  .option("--json", "Structured JSON output")
@@ -68,7 +69,7 @@ export function registerCheckpointCommand(program, emit, context) {
68
69
  const reason = parseCheckpointReason(opts.reason);
69
70
  const identity = resolveContinuityIdentity(context, opts);
70
71
  if (!identity.adapter) {
71
- throw new Error("could not infer the adapter; pass --adapter claude-code|codex|cursor");
72
+ throw new Error(`could not infer the adapter; pass --adapter ${ADAPTERS.join("|")}`);
72
73
  }
73
74
  const result = checkpointContext(identity.coordRoot, {
74
75
  sessionId: identity.sessionId,
@@ -135,18 +136,13 @@ function resolveContinuityIdentity(context, opts) {
135
136
  return { coordRoot, instanceId, sessionId, adapter };
136
137
  }
137
138
  function adapterFromPlatform(platform) {
138
- if (platform === "claude-code")
139
- return "claude-code";
140
- if (platform === "cursor")
141
- return "cursor";
142
- if (platform === "codex")
143
- return "codex";
144
- return null;
139
+ return normalizeAdapter(platform);
145
140
  }
146
141
  function parseAdapter(value) {
147
- if (value === "claude-code" || value === "codex" || value === "cursor")
148
- return value;
149
- throw new Error(`invalid adapter "${value}"; expected claude-code, codex, or cursor`);
142
+ const adapter = normalizeAdapter(value);
143
+ if (adapter)
144
+ return adapter;
145
+ throw new Error(`invalid adapter "${value}"; expected one of ${ADAPTERS.join(", ")}`);
150
146
  }
151
147
  function parseCheckpointReason(value) {
152
148
  if (value === "manual" ||
@@ -1 +1 @@
1
- {"version":3,"file":"claude-desktop.d.ts","sourceRoot":"","sources":["../../src/commands/claude-desktop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAU1E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,QAAQ,CAAC,EAAE,qBAAqB,GAC/B,IAAI,CA8JN"}
1
+ {"version":3,"file":"claude-desktop.d.ts","sourceRoot":"","sources":["../../src/commands/claude-desktop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAiB1E;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,QAAQ,CAAC,EAAE,qBAAqB,GAC/B,IAAI,CAoNN"}