harnery 0.0.1 → 0.2.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 (445) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -2
  3. package/bin/agent-coord +42 -0
  4. package/bin/agent-hook +44 -0
  5. package/bin/harn +40 -0
  6. package/dist/cli.d.ts +9 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +18 -0
  9. package/dist/commander.d.ts +128 -0
  10. package/dist/commander.d.ts.map +1 -0
  11. package/dist/commander.js +126 -0
  12. package/dist/commands/agents.d.ts +18 -0
  13. package/dist/commands/agents.d.ts.map +1 -0
  14. package/dist/commands/agents.js +3946 -0
  15. package/dist/commands/backup.d.ts +22 -0
  16. package/dist/commands/backup.d.ts.map +1 -0
  17. package/dist/commands/backup.js +262 -0
  18. package/dist/commands/browse-ai.d.ts +4 -0
  19. package/dist/commands/browse-ai.d.ts.map +1 -0
  20. package/dist/commands/browse-ai.js +156 -0
  21. package/dist/commands/browse.d.ts +4 -0
  22. package/dist/commands/browse.d.ts.map +1 -0
  23. package/dist/commands/browse.js +590 -0
  24. package/dist/commands/callers.d.ts +4 -0
  25. package/dist/commands/callers.d.ts.map +1 -0
  26. package/dist/commands/callers.js +276 -0
  27. package/dist/commands/completion.d.ts +17 -0
  28. package/dist/commands/completion.d.ts.map +1 -0
  29. package/dist/commands/completion.js +158 -0
  30. package/dist/commands/config-get.d.ts +4 -0
  31. package/dist/commands/config-get.d.ts.map +1 -0
  32. package/dist/commands/config-get.js +131 -0
  33. package/dist/commands/context.d.ts +11 -0
  34. package/dist/commands/context.d.ts.map +1 -0
  35. package/dist/commands/context.js +185 -0
  36. package/dist/commands/cookies.d.ts +4 -0
  37. package/dist/commands/cookies.d.ts.map +1 -0
  38. package/dist/commands/cookies.js +140 -0
  39. package/dist/commands/docs.d.ts +4 -0
  40. package/dist/commands/docs.d.ts.map +1 -0
  41. package/dist/commands/docs.js +137 -0
  42. package/dist/commands/doctor.d.ts +25 -0
  43. package/dist/commands/doctor.d.ts.map +1 -0
  44. package/dist/commands/doctor.js +200 -0
  45. package/dist/commands/edit-batch.d.ts +18 -0
  46. package/dist/commands/edit-batch.d.ts.map +1 -0
  47. package/dist/commands/edit-batch.js +172 -0
  48. package/dist/commands/eml.d.ts +4 -0
  49. package/dist/commands/eml.d.ts.map +1 -0
  50. package/dist/commands/eml.js +428 -0
  51. package/dist/commands/env.d.ts +4 -0
  52. package/dist/commands/env.d.ts.map +1 -0
  53. package/dist/commands/env.js +201 -0
  54. package/dist/commands/fetch.d.ts +4 -0
  55. package/dist/commands/fetch.d.ts.map +1 -0
  56. package/dist/commands/fetch.js +99 -0
  57. package/dist/commands/file-history.d.ts +4 -0
  58. package/dist/commands/file-history.d.ts.map +1 -0
  59. package/dist/commands/file-history.js +152 -0
  60. package/dist/commands/grep.d.ts +4 -0
  61. package/dist/commands/grep.d.ts.map +1 -0
  62. package/dist/commands/grep.js +317 -0
  63. package/dist/commands/init.d.ts +82 -0
  64. package/dist/commands/init.d.ts.map +1 -0
  65. package/dist/commands/init.js +288 -0
  66. package/dist/commands/outline.d.ts +4 -0
  67. package/dist/commands/outline.d.ts.map +1 -0
  68. package/dist/commands/outline.js +494 -0
  69. package/dist/commands/presence.d.ts +12 -0
  70. package/dist/commands/presence.d.ts.map +1 -0
  71. package/dist/commands/presence.js +123 -0
  72. package/dist/commands/read.d.ts +7 -0
  73. package/dist/commands/read.d.ts.map +1 -0
  74. package/dist/commands/read.js +46 -0
  75. package/dist/commands/scratch.d.ts +4 -0
  76. package/dist/commands/scratch.d.ts.map +1 -0
  77. package/dist/commands/scratch.js +426 -0
  78. package/dist/commands/session.d.ts +4 -0
  79. package/dist/commands/session.d.ts.map +1 -0
  80. package/dist/commands/session.js +162 -0
  81. package/dist/commands/sync.d.ts +24 -0
  82. package/dist/commands/sync.d.ts.map +1 -0
  83. package/dist/commands/sync.js +275 -0
  84. package/dist/commands/toc.d.ts +5 -0
  85. package/dist/commands/toc.d.ts.map +1 -0
  86. package/dist/commands/toc.js +153 -0
  87. package/dist/commands/tokens.d.ts +4 -0
  88. package/dist/commands/tokens.d.ts.map +1 -0
  89. package/dist/commands/tokens.js +48 -0
  90. package/dist/commands/tunnel.d.ts +4 -0
  91. package/dist/commands/tunnel.d.ts.map +1 -0
  92. package/dist/commands/tunnel.js +513 -0
  93. package/dist/commands/uninstall.d.ts +22 -0
  94. package/dist/commands/uninstall.d.ts.map +1 -0
  95. package/dist/commands/uninstall.js +126 -0
  96. package/dist/commands/web.d.ts +4 -0
  97. package/dist/commands/web.d.ts.map +1 -0
  98. package/dist/commands/web.js +165 -0
  99. package/dist/core/agents/canonical-emit.d.ts +27 -0
  100. package/dist/core/agents/canonical-emit.d.ts.map +1 -0
  101. package/dist/core/agents/canonical-emit.js +72 -0
  102. package/dist/core/agents/cli-emit.d.ts +27 -0
  103. package/dist/core/agents/cli-emit.d.ts.map +1 -0
  104. package/dist/core/agents/cli-emit.js +57 -0
  105. package/dist/core/agents/cli.d.ts +10 -0
  106. package/dist/core/agents/cli.d.ts.map +1 -0
  107. package/dist/core/agents/cli.js +757 -0
  108. package/dist/core/agents/codex-replay.d.ts +29 -0
  109. package/dist/core/agents/codex-replay.d.ts.map +1 -0
  110. package/dist/core/agents/codex-replay.js +138 -0
  111. package/dist/core/agents/coord-client.d.ts +98 -0
  112. package/dist/core/agents/coord-client.d.ts.map +1 -0
  113. package/dist/core/agents/coord-client.js +212 -0
  114. package/dist/core/agents/events/consume.d.ts +59 -0
  115. package/dist/core/agents/events/consume.d.ts.map +1 -0
  116. package/dist/core/agents/events/consume.js +147 -0
  117. package/dist/core/agents/events/emit.d.ts +42 -0
  118. package/dist/core/agents/events/emit.d.ts.map +1 -0
  119. package/dist/core/agents/events/emit.js +70 -0
  120. package/dist/core/agents/events/ulid.d.ts +11 -0
  121. package/dist/core/agents/events/ulid.d.ts.map +1 -0
  122. package/dist/core/agents/events/ulid.js +47 -0
  123. package/dist/core/agents/index.d.ts +14 -0
  124. package/dist/core/agents/index.d.ts.map +1 -0
  125. package/dist/core/agents/index.js +13 -0
  126. package/dist/core/agents/paths.d.ts +6 -0
  127. package/dist/core/agents/paths.d.ts.map +1 -0
  128. package/dist/core/agents/paths.js +17 -0
  129. package/dist/core/agents/render/prompt-context.d.ts +43 -0
  130. package/dist/core/agents/render/prompt-context.d.ts.map +1 -0
  131. package/dist/core/agents/render/prompt-context.js +335 -0
  132. package/dist/core/agents/render/session-context.d.ts +39 -0
  133. package/dist/core/agents/render/session-context.d.ts.map +1 -0
  134. package/dist/core/agents/render/session-context.js +283 -0
  135. package/dist/core/agents/rules/claim-conflict.d.ts +35 -0
  136. package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -0
  137. package/dist/core/agents/rules/claim-conflict.js +244 -0
  138. package/dist/core/agents/rules/commit-conflict.d.ts +59 -0
  139. package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -0
  140. package/dist/core/agents/rules/commit-conflict.js +244 -0
  141. package/dist/core/agents/rules/stop-hook.d.ts +44 -0
  142. package/dist/core/agents/rules/stop-hook.d.ts.map +1 -0
  143. package/dist/core/agents/rules/stop-hook.js +161 -0
  144. package/dist/core/agents/session-events.d.ts +41 -0
  145. package/dist/core/agents/session-events.d.ts.map +1 -0
  146. package/dist/core/agents/session-events.js +205 -0
  147. package/dist/core/agents/state/activity-log.d.ts +18 -0
  148. package/dist/core/agents/state/activity-log.d.ts.map +1 -0
  149. package/dist/core/agents/state/activity-log.js +34 -0
  150. package/dist/core/agents/state/council.d.ts +39 -0
  151. package/dist/core/agents/state/council.d.ts.map +1 -0
  152. package/dist/core/agents/state/council.js +216 -0
  153. package/dist/core/agents/state/heartbeat-projector.d.ts +59 -0
  154. package/dist/core/agents/state/heartbeat-projector.d.ts.map +1 -0
  155. package/dist/core/agents/state/heartbeat-projector.js +436 -0
  156. package/dist/core/agents/state/heartbeat-writer.d.ts +64 -0
  157. package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -0
  158. package/dist/core/agents/state/heartbeat-writer.js +271 -0
  159. package/dist/core/agents/state/names.d.ts +35 -0
  160. package/dist/core/agents/state/names.d.ts.map +1 -0
  161. package/dist/core/agents/state/names.js +376 -0
  162. package/dist/core/agents/state/pidmap.d.ts +11 -0
  163. package/dist/core/agents/state/pidmap.d.ts.map +1 -0
  164. package/dist/core/agents/state/pidmap.js +32 -0
  165. package/dist/core/agents/state/scratch.d.ts +27 -0
  166. package/dist/core/agents/state/scratch.d.ts.map +1 -0
  167. package/dist/core/agents/state/scratch.js +90 -0
  168. package/dist/core/agents/state/shell-mutation.d.ts +17 -0
  169. package/dist/core/agents/state/shell-mutation.d.ts.map +1 -0
  170. package/dist/core/agents/state/shell-mutation.js +41 -0
  171. package/dist/core/agents/state/stale-sweep.d.ts +16 -0
  172. package/dist/core/agents/state/stale-sweep.d.ts.map +1 -0
  173. package/dist/core/agents/state/stale-sweep.js +166 -0
  174. package/dist/core/config.d.ts +29 -0
  175. package/dist/core/config.d.ts.map +1 -0
  176. package/dist/core/config.js +108 -0
  177. package/dist/core/hooks/cli.d.ts +21 -0
  178. package/dist/core/hooks/cli.d.ts.map +1 -0
  179. package/dist/core/hooks/cli.js +1123 -0
  180. package/dist/core/hooks/effects/image-capture.d.ts +43 -0
  181. package/dist/core/hooks/effects/image-capture.d.ts.map +1 -0
  182. package/dist/core/hooks/effects/image-capture.js +288 -0
  183. package/dist/core/hooks/effects/index.d.ts +64 -0
  184. package/dist/core/hooks/effects/index.d.ts.map +1 -0
  185. package/dist/core/hooks/effects/index.js +197 -0
  186. package/dist/core/hooks/events/emit.d.ts +31 -0
  187. package/dist/core/hooks/events/emit.d.ts.map +1 -0
  188. package/dist/core/hooks/events/emit.js +89 -0
  189. package/dist/core/hooks/events/schema.d.ts +235 -0
  190. package/dist/core/hooks/events/schema.d.ts.map +1 -0
  191. package/dist/core/hooks/events/schema.js +12 -0
  192. package/dist/core/hooks/events/ulid.d.ts +10 -0
  193. package/dist/core/hooks/events/ulid.d.ts.map +1 -0
  194. package/dist/core/hooks/events/ulid.js +47 -0
  195. package/dist/core/hooks/harness/detect.d.ts +9 -0
  196. package/dist/core/hooks/harness/detect.d.ts.map +1 -0
  197. package/dist/core/hooks/harness/detect.js +29 -0
  198. package/dist/core/hooks/harness/events.d.ts +45 -0
  199. package/dist/core/hooks/harness/events.d.ts.map +1 -0
  200. package/dist/core/hooks/harness/events.js +71 -0
  201. package/dist/core/hooks/harness/output.d.ts +46 -0
  202. package/dist/core/hooks/harness/output.d.ts.map +1 -0
  203. package/dist/core/hooks/harness/output.js +87 -0
  204. package/dist/core/hooks/harness/parse.d.ts +67 -0
  205. package/dist/core/hooks/harness/parse.d.ts.map +1 -0
  206. package/dist/core/hooks/harness/parse.js +132 -0
  207. package/dist/core/hooks/index.d.ts +8 -0
  208. package/dist/core/hooks/index.d.ts.map +1 -0
  209. package/dist/core/hooks/index.js +7 -0
  210. package/dist/core/hooks/resolve/anchor.d.ts +37 -0
  211. package/dist/core/hooks/resolve/anchor.d.ts.map +1 -0
  212. package/dist/core/hooks/resolve/anchor.js +48 -0
  213. package/dist/core/hooks/resolve/coord-root.d.ts +6 -0
  214. package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -0
  215. package/dist/core/hooks/resolve/coord-root.js +27 -0
  216. package/dist/core/hooks/resolve/intent.d.ts +33 -0
  217. package/dist/core/hooks/resolve/intent.d.ts.map +1 -0
  218. package/dist/core/hooks/resolve/intent.js +79 -0
  219. package/dist/core/hooks/resolve/owner.d.ts +42 -0
  220. package/dist/core/hooks/resolve/owner.d.ts.map +1 -0
  221. package/dist/core/hooks/resolve/owner.js +140 -0
  222. package/dist/core/hooks/resolve/transcript.d.ts +26 -0
  223. package/dist/core/hooks/resolve/transcript.d.ts.map +1 -0
  224. package/dist/core/hooks/resolve/transcript.js +73 -0
  225. package/dist/index.d.ts +15 -0
  226. package/dist/index.d.ts.map +1 -0
  227. package/dist/index.js +13 -0
  228. package/dist/lib/agent-browser/client.d.ts +99 -0
  229. package/dist/lib/agent-browser/client.d.ts.map +1 -0
  230. package/dist/lib/agent-browser/client.js +177 -0
  231. package/dist/lib/agent-browser/index.d.ts +2 -0
  232. package/dist/lib/agent-browser/index.d.ts.map +1 -0
  233. package/dist/lib/agent-browser/index.js +1 -0
  234. package/dist/lib/browser/client.d.ts +193 -0
  235. package/dist/lib/browser/client.d.ts.map +1 -0
  236. package/dist/lib/browser/client.js +325 -0
  237. package/dist/lib/browser/dev-overlay.d.ts +23 -0
  238. package/dist/lib/browser/dev-overlay.d.ts.map +1 -0
  239. package/dist/lib/browser/dev-overlay.js +153 -0
  240. package/dist/lib/browser/index.d.ts +5 -0
  241. package/dist/lib/browser/index.d.ts.map +1 -0
  242. package/dist/lib/browser/index.js +2 -0
  243. package/dist/lib/browser/layout.d.ts +79 -0
  244. package/dist/lib/browser/layout.d.ts.map +1 -0
  245. package/dist/lib/browser/layout.js +220 -0
  246. package/dist/lib/browser/visibility.d.ts +86 -0
  247. package/dist/lib/browser/visibility.d.ts.map +1 -0
  248. package/dist/lib/browser/visibility.js +333 -0
  249. package/dist/lib/browser/visual-diff.d.ts +38 -0
  250. package/dist/lib/browser/visual-diff.d.ts.map +1 -0
  251. package/dist/lib/browser/visual-diff.js +107 -0
  252. package/dist/lib/completion/bash.d.ts +25 -0
  253. package/dist/lib/completion/bash.d.ts.map +1 -0
  254. package/dist/lib/completion/bash.js +284 -0
  255. package/dist/lib/completion/fish.d.ts +16 -0
  256. package/dist/lib/completion/fish.d.ts.map +1 -0
  257. package/dist/lib/completion/fish.js +118 -0
  258. package/dist/lib/completion/index.d.ts +5 -0
  259. package/dist/lib/completion/index.d.ts.map +1 -0
  260. package/dist/lib/completion/index.js +4 -0
  261. package/dist/lib/completion/walk.d.ts +68 -0
  262. package/dist/lib/completion/walk.d.ts.map +1 -0
  263. package/dist/lib/completion/walk.js +102 -0
  264. package/dist/lib/completion/zsh.d.ts +13 -0
  265. package/dist/lib/completion/zsh.d.ts.map +1 -0
  266. package/dist/lib/completion/zsh.js +249 -0
  267. package/dist/lib/context/index.d.ts +107 -0
  268. package/dist/lib/context/index.d.ts.map +1 -0
  269. package/dist/lib/context/index.js +275 -0
  270. package/dist/lib/cookies/client.d.ts +131 -0
  271. package/dist/lib/cookies/client.d.ts.map +1 -0
  272. package/dist/lib/cookies/client.js +239 -0
  273. package/dist/lib/cookies/index.d.ts +2 -0
  274. package/dist/lib/cookies/index.d.ts.map +1 -0
  275. package/dist/lib/cookies/index.js +1 -0
  276. package/dist/lib/council/index.d.ts +266 -0
  277. package/dist/lib/council/index.d.ts.map +1 -0
  278. package/dist/lib/council/index.js +674 -0
  279. package/dist/lib/docs-index.d.ts +28 -0
  280. package/dist/lib/docs-index.d.ts.map +1 -0
  281. package/dist/lib/docs-index.js +169 -0
  282. package/dist/lib/docs-lint.d.ts +26 -0
  283. package/dist/lib/docs-lint.d.ts.map +1 -0
  284. package/dist/lib/docs-lint.js +378 -0
  285. package/dist/lib/docs-sweep.d.ts +34 -0
  286. package/dist/lib/docs-sweep.d.ts.map +1 -0
  287. package/dist/lib/docs-sweep.js +304 -0
  288. package/dist/lib/docs.d.ts +27 -0
  289. package/dist/lib/docs.d.ts.map +1 -0
  290. package/dist/lib/docs.js +142 -0
  291. package/dist/lib/env.d.ts +11 -0
  292. package/dist/lib/env.d.ts.map +1 -0
  293. package/dist/lib/env.js +12 -0
  294. package/dist/lib/exec.d.ts +32 -0
  295. package/dist/lib/exec.d.ts.map +1 -0
  296. package/dist/lib/exec.js +54 -0
  297. package/dist/lib/format.d.ts +29 -0
  298. package/dist/lib/format.d.ts.map +1 -0
  299. package/dist/lib/format.js +139 -0
  300. package/dist/lib/http/client.d.ts +56 -0
  301. package/dist/lib/http/client.d.ts.map +1 -0
  302. package/dist/lib/http/client.js +160 -0
  303. package/dist/lib/http/index.d.ts +2 -0
  304. package/dist/lib/http/index.d.ts.map +1 -0
  305. package/dist/lib/http/index.js +1 -0
  306. package/dist/lib/identities/index.d.ts +77 -0
  307. package/dist/lib/identities/index.d.ts.map +1 -0
  308. package/dist/lib/identities/index.js +190 -0
  309. package/dist/lib/machine.d.ts +19 -0
  310. package/dist/lib/machine.d.ts.map +1 -0
  311. package/dist/lib/machine.js +61 -0
  312. package/dist/lib/presence.d.ts +48 -0
  313. package/dist/lib/presence.d.ts.map +1 -0
  314. package/dist/lib/presence.js +123 -0
  315. package/dist/lib/readability/client.d.ts +32 -0
  316. package/dist/lib/readability/client.d.ts.map +1 -0
  317. package/dist/lib/readability/client.js +119 -0
  318. package/dist/lib/readability/index.d.ts +2 -0
  319. package/dist/lib/readability/index.d.ts.map +1 -0
  320. package/dist/lib/readability/index.js +1 -0
  321. package/dist/lib/scratch/index.d.ts +74 -0
  322. package/dist/lib/scratch/index.d.ts.map +1 -0
  323. package/dist/lib/scratch/index.js +393 -0
  324. package/dist/lib/tunnel/gate.d.ts +12 -0
  325. package/dist/lib/tunnel/gate.d.ts.map +1 -0
  326. package/dist/lib/tunnel/gate.js +101 -0
  327. package/dist/lib/tunnel/state.d.ts +34 -0
  328. package/dist/lib/tunnel/state.d.ts.map +1 -0
  329. package/dist/lib/tunnel/state.js +132 -0
  330. package/package.json +160 -8
  331. package/schemas/.gitkeep +0 -0
  332. package/schemas/config.schema.json +109 -0
  333. package/src/cli.ts +22 -0
  334. package/src/commander.ts +242 -0
  335. package/src/commands/.gitkeep +0 -0
  336. package/src/commands/agents.ts +4567 -0
  337. package/src/commands/backup.ts +305 -0
  338. package/src/commands/browse-ai.ts +198 -0
  339. package/src/commands/browse.ts +849 -0
  340. package/src/commands/callers.ts +363 -0
  341. package/src/commands/completion.ts +193 -0
  342. package/src/commands/config-get.ts +161 -0
  343. package/src/commands/context.ts +209 -0
  344. package/src/commands/cookies.ts +198 -0
  345. package/src/commands/docs.ts +174 -0
  346. package/src/commands/doctor.ts +231 -0
  347. package/src/commands/edit-batch.ts +233 -0
  348. package/src/commands/eml.ts +519 -0
  349. package/src/commands/env.ts +254 -0
  350. package/src/commands/fetch.ts +136 -0
  351. package/src/commands/file-history.ts +202 -0
  352. package/src/commands/grep.ts +371 -0
  353. package/src/commands/init.ts +335 -0
  354. package/src/commands/outline.ts +564 -0
  355. package/src/commands/presence.ts +152 -0
  356. package/src/commands/read.ts +64 -0
  357. package/src/commands/scratch.ts +445 -0
  358. package/src/commands/session.ts +187 -0
  359. package/src/commands/sync.ts +306 -0
  360. package/src/commands/toc.ts +218 -0
  361. package/src/commands/tokens.ts +79 -0
  362. package/src/commands/tunnel.ts +633 -0
  363. package/src/commands/uninstall.ts +144 -0
  364. package/src/commands/web.ts +193 -0
  365. package/src/core/agents/canonical-emit.ts +77 -0
  366. package/src/core/agents/cli-emit.ts +64 -0
  367. package/src/core/agents/cli.ts +838 -0
  368. package/src/core/agents/codex-replay.ts +163 -0
  369. package/src/core/agents/coord-client.ts +249 -0
  370. package/src/core/agents/events/consume.ts +196 -0
  371. package/src/core/agents/events/emit.ts +108 -0
  372. package/src/core/agents/events/ulid.ts +51 -0
  373. package/src/core/agents/index.ts +14 -0
  374. package/src/core/agents/paths.ts +16 -0
  375. package/src/core/agents/render/prompt-context.ts +401 -0
  376. package/src/core/agents/render/session-context.ts +341 -0
  377. package/src/core/agents/rules/claim-conflict.ts +282 -0
  378. package/src/core/agents/rules/commit-conflict.ts +303 -0
  379. package/src/core/agents/rules/stop-hook.ts +229 -0
  380. package/src/core/agents/session-events.ts +228 -0
  381. package/src/core/agents/state/activity-log.ts +33 -0
  382. package/src/core/agents/state/council.ts +265 -0
  383. package/src/core/agents/state/heartbeat-projector.ts +488 -0
  384. package/src/core/agents/state/heartbeat-writer.ts +333 -0
  385. package/src/core/agents/state/names.ts +399 -0
  386. package/src/core/agents/state/pidmap.ts +38 -0
  387. package/src/core/agents/state/scratch.ts +121 -0
  388. package/src/core/agents/state/shell-mutation.ts +44 -0
  389. package/src/core/agents/state/stale-sweep.ts +190 -0
  390. package/src/core/config.ts +111 -0
  391. package/src/core/hooks/cli.ts +1247 -0
  392. package/src/core/hooks/effects/image-capture.ts +330 -0
  393. package/src/core/hooks/effects/index.ts +210 -0
  394. package/src/core/hooks/events/emit.ts +120 -0
  395. package/src/core/hooks/events/schema.ts +430 -0
  396. package/src/core/hooks/events/ulid.ts +51 -0
  397. package/src/core/hooks/harness/detect.ts +30 -0
  398. package/src/core/hooks/harness/events.ts +102 -0
  399. package/src/core/hooks/harness/output.ts +100 -0
  400. package/src/core/hooks/harness/parse.ts +180 -0
  401. package/src/core/hooks/index.ts +16 -0
  402. package/src/core/hooks/resolve/anchor.ts +51 -0
  403. package/src/core/hooks/resolve/coord-root.ts +25 -0
  404. package/src/core/hooks/resolve/intent.ts +89 -0
  405. package/src/core/hooks/resolve/owner.ts +140 -0
  406. package/src/core/hooks/resolve/transcript.ts +72 -0
  407. package/src/hooks/.gitkeep +0 -0
  408. package/src/index.ts +15 -0
  409. package/src/lib/agent-browser/client.ts +239 -0
  410. package/src/lib/agent-browser/index.ts +1 -0
  411. package/src/lib/browser/client.ts +449 -0
  412. package/src/lib/browser/dev-overlay.ts +207 -0
  413. package/src/lib/browser/index.ts +24 -0
  414. package/src/lib/browser/layout.ts +288 -0
  415. package/src/lib/browser/visibility.ts +419 -0
  416. package/src/lib/browser/visual-diff.ts +150 -0
  417. package/src/lib/completion/bash.ts +291 -0
  418. package/src/lib/completion/fish.ts +134 -0
  419. package/src/lib/completion/index.ts +10 -0
  420. package/src/lib/completion/walk.ts +184 -0
  421. package/src/lib/completion/zsh.ts +262 -0
  422. package/src/lib/context/index.ts +386 -0
  423. package/src/lib/cookies/client.ts +301 -0
  424. package/src/lib/cookies/index.ts +13 -0
  425. package/src/lib/council/index.ts +803 -0
  426. package/src/lib/docs-index.ts +216 -0
  427. package/src/lib/docs-lint.ts +413 -0
  428. package/src/lib/docs-sweep.ts +348 -0
  429. package/src/lib/docs.ts +199 -0
  430. package/src/lib/env.ts +12 -0
  431. package/src/lib/exec.ts +74 -0
  432. package/src/lib/format.ts +147 -0
  433. package/src/lib/http/client.ts +211 -0
  434. package/src/lib/http/index.ts +1 -0
  435. package/src/lib/identities/index.ts +210 -0
  436. package/src/lib/machine.ts +61 -0
  437. package/src/lib/presence.ts +154 -0
  438. package/src/lib/readability/client.ts +156 -0
  439. package/src/lib/readability/index.ts +5 -0
  440. package/src/lib/readability/turndown-plugin-gfm.d.ts +10 -0
  441. package/src/lib/scratch/index.ts +470 -0
  442. package/src/lib/tunnel/gate.ts +113 -0
  443. package/src/lib/tunnel/state.ts +167 -0
  444. package/src/web/.gitkeep +0 -0
  445. package/index.js +0 -1
@@ -0,0 +1,140 @@
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { coordEnv } from "../../../lib/env.js";
4
+ /**
5
+ * Resolve the canonical `instance_id` for the current hook invocation.
6
+ *
7
+ * Precedence:
8
+ *
9
+ * 1. `HARNERY_AGENT_COORD_OWNER` env var. Set by harness adapters when they know
10
+ * the owner identity at spawn time (Codex's apply_patch tool path uses
11
+ * this).
12
+ * 2. Hook payload fields, in order: `agent_id` → `subagent_id` →
13
+ * `session_id` → `conversation_id`. agent_id wins for CC subagent
14
+ * events; session_id is the parent-shape default.
15
+ * 3. PID-map lookup at `.harnery/pid-map/<pid>` for our own pid, then ppid
16
+ * chain (up to 20 hops).
17
+ *
18
+ * Returns null when nothing resolves. Callers must treat null as "no owner"
19
+ * and skip the event (Phase 2 fail-safe; Phase 3 will mint a temporary owner
20
+ * for orphan events).
21
+ */
22
+ export function resolveOwner(opts) {
23
+ const env = coordEnv("AGENT_COORD_OWNER");
24
+ if (env && env.length > 0) {
25
+ return { instance_id: env, source: "env" };
26
+ }
27
+ if (opts.payload) {
28
+ for (const key of ["agent_id", "subagent_id", "session_id", "conversation_id"]) {
29
+ const v = opts.payload[key];
30
+ if (typeof v === "string" && v.length > 0) {
31
+ return { instance_id: v, source: "payload" };
32
+ }
33
+ }
34
+ }
35
+ // Pid-map ancestor walk. Start at own pid (the bash wrapper's bun child),
36
+ // walk up through ppids. The pid-map is stamped keyed by the harness PID, so
37
+ // we'll usually find it 1-3 hops up.
38
+ const pidmap = join(opts.coordRoot, ".harnery", "pid-map");
39
+ if (existsSync(pidmap)) {
40
+ let pid = process.pid;
41
+ let hops = 0;
42
+ while (hops < 20) {
43
+ const file = join(pidmap, String(pid));
44
+ if (existsSync(file)) {
45
+ try {
46
+ const row = readFileSync(file, "utf8").trim();
47
+ // Row shape: "<instance_id>" or "<instance_id>\t<platform>"
48
+ const owner = row.split("\t")[0];
49
+ if (owner && owner.length > 0) {
50
+ return {
51
+ instance_id: owner,
52
+ source: hops === 0 ? "pidmap-self" : "pidmap-ancestor",
53
+ };
54
+ }
55
+ }
56
+ catch {
57
+ /* keep walking */
58
+ }
59
+ }
60
+ const ppid = readPpid(pid);
61
+ if (!ppid || ppid === 0 || ppid === 1)
62
+ break;
63
+ pid = ppid;
64
+ hops++;
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ function readPpid(pid) {
70
+ // Linux/WSL: /proc/<pid>/status carries `PPid:`. Falls back to null on
71
+ // macOS or any read failure; ancestor walk just terminates.
72
+ try {
73
+ const status = readFileSync(`/proc/${pid}/status`, "utf8");
74
+ for (const line of status.split("\n")) {
75
+ if (line.startsWith("PPid:")) {
76
+ const n = Number(line.split(/\s+/)[1]);
77
+ return Number.isFinite(n) ? n : null;
78
+ }
79
+ }
80
+ }
81
+ catch {
82
+ /* fallthrough */
83
+ }
84
+ return null;
85
+ }
86
+ /**
87
+ * Find the parent owner for a subagent invocation. The per-shell marker at
88
+ * `.harnery/shells/<pid>` is set by `sub-agent-start` and removed by
89
+ * `sub-agent-stop`.
90
+ *
91
+ * Phase 2 stub: the marker file isn't written yet, so we return null in most
92
+ * cases. Phase 2 callers can pass through.
93
+ */
94
+ export function readShellMarker(coordRoot, pid) {
95
+ const path = join(coordRoot, ".harnery", "shells", String(pid));
96
+ if (!existsSync(path))
97
+ return null;
98
+ try {
99
+ return readFileSync(path, "utf8").trim() || null;
100
+ }
101
+ catch {
102
+ return null;
103
+ }
104
+ }
105
+ /** Read the heartbeat-recorded `agent_id` for an owner if it exists. */
106
+ export function readAgentIdForOwner(coordRoot, instanceId) {
107
+ const path = join(coordRoot, ".harnery", "active", `${instanceId}.json`);
108
+ if (!existsSync(path))
109
+ return null;
110
+ try {
111
+ const body = readFileSync(path, "utf8");
112
+ const data = JSON.parse(body);
113
+ return data.agent_id ?? null;
114
+ }
115
+ catch {
116
+ return null;
117
+ }
118
+ }
119
+ /** Diagnostic: list of pid-map entries (for debugging). */
120
+ export function listPidmap(coordRoot) {
121
+ const dir = join(coordRoot, ".harnery", "pid-map");
122
+ if (!existsSync(dir))
123
+ return [];
124
+ const out = [];
125
+ for (const f of readdirSync(dir)) {
126
+ const pid = Number(f);
127
+ if (!Number.isFinite(pid))
128
+ continue;
129
+ try {
130
+ const row = readFileSync(join(dir, f), "utf8").trim();
131
+ const owner = row.split("\t")[0];
132
+ if (owner)
133
+ out.push({ pid, owner });
134
+ }
135
+ catch {
136
+ /* skip */
137
+ }
138
+ }
139
+ return out;
140
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Scan a CC-style JSONL transcript for the `┌─ agent-` status-box prefix in
3
+ * the most-recent assistant turn. Used by `turn.stop` events to populate
4
+ * `status_box_present`.
5
+ *
6
+ * Cheap by default: caps the read at 256KB tailed from the file, since the
7
+ * status box (if present) is always near the end of the most-recent turn.
8
+ * Phase 2 doesn't try to fight the flush race: if the last assistant block
9
+ * hasn't been written yet at Stop-hook time, status_box_present is `false`
10
+ * and Phase 5 verdict path catches the race via a single retry.
11
+ */
12
+ export declare function scanStatusBoxPresent(transcriptPath: string | undefined): boolean;
13
+ /**
14
+ * Resolve the agent's model from a CC-style JSONL transcript by reading the
15
+ * most-recent assistant message's `message.model`. Claude Code's SessionStart
16
+ * payload omits `model` (Codex + Cursor supply it directly), so this is the
17
+ * fallback that lets `session.start` / `turn.stop` populate the heartbeat's
18
+ * model field once the transcript has at least one assistant turn.
19
+ *
20
+ * Tail-reads the same 256KB window as the status-box scan and walks lines from
21
+ * the end, returning the first real model id found. Synthetic placeholders
22
+ * (`<synthetic>`) and empty values are skipped. Returns undefined when the
23
+ * transcript is missing/empty (e.g. a fresh session's first SessionStart).
24
+ */
25
+ export declare function scanTranscriptModel(transcriptPath: string | undefined): string | undefined;
26
+ //# sourceMappingURL=transcript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/resolve/transcript.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAOhF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAsB1F"}
@@ -0,0 +1,73 @@
1
+ import { existsSync, statSync } from "node:fs";
2
+ /**
3
+ * Scan a CC-style JSONL transcript for the `┌─ agent-` status-box prefix in
4
+ * the most-recent assistant turn. Used by `turn.stop` events to populate
5
+ * `status_box_present`.
6
+ *
7
+ * Cheap by default: caps the read at 256KB tailed from the file, since the
8
+ * status box (if present) is always near the end of the most-recent turn.
9
+ * Phase 2 doesn't try to fight the flush race: if the last assistant block
10
+ * hasn't been written yet at Stop-hook time, status_box_present is `false`
11
+ * and Phase 5 verdict path catches the race via a single retry.
12
+ */
13
+ export function scanStatusBoxPresent(transcriptPath) {
14
+ if (!transcriptPath || !existsSync(transcriptPath))
15
+ return false;
16
+ const text = tailText(transcriptPath);
17
+ if (text === undefined)
18
+ return false;
19
+ // The box is rendered as a text content block by the assistant; we look
20
+ // for the prefix on any line of the trailing window.
21
+ return text.includes("┌─ agent-");
22
+ }
23
+ /**
24
+ * Resolve the agent's model from a CC-style JSONL transcript by reading the
25
+ * most-recent assistant message's `message.model`. Claude Code's SessionStart
26
+ * payload omits `model` (Codex + Cursor supply it directly), so this is the
27
+ * fallback that lets `session.start` / `turn.stop` populate the heartbeat's
28
+ * model field once the transcript has at least one assistant turn.
29
+ *
30
+ * Tail-reads the same 256KB window as the status-box scan and walks lines from
31
+ * the end, returning the first real model id found. Synthetic placeholders
32
+ * (`<synthetic>`) and empty values are skipped. Returns undefined when the
33
+ * transcript is missing/empty (e.g. a fresh session's first SessionStart).
34
+ */
35
+ export function scanTranscriptModel(transcriptPath) {
36
+ if (!transcriptPath || !existsSync(transcriptPath))
37
+ return undefined;
38
+ const text = tailText(transcriptPath);
39
+ if (!text)
40
+ return undefined;
41
+ const lines = text.split("\n");
42
+ for (let i = lines.length - 1; i >= 0; i--) {
43
+ const line = lines[i]?.trim();
44
+ if (!line?.includes('"model"'))
45
+ continue;
46
+ try {
47
+ const obj = JSON.parse(line);
48
+ const model = obj.message?.model ?? obj.model;
49
+ if (typeof model === "string" && model.length > 0 && !model.startsWith("<")) {
50
+ return model;
51
+ }
52
+ }
53
+ catch {
54
+ // Partial/truncated first line of the tail window; skip it.
55
+ }
56
+ }
57
+ return undefined;
58
+ }
59
+ /** Tail-read up to 256KB from the end of a file as UTF-8, or undefined on error. */
60
+ function tailText(path) {
61
+ try {
62
+ const size = statSync(path).size;
63
+ const start = Math.max(0, size - 256 * 1024);
64
+ const fd = require("node:fs").openSync(path, "r");
65
+ const buf = Buffer.alloc(size - start);
66
+ require("node:fs").readSync(fd, buf, 0, buf.length, start);
67
+ require("node:fs").closeSync(fd);
68
+ return buf.toString("utf8");
69
+ }
70
+ catch {
71
+ return undefined;
72
+ }
73
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Public library entry. Re-exports the harn-able surface for consumers that
3
+ * import harnery as a library rather than calling the CLI.
4
+ *
5
+ * Examples of intended consumption:
6
+ * import { createHarneryProgram } from 'harnery'; // CLI composition
7
+ * import { evaluateClaim } from 'harnery/core/agents'; // verdict rule directly
8
+ * import type { Heartbeat } from 'harnery/core/agents'; // schema types
9
+ *
10
+ * Heavy modules (web UI, hook scripts) are not re-exported from here; they're
11
+ * reachable via their own subpath entries in package.json#exports.
12
+ */
13
+ export type { HarneryContextOpts, HarneryProgramContext } from "./commander.js";
14
+ export { createHarneryProgram } from "./commander.js";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Public library entry. Re-exports the harn-able surface for consumers that
3
+ * import harnery as a library rather than calling the CLI.
4
+ *
5
+ * Examples of intended consumption:
6
+ * import { createHarneryProgram } from 'harnery'; // CLI composition
7
+ * import { evaluateClaim } from 'harnery/core/agents'; // verdict rule directly
8
+ * import type { Heartbeat } from 'harnery/core/agents'; // schema types
9
+ *
10
+ * Heavy modules (web UI, hook scripts) are not re-exported from here; they're
11
+ * reachable via their own subpath entries in package.json#exports.
12
+ */
13
+ export { createHarneryProgram } from "./commander.js";
@@ -0,0 +1,99 @@
1
+ import { type CookieJar } from "../cookies/index.js";
2
+ /**
3
+ * Thin wrapper over Vercel Labs' `agent-browser` Rust CLI.
4
+ *
5
+ * agent-browser is a process that wraps a managed Chrome for Testing
6
+ * binary and exposes verbs over its own daemon (state persists across
7
+ * invocations within a shell). This wrapper exec's the binary; it does
8
+ * **not** manage the daemon itself.
9
+ *
10
+ * Optional cookie-jar integration: if a CookieJar is passed in the
11
+ * options, the wrapper will write the jar contents to a temp state file
12
+ * and `state load` it before any nav, then `cookies get` and merge the
13
+ * result back into the jar after work is done. Cookies are best-effort:
14
+ * the wrapper never fails because a load/save round-trip blew up.
15
+ *
16
+ * Canonical for `harn browse-ai` (dev side); ready to be the shared core of
17
+ * the agent-side `browse` wrapper (sandbox side) when that wrapper gets refactored.
18
+ */
19
+ export interface AgentBrowserOptions {
20
+ /** Override the binary path. Default: looks up `agent-browser` on PATH. */
21
+ binary?: string;
22
+ /** Cookie jar for cross-tool sharing. Pass `null` to skip. */
23
+ jar?: CookieJar | null;
24
+ /** Default per-call timeout in ms. Default 60000. */
25
+ timeoutMs?: number;
26
+ /** Extra env vars to merge into every spawn. */
27
+ env?: Record<string, string>;
28
+ /**
29
+ * Path used as the `state load` source when seeding cookies into the
30
+ * agent-browser session. Defaults to a tmp file derived from the jar.
31
+ */
32
+ stateFilePath?: string;
33
+ }
34
+ export interface ExecResult {
35
+ stdout: string;
36
+ stderr: string;
37
+ ok: boolean;
38
+ exitCode: number | null;
39
+ }
40
+ export declare class AgentBrowser {
41
+ private readonly opts;
42
+ private cookiesSeeded;
43
+ constructor(opts?: AgentBrowserOptions);
44
+ /**
45
+ * Run an `agent-browser` subcommand. Returns a structured result.
46
+ * Throws only on spawn failure (e.g., binary not found); non-zero exit
47
+ * returns ok=false.
48
+ */
49
+ exec(args: string[], timeoutMs?: number): ExecResult;
50
+ /**
51
+ * Same as `exec` but throws on non-zero exit code, with stderr in the
52
+ * error message. Use when the caller can't recover from a failure.
53
+ */
54
+ execOrThrow(args: string[], timeoutMs?: number): ExecResult;
55
+ /**
56
+ * Seed the jar's cookies into the agent-browser session via `state load`.
57
+ * Called automatically by `open()`. Safe to call multiple times; only
58
+ * the first call does work.
59
+ */
60
+ seedCookies(): void;
61
+ open(url: string, timeoutMs?: number): ExecResult;
62
+ snapshot(opts?: {
63
+ interactive?: boolean;
64
+ }): string;
65
+ screenshot(path: string, opts?: {
66
+ full?: boolean;
67
+ annotate?: boolean;
68
+ }): void;
69
+ click(refOrSelector: string): ExecResult;
70
+ fill(refOrSelector: string, value: string): ExecResult;
71
+ press(key: string): ExecResult;
72
+ wait(selectorOrMs: string): ExecResult;
73
+ evaluate(script: string): string;
74
+ /**
75
+ * Run a semicolon-separated batch of agent-browser sub-commands in a
76
+ * single session. Each step is exec'd with the same daemon, so state
77
+ * persists. Returns one ExecResult per step in order.
78
+ */
79
+ batch(steps: string[]): ExecResult[];
80
+ /** Start HAR recording. Pair with `harStop`. */
81
+ harStart(path: string): ExecResult;
82
+ /** Stop HAR recording. Returns the same result for symmetry with start. */
83
+ harStop(path: string): ExecResult;
84
+ /**
85
+ * Pull cookies out of the agent-browser session via `cookies get --json`,
86
+ * merge them into the jar (if one was provided), and persist. Best-effort:
87
+ * a parse failure or missing jar returns 0 without raising.
88
+ */
89
+ syncCookiesToJar(): {
90
+ saved: number;
91
+ };
92
+ /**
93
+ * Some shell environments leak XDG_CONFIG_HOME into Chrome's crashpad
94
+ * lookup, which can cause SIGTRAP if the path is read-only (e.g. in
95
+ * containerized sandbox environments). Strip it here defensively.
96
+ */
97
+ private scrubEnv;
98
+ }
99
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/agent-browser/client.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,SAAS,EAIf,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,WAAW,mBAAmB;IAClC,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,GAAG,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IACvB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAID,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;IAC3C,OAAO,CAAC,aAAa,CAAS;gBAElB,IAAI,GAAE,mBAAwB;IAI1C;;;;OAIG;IACH,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU;IAyBpD;;;OAGG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU;IAc3D;;;;OAIG;IACH,WAAW,IAAI,IAAI;IAwBnB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,UAAU;IAKjD,QAAQ,CAAC,IAAI,GAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,MAAM;IAMtD,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,IAAI;IAQjF,KAAK,CAAC,aAAa,EAAE,MAAM,GAAG,UAAU;IAIxC,IAAI,CAAC,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU;IAItD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;IAI9B,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU;IAItC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;IAIhC;;;;OAIG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE;IAcpC,gDAAgD;IAChD,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAIlC,2EAA2E;IAC3E,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU;IAIjC;;;;OAIG;IACH,gBAAgB,IAAI;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAkBrC;;;;OAIG;IACH,OAAO,CAAC,QAAQ;CAKjB"}
@@ -0,0 +1,177 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { writeFileSync } from "node:fs";
3
+ import { mergeCookies, } from "../cookies/index.js";
4
+ const DEFAULT_TIMEOUT_MS = 60_000;
5
+ export class AgentBrowser {
6
+ opts;
7
+ cookiesSeeded = false;
8
+ constructor(opts = {}) {
9
+ this.opts = opts;
10
+ }
11
+ /**
12
+ * Run an `agent-browser` subcommand. Returns a structured result.
13
+ * Throws only on spawn failure (e.g., binary not found); non-zero exit
14
+ * returns ok=false.
15
+ */
16
+ exec(args, timeoutMs) {
17
+ const binary = this.opts.binary ?? "agent-browser";
18
+ const env = this.scrubEnv();
19
+ const result = spawnSync(binary, args, {
20
+ timeout: timeoutMs ?? this.opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,
21
+ encoding: "utf8",
22
+ env,
23
+ });
24
+ if (result.error && result.error.code === "ENOENT") {
25
+ throw new Error(`agent-browser binary not found at "${binary}". Install once with:\n curl -fsSL https://github.com/vercel-labs/agent-browser/releases/download/v0.25.4/agent-browser-linux-x64 \\\n -o ~/.local/bin/agent-browser && chmod +x ~/.local/bin/agent-browser\n agent-browser install`);
26
+ }
27
+ if (result.error) {
28
+ throw result.error;
29
+ }
30
+ return {
31
+ stdout: (result.stdout ?? "").toString(),
32
+ stderr: (result.stderr ?? "").toString(),
33
+ ok: result.status === 0,
34
+ exitCode: result.status,
35
+ };
36
+ }
37
+ /**
38
+ * Same as `exec` but throws on non-zero exit code, with stderr in the
39
+ * error message. Use when the caller can't recover from a failure.
40
+ */
41
+ execOrThrow(args, timeoutMs) {
42
+ const result = this.exec(args, timeoutMs);
43
+ if (!result.ok) {
44
+ throw new Error(`agent-browser ${args.join(" ")} failed (exit ${result.exitCode ?? "?"}): ${result.stderr.trim() || result.stdout.trim()}`);
45
+ }
46
+ return result;
47
+ }
48
+ // -------------------------------------------------------------------------
49
+ // High-level verbs
50
+ // -------------------------------------------------------------------------
51
+ /**
52
+ * Seed the jar's cookies into the agent-browser session via `state load`.
53
+ * Called automatically by `open()`. Safe to call multiple times; only
54
+ * the first call does work.
55
+ */
56
+ seedCookies() {
57
+ if (this.cookiesSeeded)
58
+ return;
59
+ if (!this.opts.jar) {
60
+ this.cookiesSeeded = true;
61
+ return;
62
+ }
63
+ try {
64
+ const jarStore = this.opts.jar.load();
65
+ if (jarStore.cookies.length === 0) {
66
+ this.cookiesSeeded = true;
67
+ return;
68
+ }
69
+ const stateFile = this.opts.stateFilePath ?? `/tmp/bp-agent-browser-state-${process.pid}.json`;
70
+ writeFileSync(stateFile, JSON.stringify(jarStore, null, 2));
71
+ this.exec(["state", "load", stateFile], 10_000);
72
+ this.cookiesSeeded = true;
73
+ }
74
+ catch {
75
+ // Cookie seeding is best-effort; never fail the session because
76
+ // the jar couldn't be written/loaded.
77
+ this.cookiesSeeded = true;
78
+ }
79
+ }
80
+ open(url, timeoutMs) {
81
+ this.seedCookies();
82
+ return this.execOrThrow(["open", url], timeoutMs);
83
+ }
84
+ snapshot(opts = {}) {
85
+ const args = ["snapshot"];
86
+ if (opts.interactive)
87
+ args.push("-i");
88
+ return this.execOrThrow(args).stdout.trim();
89
+ }
90
+ screenshot(path, opts = {}) {
91
+ const args = ["screenshot"];
92
+ if (opts.full)
93
+ args.push("--full");
94
+ if (opts.annotate)
95
+ args.push("--annotate");
96
+ args.push(path);
97
+ this.execOrThrow(args);
98
+ }
99
+ click(refOrSelector) {
100
+ return this.execOrThrow(["click", refOrSelector]);
101
+ }
102
+ fill(refOrSelector, value) {
103
+ return this.execOrThrow(["fill", refOrSelector, value]);
104
+ }
105
+ press(key) {
106
+ return this.execOrThrow(["press", key]);
107
+ }
108
+ wait(selectorOrMs) {
109
+ return this.execOrThrow(["wait", selectorOrMs]);
110
+ }
111
+ evaluate(script) {
112
+ return this.execOrThrow(["eval", script]).stdout.trim();
113
+ }
114
+ /**
115
+ * Run a semicolon-separated batch of agent-browser sub-commands in a
116
+ * single session. Each step is exec'd with the same daemon, so state
117
+ * persists. Returns one ExecResult per step in order.
118
+ */
119
+ batch(steps) {
120
+ this.seedCookies();
121
+ const results = [];
122
+ for (const step of steps) {
123
+ const trimmed = step.trim();
124
+ if (!trimmed)
125
+ continue;
126
+ // Naive shell-like splitting; agent-browser's own argv parser handles
127
+ // the actual command; we just split on whitespace for the wrapper.
128
+ const args = trimmed.split(/\s+/);
129
+ results.push(this.exec(args));
130
+ }
131
+ return results;
132
+ }
133
+ /** Start HAR recording. Pair with `harStop`. */
134
+ harStart(path) {
135
+ return this.execOrThrow(["network", "har", "start", path]);
136
+ }
137
+ /** Stop HAR recording. Returns the same result for symmetry with start. */
138
+ harStop(path) {
139
+ return this.execOrThrow(["network", "har", "stop", path]);
140
+ }
141
+ /**
142
+ * Pull cookies out of the agent-browser session via `cookies get --json`,
143
+ * merge them into the jar (if one was provided), and persist. Best-effort:
144
+ * a parse failure or missing jar returns 0 without raising.
145
+ */
146
+ syncCookiesToJar() {
147
+ if (!this.opts.jar)
148
+ return { saved: 0 };
149
+ try {
150
+ const result = this.exec(["cookies", "get", "--json"], 10_000);
151
+ if (!result.ok)
152
+ return { saved: 0 };
153
+ const parsed = JSON.parse(result.stdout);
154
+ const cookies = parsed.data?.cookies ?? parsed.cookies ?? [];
155
+ if (!Array.isArray(cookies) || cookies.length === 0)
156
+ return { saved: 0 };
157
+ const jar = this.opts.jar;
158
+ const store = jar.load();
159
+ const merged = mergeCookies(store, cookies);
160
+ jar.save(merged);
161
+ return { saved: cookies.length };
162
+ }
163
+ catch {
164
+ return { saved: 0 };
165
+ }
166
+ }
167
+ /**
168
+ * Some shell environments leak XDG_CONFIG_HOME into Chrome's crashpad
169
+ * lookup, which can cause SIGTRAP if the path is read-only (e.g. in
170
+ * containerized sandbox environments). Strip it here defensively.
171
+ */
172
+ scrubEnv() {
173
+ const env = { ...process.env, ...this.opts.env };
174
+ env.XDG_CONFIG_HOME = undefined;
175
+ return env;
176
+ }
177
+ }
@@ -0,0 +1,2 @@
1
+ export { AgentBrowser, type AgentBrowserOptions, type ExecResult } from "./client.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/agent-browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1 @@
1
+ export { AgentBrowser } from "./client.js";