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
@@ -256,7 +256,17 @@ function selectedCommand(
256
256
  if (token === "--") return undefined;
257
257
  if (token.startsWith("-")) {
258
258
  const option = findRootOption(program, token);
259
- if (option?.required || (option?.optional && !args[index + 1]?.startsWith("-"))) index++;
259
+ // `--format=json` carries its value inline, so the next token is the
260
+ // command, not the value. Skipping it here consumed the command name and
261
+ // the wrong bundle (or none) was materialized, which surfaced downstream
262
+ // as empty output or a bogus "too many arguments" error.
263
+ const inlineValue = token.includes("=");
264
+ if (
265
+ !inlineValue &&
266
+ (option?.required || (option?.optional && !args[index + 1]?.startsWith("-")))
267
+ ) {
268
+ index++;
269
+ }
260
270
  continue;
261
271
  }
262
272
  if (token === "help") return state.byName.get(args[index + 1] ?? "");
@@ -1,6 +1,7 @@
1
1
  import { type SpawnSyncOptions, spawnSync } from "node:child_process";
2
2
  import { writeFileSync } from "node:fs";
3
3
  import type { CookieJar, Cookie as JarCookie } from "../cookies/index.ts";
4
+ import { PaceGate, pacePolicyFromEnv } from "../pace/index.ts";
4
5
 
5
6
  /**
6
7
  * Thin wrapper over Vercel Labs' `agent-browser` Rust CLI.
@@ -34,6 +35,11 @@ export interface AgentBrowserOptions {
34
35
  * agent-browser session. Defaults to a tmp file derived from the jar.
35
36
  */
36
37
  stateFilePath?: string;
38
+ /**
39
+ * Human-pace gate applied before every `open`. Unset resolves the default
40
+ * from the `HARNERY_PACE*` environment; `null` disables pacing.
41
+ */
42
+ pace?: PaceGate | null;
37
43
  }
38
44
 
39
45
  export interface ExecResult {
@@ -48,11 +54,21 @@ const DEFAULT_TIMEOUT_MS = 60_000;
48
54
  export class AgentBrowser {
49
55
  private readonly opts: AgentBrowserOptions;
50
56
  private cookiesSeeded = false;
57
+ private paceGate: PaceGate | null | undefined;
51
58
 
52
59
  constructor(opts: AgentBrowserOptions = {}) {
53
60
  this.opts = opts;
54
61
  }
55
62
 
63
+ /** Block for the human-pace slot before a page load. Synchronous like the rest of this client. */
64
+ private paceBefore(url: string): void {
65
+ if (this.paceGate === undefined) {
66
+ this.paceGate =
67
+ this.opts.pace === undefined ? new PaceGate(pacePolicyFromEnv()) : this.opts.pace;
68
+ }
69
+ this.paceGate?.beforeSync(url);
70
+ }
71
+
56
72
  /**
57
73
  * Run an `agent-browser` subcommand. Returns a structured result.
58
74
  * Throws only on spawn failure (e.g., binary not found); non-zero exit
@@ -132,6 +148,7 @@ export class AgentBrowser {
132
148
 
133
149
  open(url: string, timeoutMs?: number): ExecResult {
134
150
  this.seedCookies();
151
+ this.paceBefore(url);
135
152
  return this.execOrThrow(["open", url], timeoutMs);
136
153
  }
137
154
 
@@ -183,6 +200,7 @@ export class AgentBrowser {
183
200
  // Naive shell-like splitting; agent-browser's own argv parser handles
184
201
  // the actual command; we just split on whitespace for the wrapper.
185
202
  const args = trimmed.split(/\s+/);
203
+ if (args[0] === "open" && args[1]) this.paceBefore(args[1]);
186
204
  results.push(this.exec(args));
187
205
  }
188
206
  return results;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Split a `browse --batch` string into steps.
3
+ *
4
+ * Steps are separated by `;`. Two rules keep JavaScript intact:
5
+ *
6
+ * 1. A step that starts with the `eval` verb ends only at a `;` that sits
7
+ * outside JavaScript quotes ('...', "...", `...`) and outside (), [] and {}.
8
+ * So `eval (() => { const a = 1; return a })(); wait 500` is two steps.
9
+ * 2. Every other step ends at the next `;`, exactly as before. Selectors and
10
+ * fill values may contain apostrophes or brackets that are not balanced
11
+ * JavaScript, so they get no quote or bracket tracking.
12
+ *
13
+ * `\;` always inserts a literal `;` without ending the step, in any verb.
14
+ * A top-level `;` inside an eval (two bare statements) still ends the step:
15
+ * wrap multiple statements in a block or an arrow function.
16
+ */
17
+ export function splitBatchSteps(input: string): string[] {
18
+ const steps: string[] = [];
19
+ let buf = "";
20
+ let stepStart = true;
21
+ let jsAware = false;
22
+ let quote: string | null = null;
23
+ let depth = 0;
24
+
25
+ const endStep = () => {
26
+ if (buf.trim()) steps.push(buf);
27
+ buf = "";
28
+ stepStart = true;
29
+ jsAware = false;
30
+ quote = null;
31
+ depth = 0;
32
+ };
33
+
34
+ for (let i = 0; i < input.length; i++) {
35
+ if (stepStart) {
36
+ // Decide the splitting rule once per step from its leading verb.
37
+ jsAware = /^\s*eval(\s|$)/i.test(input.slice(i));
38
+ stepStart = false;
39
+ }
40
+ const ch = input[i] as string;
41
+ if (ch === "\\" && input[i + 1] === ";") {
42
+ buf += ";";
43
+ i++;
44
+ continue;
45
+ }
46
+ if (jsAware) {
47
+ if (quote) {
48
+ buf += ch;
49
+ if (ch === "\\" && i + 1 < input.length) {
50
+ buf += input[i + 1];
51
+ i++;
52
+ } else if (ch === quote) {
53
+ quote = null;
54
+ }
55
+ continue;
56
+ }
57
+ if (ch === "'" || ch === '"' || ch === "`") {
58
+ quote = ch;
59
+ buf += ch;
60
+ continue;
61
+ }
62
+ if (ch === "(" || ch === "[" || ch === "{") depth++;
63
+ else if (ch === ")" || ch === "]" || ch === "}") depth = Math.max(0, depth - 1);
64
+ if (ch === ";" && depth === 0) {
65
+ endStep();
66
+ continue;
67
+ }
68
+ buf += ch;
69
+ continue;
70
+ }
71
+ if (ch === ";") {
72
+ endStep();
73
+ continue;
74
+ }
75
+ buf += ch;
76
+ }
77
+ if (buf.trim()) steps.push(buf);
78
+ return steps;
79
+ }
@@ -16,6 +16,7 @@ import {
16
16
  CookieStoreParseError,
17
17
  type Cookie as JarCookie,
18
18
  } from "../cookies/index.ts";
19
+ import { PaceGate, pacePolicyFromEnv } from "../pace/index.ts";
19
20
  import { type AssertResult, type AssertSpec, buildAssertCheck } from "./asserts.js";
20
21
  import { stitchPngRows } from "./capture-fidelity.js";
21
22
  import {
@@ -33,6 +34,8 @@ import {
33
34
  type LayoutLintRequest,
34
35
  type LayoutLintResult,
35
36
  } from "./geometry.js";
37
+ import { browserIdentity, installDocumentIdentity } from "./identity.js";
38
+ import { AUTOMATION_DEFAULT_ARGS_TO_DROP, automationDisguiseArgs } from "./launch-args.js";
36
39
  import {
37
40
  buildClearLayoutAnnotationsScript,
38
41
  buildLayoutAnnotateScript,
@@ -91,7 +94,7 @@ export interface BrowserOptions {
91
94
  /** Cookie jar to seed/sync with. Pass `null` to skip jar entirely. */
92
95
  jar?: CookieJar | null;
93
96
  /** Viewport. Default 1280x800. */
94
- viewport?: { width: number; height: number };
97
+ viewport?: { width: number; height: number } | null;
95
98
  /**
96
99
  * Device scale factor (DPR) for the context. Unset keeps Playwright's
97
100
  * default of 1, so screenshots are CSS-pixel sized. A higher value renders
@@ -128,6 +131,13 @@ export interface BrowserOptions {
128
131
  * via this callback (e.g., a Cloudflare-bypass header for specific zones).
129
132
  */
130
133
  extraHeaders?: (url: string) => Record<string, string>;
134
+ /**
135
+ * Human-pace gate applied before every page load: `navigate`, `reload`, and
136
+ * the session tab verbs. Unset resolves the default from the `HARNERY_PACE*`
137
+ * environment (on, 3 to 9 seconds between loads of one site). `null`
138
+ * disables pacing for this client.
139
+ */
140
+ pace?: PaceGate | null;
131
141
  /**
132
142
  * Extra Chromium command-line flags, passed through to Playwright's
133
143
  * `launchPersistentContext` `args`. Used for environment-specific
@@ -136,6 +146,28 @@ export interface BrowserOptions {
136
146
  * defaults only.
137
147
  */
138
148
  launchArgs?: string[];
149
+ /**
150
+ * Playwright browser channel. `"chrome"` launches the operator's installed
151
+ * Google Chrome instead of the bundled "Chrome for Testing" build. Unset or
152
+ * `"chromium"` keeps the bundled browser.
153
+ */
154
+ channel?: "chrome" | "chrome-beta" | "msedge" | "chromium";
155
+ /**
156
+ * Drop Playwright's `--enable-automation` default, disable Blink's
157
+ * AutomationControlled feature, and run with the Chromium sandbox on (no
158
+ * `--no-sandbox`), so pages do not see `navigator.webdriver`, the automation
159
+ * infobar, or the unsupported-flag banner. Headed sessions set this; sites
160
+ * that screen for automation otherwise refuse clicks a person makes in the
161
+ * window.
162
+ */
163
+ hideAutomation?: boolean;
164
+ /**
165
+ * User agent to present. Set by `browse` from `lib/browser/user-agent`
166
+ * (never Linux, never HeadlessChrome). Applied both as the Playwright
167
+ * context override and as `--user-agent` so workers and frames agree.
168
+ * Unset keeps the browser's native string.
169
+ */
170
+ userAgent?: string;
139
171
  /** Authenticated browser proxy passed directly to Playwright. */
140
172
  proxy?: { server: string; username?: string; password?: string };
141
173
  }
@@ -306,6 +338,7 @@ export class Browser {
306
338
  private consoleEvents: ConsoleEvent[] = [];
307
339
  private pageErrors: PageErrorEvent[] = [];
308
340
  private failedRequests: FailedRequest[] = [];
341
+ private identityReady = new WeakMap<Page, Promise<void>>();
309
342
 
310
343
  constructor(private opts: BrowserOptions = {}) {
311
344
  this.profileDir = opts.profileDir ?? DEFAULT_PROFILE;
@@ -326,20 +359,54 @@ export class Browser {
326
359
  */
327
360
  private async openOnce(): Promise<void> {
328
361
  const jarCookies = this.opts.jar?.list() ?? [];
362
+ const launchIdentity = this.opts.userAgent ? browserIdentity(this.opts.userAgent) : undefined;
363
+ const launchArgs = [
364
+ ...new Set([
365
+ ...(this.opts.headed && this.opts.viewport == null ? ["--window-size=1536,864"] : []),
366
+ ...(this.opts.launchArgs ?? []),
367
+ ...(this.opts.hideAutomation ? automationDisguiseArgs() : []),
368
+ ...(this.opts.userAgent ? [`--user-agent=${this.opts.userAgent}`] : []),
369
+ ]),
370
+ ];
329
371
 
330
372
  // Hold a launch slot only across the spawn itself, not the browser's life.
331
373
  await acquireLaunchSlot();
332
374
  try {
333
375
  this.context = await chromium.launchPersistentContext(this.profileDir, {
334
376
  headless: !this.opts.headed,
335
- viewport: this.opts.viewport ?? { width: 1280, height: 800 },
377
+ // Service-worker-owned navigations bypass Playwright request routes.
378
+ ...(this.getPaceGate()?.policy.enabled ? { serviceWorkers: "block" as const } : {}),
379
+ viewport:
380
+ this.opts.viewport !== undefined
381
+ ? this.opts.viewport
382
+ : this.opts.headed
383
+ ? null
384
+ : { width: 1280, height: 800 },
336
385
  ...(this.opts.deviceScaleFactor !== undefined
337
386
  ? { deviceScaleFactor: this.opts.deviceScaleFactor }
338
387
  : {}),
339
388
  ...(this.opts.colorScheme ? { colorScheme: this.opts.colorScheme } : {}),
389
+ ...(this.opts.userAgent ? { userAgent: this.opts.userAgent } : {}),
390
+ ...(launchIdentity
391
+ ? {
392
+ extraHTTPHeaders: {
393
+ "sec-ch-ua-platform": JSON.stringify(launchIdentity.userAgentMetadata.platform),
394
+ "sec-ch-ua-mobile": "?0",
395
+ "sec-ch-ua": launchIdentity.userAgentMetadata.brands
396
+ .map(
397
+ ({ brand, version }) => `${JSON.stringify(brand)};v=${JSON.stringify(version)}`,
398
+ )
399
+ .join(", "),
400
+ },
401
+ }
402
+ : {}),
340
403
  ...(this.opts.launchTimeout !== undefined ? { timeout: this.opts.launchTimeout } : {}),
341
- ...(this.opts.launchArgs && this.opts.launchArgs.length > 0
342
- ? { args: this.opts.launchArgs }
404
+ ...(launchArgs.length > 0 ? { args: launchArgs } : {}),
405
+ ...(this.opts.channel && this.opts.channel !== "chromium"
406
+ ? { channel: this.opts.channel }
407
+ : {}),
408
+ ...(this.opts.hideAutomation
409
+ ? { ignoreDefaultArgs: [...AUTOMATION_DEFAULT_ARGS_TO_DROP], chromiumSandbox: true }
343
410
  : {}),
344
411
  ...(this.opts.proxy ? { proxy: this.opts.proxy } : {}),
345
412
  ...(this.opts.recordHarPath
@@ -350,18 +417,55 @@ export class Browser {
350
417
  releaseLaunchSlot();
351
418
  }
352
419
  this.context.setDefaultNavigationTimeout(this.opts.navigationTimeout ?? 30_000);
420
+ const identity = this.opts.userAgent
421
+ ? browserIdentity(this.opts.userAgent, this.context.browser()?.version())
422
+ : undefined;
423
+ if (identity) await this.context.addInitScript(installDocumentIdentity, identity);
353
424
 
354
425
  if (jarCookies.length > 0) {
355
426
  await this.context.addCookies(jarCookies.map(toPWCookie));
356
427
  }
357
428
 
358
- // Caller-injected extraHeaders callback (e.g., for Cloudflare-bypass
359
- // or custom auth headers). Per-request route handler so headers only
360
- // attach when the callback returns non-empty.
429
+ // Gate actual document requests, including links, forms, script navigation,
430
+ // and the first request of a popup. Method-level waits miss those loads.
431
+ // Redirect hops are part of the original load, not additional reservations.
361
432
  const headersCb = this.opts.extraHeaders;
362
- if (headersCb) {
433
+ if (this.getPaceGate()?.policy.enabled || headersCb || this.opts.userAgent) {
363
434
  await this.context.route("**/*", async (route, request) => {
364
- const extra = headersCb(request.url());
435
+ let mainDocument = false;
436
+ if (request.isNavigationRequest() && !request.redirectedFrom()) {
437
+ try {
438
+ mainDocument = request.frame() === request.frame().page().mainFrame();
439
+ } catch {
440
+ // A popup's first request can precede creation of its Page/Frame.
441
+ mainDocument = true;
442
+ }
443
+ }
444
+ if (mainDocument) {
445
+ try {
446
+ await this.getPaceGate()?.before(request.url());
447
+ } catch {
448
+ await route.abort("failed");
449
+ return;
450
+ }
451
+ }
452
+ const extra = { ...headersCb?.(request.url()) };
453
+ // Popup request headers are already computed before its CDP session is
454
+ // available. Keep negotiated hints consistent on that first request too.
455
+ if (identity) {
456
+ const metadata = identity.userAgentMetadata;
457
+ extra["sec-ch-ua-platform"] = JSON.stringify(metadata.platform);
458
+ extra["sec-ch-ua-mobile"] = "?0";
459
+ extra["sec-ch-ua"] = metadata.brands
460
+ .map(({ brand, version }) => `${JSON.stringify(brand)};v=${JSON.stringify(version)}`)
461
+ .join(", ");
462
+ for (const [header, value] of Object.entries({
463
+ "sec-ch-ua-platform-version": metadata.platformVersion,
464
+ "sec-ch-ua-arch": metadata.architecture,
465
+ "sec-ch-ua-bitness": metadata.bitness,
466
+ }))
467
+ if (header in request.headers()) extra[header] = JSON.stringify(value);
468
+ }
365
469
  if (Object.keys(extra).length === 0) return route.continue();
366
470
  const headers = { ...request.headers(), ...extra };
367
471
  return route.continue({ headers });
@@ -370,6 +474,7 @@ export class Browser {
370
474
 
371
475
  const pages = this.context.pages();
372
476
  const firstPage = pages[0] ?? (await this.context.newPage());
477
+ await Promise.all(this.context.pages().map((page) => this.preparePageIdentity(page)));
373
478
  for (const page of this.context.pages()) this.trackPage(page, page === firstPage);
374
479
  this.context.on("page", (page) => this.trackPage(page, true));
375
480
  }
@@ -491,6 +596,10 @@ export class Browser {
491
596
  type: "unknown",
492
597
  });
493
598
  this.attachDiagnosticListeners(page);
599
+ void this.preparePageIdentity(page).catch((error) => {
600
+ if (!page.isClosed())
601
+ this.pageErrors.push({ message: `Browser identity setup failed: ${String(error)}` });
602
+ });
494
603
  page.on("domcontentloaded", () => this.recordDocumentNavigation(page));
495
604
  page.once("close", () => {
496
605
  this.pageRecency.delete(page);
@@ -501,6 +610,23 @@ export class Browser {
501
610
  if (makeActive) this.setActivePage(page);
502
611
  }
503
612
 
613
+ private preparePageIdentity(page: Page): Promise<void> {
614
+ if (!this.opts.userAgent || !this.context) return Promise.resolve();
615
+ let ready = this.identityReady.get(page);
616
+ if (!ready) {
617
+ const context = this.context;
618
+ const userAgent = this.opts.userAgent;
619
+ ready = (async () => {
620
+ const identity = browserIdentity(userAgent, context.browser()?.version());
621
+ if (!identity) return;
622
+ const session = await context.newCDPSession(page);
623
+ await session.send("Emulation.setUserAgentOverride", identity);
624
+ })();
625
+ this.identityReady.set(page, ready);
626
+ }
627
+ return ready;
628
+ }
629
+
504
630
  private setActivePage(page: Page): void {
505
631
  if (page.isClosed()) return;
506
632
  this.page = page;
@@ -569,8 +695,19 @@ export class Browser {
569
695
  };
570
696
  }
571
697
 
698
+ private paceGate: PaceGate | null | undefined;
699
+
700
+ private getPaceGate(): PaceGate | null {
701
+ if (this.paceGate === undefined) {
702
+ this.paceGate =
703
+ this.opts.pace === undefined ? new PaceGate(pacePolicyFromEnv()) : this.opts.pace;
704
+ }
705
+ return this.paceGate;
706
+ }
707
+
572
708
  async navigate(url: string): Promise<NavigateResult> {
573
709
  const page = this.currentPage;
710
+ await this.preparePageIdentity(page);
574
711
  const response = await page.goto(url, { waitUntil: this.opts.waitUntil ?? "load" });
575
712
  return {
576
713
  url: page.url(),
@@ -1381,6 +1518,7 @@ export class Browser {
1381
1518
  const page = await this.context.newPage();
1382
1519
  this.trackPage(page, true);
1383
1520
  try {
1521
+ await this.preparePageIdentity(page);
1384
1522
  await page.goto(url, { waitUntil: this.opts.waitUntil ?? "load" });
1385
1523
  this.sessionRevision++;
1386
1524
  return await this.describeTab(page);