harnery 0.0.1 → 0.2.1

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 +509 -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 +39 -0
  316. package/dist/lib/readability/client.d.ts.map +1 -0
  317. package/dist/lib/readability/client.js +121 -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 +583 -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 +169 -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,428 @@
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ import { simpleParser } from "mailparser";
3
+ export function registerEmlCommand(program, emit) {
4
+ program
5
+ .command("eml")
6
+ .description("Parse a Gmail .eml file into a clean chronological markdown thread")
7
+ .argument("<file>", "Path to the .eml file")
8
+ .option("-o, --output <path>", "Write output to a file instead of stdout")
9
+ .option("--format <type>", "Output format: markdown, json", "markdown")
10
+ .option("--headers", "Include full email headers per message")
11
+ .option("--attachments", "List attachment filenames and sizes")
12
+ .action(async (file, opts) => {
13
+ try {
14
+ await handleEml(file, opts, emit);
15
+ }
16
+ catch (err) {
17
+ const msg = err instanceof Error ? err.message : String(err);
18
+ emit.error({ code: "eml_error", message: msg });
19
+ process.exit(1);
20
+ }
21
+ });
22
+ }
23
+ async function handleEml(file, opts, emit) {
24
+ const raw = readFileSync(file);
25
+ const parsed = await simpleParser(raw);
26
+ const messages = extractThread(parsed);
27
+ if (messages.length === 0) {
28
+ emit.error({ code: "no_messages", message: "No messages found in the .eml file." });
29
+ process.exit(1);
30
+ }
31
+ if (opts.format === "json") {
32
+ const rows = messages.map((m, i) => ({
33
+ index: i + 1,
34
+ from: m.from,
35
+ date: m.date?.toISOString() ?? null,
36
+ body: m.body,
37
+ }));
38
+ if (opts.output) {
39
+ writeFileSync(opts.output, JSON.stringify(rows));
40
+ emit.file(opts.output, { messages: messages.length, format: "json" });
41
+ }
42
+ else {
43
+ emit.config({ format: "json" });
44
+ emit.rows(rows);
45
+ }
46
+ return;
47
+ }
48
+ const output = renderMarkdown(parsed, messages, opts);
49
+ if (opts.output) {
50
+ writeFileSync(opts.output, output);
51
+ emit.file(opts.output, { messages: messages.length, format: "markdown" });
52
+ }
53
+ else {
54
+ emit.text(output);
55
+ }
56
+ }
57
+ /**
58
+ * Extract individual messages from the parsed email.
59
+ * Strategy: use HTML body (Gmail quote structure) first, fall back to plain text.
60
+ */
61
+ function extractThread(parsed) {
62
+ if (parsed.html && typeof parsed.html === "string") {
63
+ const messages = extractFromHtml(parsed.html, parsed);
64
+ if (messages.length > 0)
65
+ return messages;
66
+ }
67
+ // Fallback: plain text
68
+ if (parsed.text) {
69
+ return extractFromPlainText(parsed.text, parsed);
70
+ }
71
+ return [];
72
+ }
73
+ /**
74
+ * Parse Gmail's nested HTML quote structure.
75
+ *
76
+ * Gmail wraps each quoted reply in:
77
+ * <div class="gmail_quote">
78
+ * <div class="gmail_attr">On <date>, <name> <<email>> wrote:</div>
79
+ * <blockquote class="gmail_quote">...nested older messages...</blockquote>
80
+ * </div>
81
+ */
82
+ function extractFromHtml(html, parsed) {
83
+ const messages = [];
84
+ // Work with the decoded HTML
85
+ const doc = html;
86
+ // Extract attribution lines and their positions to find message boundaries
87
+ // Pattern: <div ... class="gmail_attr">On ..., ... wrote:<br></div>
88
+ const attrPattern = /class=["']gmail_attr["'][^>]*>([\s\S]*?)<\/div>/gi;
89
+ const attrs = [];
90
+ let match = attrPattern.exec(doc);
91
+ while (match !== null) {
92
+ attrs.push({ text: stripHtml(match[1]), index: match.index });
93
+ match = attrPattern.exec(doc);
94
+ }
95
+ // The top-level message (newest) is before the first gmail_quote
96
+ const firstQuoteIdx = doc.search(/class=["']gmail_quote\s*(gmail_quote_container)?["']/i);
97
+ if (firstQuoteIdx > 0) {
98
+ // Extract the top-level body (everything before the first quote container)
99
+ const topBody = extractBodyBeforeQuote(doc, firstQuoteIdx);
100
+ if (topBody.trim()) {
101
+ messages.push({
102
+ from: formatAddress(parsed.from),
103
+ date: parsed.date ?? null,
104
+ body: topBody,
105
+ });
106
+ }
107
+ }
108
+ else {
109
+ // No quotes - single message
110
+ messages.push({
111
+ from: formatAddress(parsed.from),
112
+ date: parsed.date ?? null,
113
+ body: cleanBody(stripHtml(doc)),
114
+ });
115
+ return messages;
116
+ }
117
+ // Now extract each quoted message using attribution lines
118
+ for (let i = 0; i < attrs.length; i++) {
119
+ const attr = attrs[i];
120
+ const { name, date } = parseAttribution(attr.text);
121
+ // Find the blockquote that follows this attribution
122
+ const afterAttr = doc.indexOf("</div>", attr.index + 10);
123
+ if (afterAttr === -1)
124
+ continue;
125
+ // Find the blockquote content after the attribution div
126
+ const searchRegion = doc.slice(afterAttr, afterAttr + 500);
127
+ const bqStart = searchRegion.indexOf("<blockquote");
128
+ if (bqStart === -1)
129
+ continue;
130
+ const bqStartAbsolute = afterAttr + bqStart;
131
+ const bqContent = extractBlockquoteContent(doc, bqStartAbsolute);
132
+ // The body is everything in this blockquote BEFORE any nested gmail_quote
133
+ const nestedQuoteIdx = bqContent.search(/class=["']gmail_quote["']/i);
134
+ const bodyHtml = nestedQuoteIdx > 0 ? bqContent.slice(0, nestedQuoteIdx) : bqContent;
135
+ // Find the actual start of content (skip the opening blockquote tag)
136
+ const tagEnd = bodyHtml.indexOf(">");
137
+ const content = tagEnd > 0 ? bodyHtml.slice(tagEnd + 1) : bodyHtml;
138
+ const body = cleanBody(stripHtml(content));
139
+ if (body.trim()) {
140
+ messages.push({ from: name, date, body });
141
+ }
142
+ }
143
+ // Reverse: messages are newest-first in the .eml, we want oldest-first
144
+ messages.reverse();
145
+ return messages;
146
+ }
147
+ /**
148
+ * Extract content of a blockquote tag, handling nested blockquotes.
149
+ */
150
+ function extractBlockquoteContent(html, startIdx) {
151
+ let depth = 0;
152
+ let i = startIdx;
153
+ const openTag = /<blockquote/gi;
154
+ const closeTag = /<\/blockquote>/gi;
155
+ // Find the end of the opening tag
156
+ const tagEnd = html.indexOf(">", startIdx);
157
+ if (tagEnd === -1)
158
+ return "";
159
+ i = tagEnd + 1;
160
+ depth = 1;
161
+ while (depth > 0 && i < html.length) {
162
+ openTag.lastIndex = i;
163
+ closeTag.lastIndex = i;
164
+ const nextOpen = openTag.exec(html);
165
+ const nextClose = closeTag.exec(html);
166
+ if (!nextClose)
167
+ break;
168
+ if (nextOpen && nextOpen.index < nextClose.index) {
169
+ depth++;
170
+ i = nextOpen.index + 12;
171
+ }
172
+ else {
173
+ depth--;
174
+ if (depth === 0) {
175
+ return html.slice(tagEnd + 1, nextClose.index);
176
+ }
177
+ i = nextClose.index + 13;
178
+ }
179
+ }
180
+ return html.slice(tagEnd + 1, Math.min(startIdx + 50000, html.length));
181
+ }
182
+ /**
183
+ * Get body content before the first gmail_quote div.
184
+ */
185
+ function extractBodyBeforeQuote(html, quoteIdx) {
186
+ // Walk backwards from the quote to find the containing div
187
+ // The body is typically in the main content area before the quote
188
+ let bodyHtml = html.slice(0, quoteIdx);
189
+ // Remove the outermost container divs and get to the content
190
+ // Look for the last closing tag before the quote div's opening
191
+ const lastDivOpen = bodyHtml.lastIndexOf('<div class="gmail_quote');
192
+ if (lastDivOpen === -1) {
193
+ // Try the simpler approach: strip from after <body> or start of content
194
+ const bodyTag = bodyHtml.indexOf("<body");
195
+ if (bodyTag > 0) {
196
+ const bodyEnd = bodyHtml.indexOf(">", bodyTag);
197
+ bodyHtml = bodyHtml.slice(bodyEnd + 1);
198
+ }
199
+ }
200
+ else {
201
+ bodyHtml = bodyHtml.slice(0, lastDivOpen);
202
+ }
203
+ return cleanBody(stripHtml(bodyHtml));
204
+ }
205
+ /**
206
+ * Fallback: parse plain text thread using "> " quote markers and "On ... wrote:" patterns.
207
+ */
208
+ function extractFromPlainText(text, parsed) {
209
+ const messages = [];
210
+ const wrotePattern = /^On\s+.+\s+wrote:\s*$/m;
211
+ const parts = text.split(wrotePattern);
212
+ if (parts.length <= 1) {
213
+ // No quoted thread found, single message
214
+ messages.push({
215
+ from: formatAddress(parsed.from),
216
+ date: parsed.date ?? null,
217
+ body: cleanBody(text),
218
+ });
219
+ return messages;
220
+ }
221
+ // First part is the newest message body
222
+ messages.push({
223
+ from: formatAddress(parsed.from),
224
+ date: parsed.date ?? null,
225
+ body: cleanBody(parts[0]),
226
+ });
227
+ // Find all "On ... wrote:" lines to get attributions
228
+ const attrMatches = [...text.matchAll(/^(On\s+.+\s+wrote:)\s*$/gm)];
229
+ for (let i = 0; i < attrMatches.length; i++) {
230
+ const attrText = attrMatches[i][1];
231
+ const { name, date } = parseAttribution(attrText);
232
+ // The body is the next part, with ">" prefixes stripped
233
+ if (i + 1 < parts.length) {
234
+ const quotedBody = parts[i + 1]
235
+ .split("\n")
236
+ .map((line) => line.replace(/^>+\s?/, ""))
237
+ .join("\n");
238
+ messages.push({ from: name, date, body: cleanBody(quotedBody) });
239
+ }
240
+ }
241
+ messages.reverse();
242
+ return messages;
243
+ }
244
+ /**
245
+ * Parse an attribution line like "On Fri, Apr 10, 2026 at 9:21 AM Tyler Prins <tyler@...> wrote:"
246
+ */
247
+ function parseAttribution(text) {
248
+ const cleaned = text.replace(/\s+/g, " ").trim();
249
+ // Extract date: "On <date>, <name> ... wrote:"
250
+ // Pattern: On <day>, <month> <day>, <year> at <time> <AM/PM>
251
+ const dateMatch = cleaned.match(/On\s+\w+,\s+(\w+\s+\d{1,2},\s+\d{4})\s+at\s+(\d{1,2}:\d{2})\s*(?:\u202F|\s)*(AM|PM)?/i);
252
+ let date = null;
253
+ if (dateMatch) {
254
+ const dateStr = `${dateMatch[1]} ${dateMatch[2]} ${dateMatch[3] ?? ""}`.trim();
255
+ const parsed = new Date(dateStr);
256
+ if (!Number.isNaN(parsed.getTime())) {
257
+ date = parsed;
258
+ }
259
+ }
260
+ // Extract name: everything after the time and before "wrote:" or before < email >
261
+ const nameMatch = cleaned.match(/(?:AM|PM)\s+(.+?)(?:\s*<[^>]+>)?\s+wrote:/i);
262
+ let name = "Unknown";
263
+ if (nameMatch) {
264
+ name = nameMatch[1].replace(/<[^>]+>/g, "").trim();
265
+ }
266
+ else {
267
+ // Try simpler pattern without AM/PM
268
+ const simpleMatch = cleaned.match(/at\s+[\d:]+\s+(.+?)(?:\s*<[^>]+>)?\s+wrote:/i);
269
+ if (simpleMatch) {
270
+ name = simpleMatch[1].replace(/<[^>]+>/g, "").trim();
271
+ }
272
+ }
273
+ return { name, date };
274
+ }
275
+ /**
276
+ * Strip HTML tags, decode entities, and normalize whitespace.
277
+ */
278
+ function stripHtml(html) {
279
+ let text = html;
280
+ // Replace <br>, <br/>, <br /> with newlines
281
+ text = text.replace(/<br\s*\/?>/gi, "\n");
282
+ // Replace block-level elements with newlines
283
+ text = text.replace(/<\/(p|div|tr|li|h[1-6])>/gi, "\n");
284
+ text = text.replace(/<(p|div|tr|li|h[1-6])\b[^>]*>/gi, "\n");
285
+ // Replace <td> with tab
286
+ text = text.replace(/<\/td>/gi, "\t");
287
+ // Remove all remaining HTML tags
288
+ text = text.replace(/<[^>]+>/g, "");
289
+ // Decode HTML entities
290
+ text = decodeEntities(text);
291
+ // Normalize whitespace (but preserve newlines)
292
+ text = text
293
+ .split("\n")
294
+ .map((line) => line.replace(/[ \t]+/g, " ").trim())
295
+ .join("\n");
296
+ return text;
297
+ }
298
+ /**
299
+ * Decode common HTML entities.
300
+ */
301
+ function decodeEntities(text) {
302
+ const entities = {
303
+ "&amp;": "&",
304
+ "&lt;": "<",
305
+ "&gt;": ">",
306
+ "&quot;": '"',
307
+ "&#39;": "'",
308
+ "&apos;": "'",
309
+ "&nbsp;": " ",
310
+ "&#160;": " ",
311
+ "&ndash;": "-",
312
+ "&mdash;": "-",
313
+ "&laquo;": "<<",
314
+ "&raquo;": ">>",
315
+ "&bull;": "*",
316
+ "&hellip;": "...",
317
+ "&copy;": "(c)",
318
+ "&reg;": "(R)",
319
+ "&trade;": "(TM)",
320
+ };
321
+ let result = text;
322
+ for (const [entity, char] of Object.entries(entities)) {
323
+ result = result.replaceAll(entity, char);
324
+ }
325
+ // Decode numeric entities (&#NNN; and &#xHHH;)
326
+ result = result.replace(/&#(\d+);/g, (_, code) => String.fromCharCode(Number.parseInt(code, 10)));
327
+ result = result.replace(/&#x([0-9a-fA-F]+);/g, (_, code) => String.fromCharCode(Number.parseInt(code, 16)));
328
+ return result;
329
+ }
330
+ /**
331
+ * Clean up message body text.
332
+ */
333
+ function cleanBody(text) {
334
+ let body = text;
335
+ // Remove common email signatures
336
+ const sigPatterns = [
337
+ /^--\s*$/m, // standard sig delimiter
338
+ /^Sent from my (iPhone|iPad|Galaxy|Android|Samsung)/m,
339
+ /^Get Outlook for/m,
340
+ ];
341
+ for (const pattern of sigPatterns) {
342
+ const match = body.match(pattern);
343
+ if (match?.index !== undefined) {
344
+ // Only strip if the signature is in the latter half of the message
345
+ if (match.index > body.length * 0.3) {
346
+ body = body.slice(0, match.index);
347
+ }
348
+ }
349
+ }
350
+ // Remove stray partial HTML tags at the end of the body
351
+ body = body.replace(/<\w+\s*$/, "");
352
+ // Remove any remaining HTML tags that slipped through
353
+ body = body.replace(/<[^>]+>/g, "");
354
+ // Collapse 3+ consecutive newlines into 2
355
+ body = body.replace(/\n{3,}/g, "\n\n");
356
+ return body.trim();
357
+ }
358
+ /**
359
+ * Format an address object from mailparser into "Name <email>" or just "email".
360
+ */
361
+ function formatAddress(addr) {
362
+ if (!addr?.value?.[0])
363
+ return "Unknown";
364
+ const a = addr.value[0];
365
+ if (a.name)
366
+ return a.name;
367
+ return a.address ?? "Unknown";
368
+ }
369
+ /**
370
+ * Render the thread as markdown.
371
+ */
372
+ function renderMarkdown(parsed, messages, opts) {
373
+ const subject = parsed.subject ?? "Untitled Thread";
374
+ const participants = new Map();
375
+ for (const m of messages) {
376
+ participants.set(m.from, true);
377
+ }
378
+ const dates = messages.filter((m) => m.date).map((m) => m.date);
379
+ const minDate = dates.length > 0 ? formatDate(new Date(Math.min(...dates.map((d) => d.getTime())))) : "unknown";
380
+ const maxDate = dates.length > 0 ? formatDate(new Date(Math.max(...dates.map((d) => d.getTime())))) : "unknown";
381
+ const lines = [];
382
+ lines.push(`# ${subject}`);
383
+ lines.push("");
384
+ lines.push(`**Participants:** ${[...participants.keys()].join(", ")}`);
385
+ lines.push(`**Date range:** ${minDate} to ${maxDate}`);
386
+ lines.push(`**Messages:** ${messages.length}`);
387
+ if (opts.attachments && parsed.attachments?.length) {
388
+ lines.push("");
389
+ lines.push("**Attachments:**");
390
+ for (const att of parsed.attachments) {
391
+ const size = att.size ? `(${formatSize(att.size)})` : "";
392
+ lines.push(`- ${att.filename ?? "unnamed"} ${size}`);
393
+ }
394
+ }
395
+ for (let i = 0; i < messages.length; i++) {
396
+ const m = messages[i];
397
+ const dateStr = m.date ? formatDateTime(m.date) : "unknown date";
398
+ lines.push("");
399
+ lines.push("---");
400
+ lines.push("");
401
+ lines.push(`## ${i + 1}. ${m.from} - ${dateStr}`);
402
+ lines.push("");
403
+ lines.push(m.body);
404
+ }
405
+ lines.push("");
406
+ return lines.join("\n");
407
+ }
408
+ function formatDate(d) {
409
+ return d.toISOString().slice(0, 10);
410
+ }
411
+ function formatDateTime(d) {
412
+ return d.toLocaleString("en-US", {
413
+ year: "numeric",
414
+ month: "short",
415
+ day: "numeric",
416
+ hour: "numeric",
417
+ minute: "2-digit",
418
+ hour12: true,
419
+ timeZone: "America/Chicago",
420
+ });
421
+ }
422
+ function formatSize(bytes) {
423
+ if (bytes < 1024)
424
+ return `${bytes}B`;
425
+ if (bytes < 1024 * 1024)
426
+ return `${(bytes / 1024).toFixed(1)}KB`;
427
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
428
+ }
@@ -0,0 +1,4 @@
1
+ import type { Command } from "commander";
2
+ import type { EmitContext, HarneryProgramContext } from "../commander.js";
3
+ export declare function registerEnvCommand(program: Command, emit: EmitContext, context?: HarneryProgramContext): void;
4
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/commands/env.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAqB1E,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CAaN"}
@@ -0,0 +1,201 @@
1
+ import { existsSync, readdirSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ import { exec, sh } from "../lib/exec.js";
4
+ export function registerEnvCommand(program, emit, context) {
5
+ program
6
+ .command("env [section]")
7
+ .description("Show environment status (docker, gcp, bq, node, python, git)")
8
+ .action(async (section) => {
9
+ try {
10
+ await handleEnv(section, emit, context);
11
+ }
12
+ catch (err) {
13
+ const msg = err instanceof Error ? err.message : String(err);
14
+ emit.error({ code: "env_error", message: msg });
15
+ process.exit(1);
16
+ }
17
+ });
18
+ }
19
+ async function handleEnv(section, emit, context) {
20
+ const sections = {
21
+ runtimes: checkRuntimes,
22
+ docker: checkDocker,
23
+ gcp: checkGcp,
24
+ bq: checkBigQuery,
25
+ git: () => checkGit(context),
26
+ };
27
+ if (section) {
28
+ const fn = sections[section];
29
+ if (!fn) {
30
+ emit.error({
31
+ code: "unknown_section",
32
+ message: `Unknown section "${section}". Valid: ${Object.keys(sections).join(", ")}`,
33
+ });
34
+ process.exit(1);
35
+ }
36
+ const checks = await fn();
37
+ emit.data({ ok: true, section, checks: checks.map(toRow) });
38
+ return;
39
+ }
40
+ const results = await Promise.all(Object.entries(sections).map(async ([name, fn]) => ({
41
+ name,
42
+ checks: await fn().catch(() => [
43
+ { label: name, value: "check failed", status: "missing" },
44
+ ]),
45
+ })));
46
+ emit.data({
47
+ ok: true,
48
+ sections: Object.fromEntries(results.map(({ name, checks }) => [name, checks.map(toRow)])),
49
+ });
50
+ }
51
+ function toRow(check) {
52
+ return { label: check.label, value: check.value };
53
+ }
54
+ async function checkRuntimes() {
55
+ const checks = [];
56
+ const [node, bun, python, php] = await Promise.all([
57
+ exec(["node", "--version"]).catch(() => ({ stdout: "", exitCode: 1, stderr: "" })),
58
+ exec(["bun", "--version"]).catch(() => ({ stdout: "", exitCode: 1, stderr: "" })),
59
+ exec(["python3", "--version"]).catch(() => ({ stdout: "", exitCode: 1, stderr: "" })),
60
+ exec(["php", "--version"]).catch(() => ({ stdout: "", exitCode: 1, stderr: "" })),
61
+ ]);
62
+ if (node.exitCode === 0)
63
+ checks.push({ label: "Node.js", value: node.stdout, status: "ok" });
64
+ else
65
+ checks.push({ label: "Node.js", value: "not found", status: "missing" });
66
+ if (bun.exitCode === 0)
67
+ checks.push({ label: "Bun", value: bun.stdout, status: "ok" });
68
+ else
69
+ checks.push({ label: "Bun", value: "not found", status: "missing" });
70
+ if (python.exitCode === 0)
71
+ checks.push({ label: "Python", value: python.stdout.replace("Python ", ""), status: "ok" });
72
+ else
73
+ checks.push({ label: "Python", value: "not found", status: "missing" });
74
+ if (php.exitCode === 0) {
75
+ const ver = php.stdout.split("\n")[0]?.match(/PHP (\S+)/)?.[1] ?? php.stdout;
76
+ checks.push({ label: "PHP", value: ver, status: "ok" });
77
+ }
78
+ else {
79
+ checks.push({ label: "PHP", value: "not found", status: "info" });
80
+ }
81
+ return checks;
82
+ }
83
+ async function checkDocker() {
84
+ const checks = [];
85
+ const dockerVersion = await exec(["docker", "--version"]).catch(() => ({
86
+ stdout: "",
87
+ exitCode: 1,
88
+ stderr: "",
89
+ }));
90
+ if (dockerVersion.exitCode !== 0) {
91
+ return [{ label: "Docker", value: "not installed", status: "missing" }];
92
+ }
93
+ const ver = dockerVersion.stdout.match(/Docker version (\S+)/)?.[1] ?? dockerVersion.stdout;
94
+ checks.push({ label: "Docker", value: ver, status: "ok" });
95
+ const ps = await sh('docker ps --format "{{.Names}}" 2>/dev/null').catch(() => ({
96
+ stdout: "",
97
+ exitCode: 1,
98
+ stderr: "",
99
+ }));
100
+ if (ps.exitCode === 0) {
101
+ const names = ps.stdout.split("\n").filter(Boolean);
102
+ checks.push({
103
+ label: "Containers",
104
+ value: names.length > 0 ? `${names.length} running` : "none running",
105
+ status: names.length > 0 ? "ok" : "info",
106
+ });
107
+ }
108
+ else {
109
+ checks.push({ label: "Containers", value: "docker ps unavailable", status: "info" });
110
+ }
111
+ return checks;
112
+ }
113
+ async function checkGcp() {
114
+ const checks = [];
115
+ const account = await sh("gcloud config get-value account 2>/dev/null").catch(() => ({
116
+ stdout: "",
117
+ exitCode: 1,
118
+ stderr: "",
119
+ }));
120
+ const project = await sh("gcloud config get-value project 2>/dev/null").catch(() => ({
121
+ stdout: "",
122
+ exitCode: 1,
123
+ stderr: "",
124
+ }));
125
+ if (account.exitCode === 0 && account.stdout) {
126
+ checks.push({ label: "GCP Account", value: account.stdout, status: "ok" });
127
+ }
128
+ else {
129
+ checks.push({ label: "GCP Account", value: "not authenticated", status: "missing" });
130
+ }
131
+ if (project.exitCode === 0 && project.stdout) {
132
+ checks.push({ label: "GCP Project", value: project.stdout, status: "ok" });
133
+ }
134
+ else {
135
+ checks.push({ label: "GCP Project", value: "not set", status: "missing" });
136
+ }
137
+ return checks;
138
+ }
139
+ async function checkBigQuery() {
140
+ const checks = [];
141
+ const result = await sh("bq ls --max_results=1 2>/dev/null").catch(() => ({
142
+ stdout: "",
143
+ exitCode: 1,
144
+ stderr: "",
145
+ }));
146
+ if (result.exitCode === 0) {
147
+ checks.push({ label: "BigQuery", value: "connected", status: "ok" });
148
+ }
149
+ else {
150
+ checks.push({ label: "BigQuery", value: "not connected (check GCP auth)", status: "missing" });
151
+ }
152
+ const datasets = await sh("bq ls --format=json --max_results=20 2>/dev/null").catch(() => ({
153
+ stdout: "",
154
+ exitCode: 1,
155
+ stderr: "",
156
+ }));
157
+ if (datasets.exitCode === 0 && datasets.stdout) {
158
+ try {
159
+ const ds = JSON.parse(datasets.stdout);
160
+ const names = ds
161
+ .map((d) => d.datasetReference?.datasetId)
162
+ .filter(Boolean)
163
+ .join(", ");
164
+ if (names)
165
+ checks.push({ label: "Datasets", value: names, status: "info" });
166
+ }
167
+ catch {
168
+ // Ignore parse failures
169
+ }
170
+ }
171
+ return checks;
172
+ }
173
+ async function checkGit(context) {
174
+ const checks = [];
175
+ const cwd = context?.repoRoot ?? process.cwd();
176
+ const branch = await exec(["git", "rev-parse", "--abbrev-ref", "HEAD"], { cwd });
177
+ checks.push({ label: "Branch", value: branch.stdout, status: "info" });
178
+ if (context?.repoRoot && context.submodules && context.submodules.length > 0) {
179
+ const initialized = context.submodules.filter((name) => isSubmoduleInitialized(resolve(context.repoRoot, name)));
180
+ const total = context.submodules.length;
181
+ checks.push({
182
+ label: "Submodules",
183
+ value: `${initialized.length}/${total} initialized`,
184
+ status: initialized.length === total ? "ok" : "warn",
185
+ });
186
+ }
187
+ return checks;
188
+ }
189
+ function isSubmoduleInitialized(dir) {
190
+ if (!existsSync(dir))
191
+ return false;
192
+ try {
193
+ // readdirSync lists every entry (dotfiles included, `.`/`..` excluded):
194
+ // the non-recursive "is this dir non-empty?" check this needs, on both
195
+ // Bun and Node (replaces the Bun-only `new Bun.Glob("*").scanSync`).
196
+ return readdirSync(dir).length > 0;
197
+ }
198
+ catch {
199
+ return false;
200
+ }
201
+ }
@@ -0,0 +1,4 @@
1
+ import type { Command } from "commander";
2
+ import type { EmitContext, HarneryProgramContext } from "../commander.js";
3
+ export declare function registerFetchCommand(program: Command, emit: EmitContext, context?: HarneryProgramContext): void;
4
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../src/commands/fetch.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AA4B1E,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,WAAW,EACjB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,IAAI,CA2BN"}