steroids-cli 0.4.47

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 (395) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +640 -0
  3. package/dist/cli/colors.d.ts +110 -0
  4. package/dist/cli/colors.d.ts.map +1 -0
  5. package/dist/cli/colors.js +228 -0
  6. package/dist/cli/colors.js.map +1 -0
  7. package/dist/cli/env.d.ts +159 -0
  8. package/dist/cli/env.d.ts.map +1 -0
  9. package/dist/cli/env.js +227 -0
  10. package/dist/cli/env.js.map +1 -0
  11. package/dist/cli/errors.d.ts +166 -0
  12. package/dist/cli/errors.d.ts.map +1 -0
  13. package/dist/cli/errors.js +244 -0
  14. package/dist/cli/errors.js.map +1 -0
  15. package/dist/cli/flags.d.ts +75 -0
  16. package/dist/cli/flags.d.ts.map +1 -0
  17. package/dist/cli/flags.js +232 -0
  18. package/dist/cli/flags.js.map +1 -0
  19. package/dist/cli/help.d.ts +97 -0
  20. package/dist/cli/help.d.ts.map +1 -0
  21. package/dist/cli/help.js +275 -0
  22. package/dist/cli/help.js.map +1 -0
  23. package/dist/cli/index.d.ts +13 -0
  24. package/dist/cli/index.d.ts.map +1 -0
  25. package/dist/cli/index.js +29 -0
  26. package/dist/cli/index.js.map +1 -0
  27. package/dist/cli/interactive.d.ts +58 -0
  28. package/dist/cli/interactive.d.ts.map +1 -0
  29. package/dist/cli/interactive.js +127 -0
  30. package/dist/cli/interactive.js.map +1 -0
  31. package/dist/cli/output.d.ts +116 -0
  32. package/dist/cli/output.d.ts.map +1 -0
  33. package/dist/cli/output.js +178 -0
  34. package/dist/cli/output.js.map +1 -0
  35. package/dist/commands/about.d.ts +7 -0
  36. package/dist/commands/about.d.ts.map +1 -0
  37. package/dist/commands/about.js +259 -0
  38. package/dist/commands/about.js.map +1 -0
  39. package/dist/commands/ai.d.ts +6 -0
  40. package/dist/commands/ai.d.ts.map +1 -0
  41. package/dist/commands/ai.js +382 -0
  42. package/dist/commands/ai.js.map +1 -0
  43. package/dist/commands/backup.d.ts +3 -0
  44. package/dist/commands/backup.d.ts.map +1 -0
  45. package/dist/commands/backup.js +528 -0
  46. package/dist/commands/backup.js.map +1 -0
  47. package/dist/commands/completion.d.ts +3 -0
  48. package/dist/commands/completion.d.ts.map +1 -0
  49. package/dist/commands/completion.js +405 -0
  50. package/dist/commands/completion.js.map +1 -0
  51. package/dist/commands/config.d.ts +3 -0
  52. package/dist/commands/config.d.ts.map +1 -0
  53. package/dist/commands/config.js +665 -0
  54. package/dist/commands/config.js.map +1 -0
  55. package/dist/commands/disputes.d.ts +3 -0
  56. package/dist/commands/disputes.d.ts.map +1 -0
  57. package/dist/commands/disputes.js +499 -0
  58. package/dist/commands/disputes.js.map +1 -0
  59. package/dist/commands/gc.d.ts +3 -0
  60. package/dist/commands/gc.d.ts.map +1 -0
  61. package/dist/commands/gc.js +300 -0
  62. package/dist/commands/gc.js.map +1 -0
  63. package/dist/commands/git.d.ts +3 -0
  64. package/dist/commands/git.d.ts.map +1 -0
  65. package/dist/commands/git.js +458 -0
  66. package/dist/commands/git.js.map +1 -0
  67. package/dist/commands/health.d.ts +3 -0
  68. package/dist/commands/health.d.ts.map +1 -0
  69. package/dist/commands/health.js +604 -0
  70. package/dist/commands/health.js.map +1 -0
  71. package/dist/commands/hooks.d.ts +6 -0
  72. package/dist/commands/hooks.d.ts.map +1 -0
  73. package/dist/commands/hooks.js +529 -0
  74. package/dist/commands/hooks.js.map +1 -0
  75. package/dist/commands/init.d.ts +6 -0
  76. package/dist/commands/init.d.ts.map +1 -0
  77. package/dist/commands/init.js +200 -0
  78. package/dist/commands/init.js.map +1 -0
  79. package/dist/commands/llm.d.ts +7 -0
  80. package/dist/commands/llm.d.ts.map +1 -0
  81. package/dist/commands/llm.js +285 -0
  82. package/dist/commands/llm.js.map +1 -0
  83. package/dist/commands/locks.d.ts +3 -0
  84. package/dist/commands/locks.d.ts.map +1 -0
  85. package/dist/commands/locks.js +431 -0
  86. package/dist/commands/locks.js.map +1 -0
  87. package/dist/commands/logs.d.ts +3 -0
  88. package/dist/commands/logs.d.ts.map +1 -0
  89. package/dist/commands/logs.js +487 -0
  90. package/dist/commands/logs.js.map +1 -0
  91. package/dist/commands/loop-phases.d.ts +11 -0
  92. package/dist/commands/loop-phases.d.ts.map +1 -0
  93. package/dist/commands/loop-phases.js +204 -0
  94. package/dist/commands/loop-phases.js.map +1 -0
  95. package/dist/commands/loop.d.ts +3 -0
  96. package/dist/commands/loop.d.ts.map +1 -0
  97. package/dist/commands/loop.js +396 -0
  98. package/dist/commands/loop.js.map +1 -0
  99. package/dist/commands/projects.d.ts +6 -0
  100. package/dist/commands/projects.d.ts.map +1 -0
  101. package/dist/commands/projects.js +362 -0
  102. package/dist/commands/projects.js.map +1 -0
  103. package/dist/commands/purge.d.ts +3 -0
  104. package/dist/commands/purge.d.ts.map +1 -0
  105. package/dist/commands/purge.js +516 -0
  106. package/dist/commands/purge.js.map +1 -0
  107. package/dist/commands/runners.d.ts +3 -0
  108. package/dist/commands/runners.d.ts.map +1 -0
  109. package/dist/commands/runners.js +1076 -0
  110. package/dist/commands/runners.js.map +1 -0
  111. package/dist/commands/scan.d.ts +3 -0
  112. package/dist/commands/scan.d.ts.map +1 -0
  113. package/dist/commands/scan.js +291 -0
  114. package/dist/commands/scan.js.map +1 -0
  115. package/dist/commands/sections-commands.d.ts +9 -0
  116. package/dist/commands/sections-commands.d.ts.map +1 -0
  117. package/dist/commands/sections-commands.js +282 -0
  118. package/dist/commands/sections-commands.js.map +1 -0
  119. package/dist/commands/sections-graph.d.ts +25 -0
  120. package/dist/commands/sections-graph.d.ts.map +1 -0
  121. package/dist/commands/sections-graph.js +180 -0
  122. package/dist/commands/sections-graph.js.map +1 -0
  123. package/dist/commands/sections.d.ts +3 -0
  124. package/dist/commands/sections.d.ts.map +1 -0
  125. package/dist/commands/sections.js +376 -0
  126. package/dist/commands/sections.js.map +1 -0
  127. package/dist/commands/stats.d.ts +6 -0
  128. package/dist/commands/stats.d.ts.map +1 -0
  129. package/dist/commands/stats.js +324 -0
  130. package/dist/commands/stats.js.map +1 -0
  131. package/dist/commands/tasks.d.ts +3 -0
  132. package/dist/commands/tasks.d.ts.map +1 -0
  133. package/dist/commands/tasks.js +1115 -0
  134. package/dist/commands/tasks.js.map +1 -0
  135. package/dist/commands/web.d.ts +7 -0
  136. package/dist/commands/web.d.ts.map +1 -0
  137. package/dist/commands/web.js +204 -0
  138. package/dist/commands/web.js.map +1 -0
  139. package/dist/config/ai-setup.d.ts +27 -0
  140. package/dist/config/ai-setup.d.ts.map +1 -0
  141. package/dist/config/ai-setup.js +432 -0
  142. package/dist/config/ai-setup.js.map +1 -0
  143. package/dist/config/browser.d.ts +9 -0
  144. package/dist/config/browser.d.ts.map +1 -0
  145. package/dist/config/browser.js +200 -0
  146. package/dist/config/browser.js.map +1 -0
  147. package/dist/config/json-schema.d.ts +28 -0
  148. package/dist/config/json-schema.d.ts.map +1 -0
  149. package/dist/config/json-schema.js +84 -0
  150. package/dist/config/json-schema.js.map +1 -0
  151. package/dist/config/loader.d.ts +152 -0
  152. package/dist/config/loader.d.ts.map +1 -0
  153. package/dist/config/loader.js +270 -0
  154. package/dist/config/loader.js.map +1 -0
  155. package/dist/config/schema.d.ts +34 -0
  156. package/dist/config/schema.d.ts.map +1 -0
  157. package/dist/config/schema.js +437 -0
  158. package/dist/config/schema.js.map +1 -0
  159. package/dist/config/validator.d.ts +32 -0
  160. package/dist/config/validator.d.ts.map +1 -0
  161. package/dist/config/validator.js +187 -0
  162. package/dist/config/validator.js.map +1 -0
  163. package/dist/database/connection.d.ts +35 -0
  164. package/dist/database/connection.d.ts.map +1 -0
  165. package/dist/database/connection.js +208 -0
  166. package/dist/database/connection.js.map +1 -0
  167. package/dist/database/queries.d.ts +218 -0
  168. package/dist/database/queries.d.ts.map +1 -0
  169. package/dist/database/queries.js +613 -0
  170. package/dist/database/queries.js.map +1 -0
  171. package/dist/database/schema.d.ts +8 -0
  172. package/dist/database/schema.d.ts.map +1 -0
  173. package/dist/database/schema.js +160 -0
  174. package/dist/database/schema.js.map +1 -0
  175. package/dist/disputes/behavior.d.ts +106 -0
  176. package/dist/disputes/behavior.d.ts.map +1 -0
  177. package/dist/disputes/behavior.js +150 -0
  178. package/dist/disputes/behavior.js.map +1 -0
  179. package/dist/disputes/create.d.ts +59 -0
  180. package/dist/disputes/create.d.ts.map +1 -0
  181. package/dist/disputes/create.js +222 -0
  182. package/dist/disputes/create.js.map +1 -0
  183. package/dist/disputes/index.d.ts +21 -0
  184. package/dist/disputes/index.d.ts.map +1 -0
  185. package/dist/disputes/index.js +76 -0
  186. package/dist/disputes/index.js.map +1 -0
  187. package/dist/disputes/markdown.d.ts +41 -0
  188. package/dist/disputes/markdown.d.ts.map +1 -0
  189. package/dist/disputes/markdown.js +261 -0
  190. package/dist/disputes/markdown.js.map +1 -0
  191. package/dist/disputes/queries.d.ts +83 -0
  192. package/dist/disputes/queries.d.ts.map +1 -0
  193. package/dist/disputes/queries.js +180 -0
  194. package/dist/disputes/queries.js.map +1 -0
  195. package/dist/disputes/resolve.d.ts +57 -0
  196. package/dist/disputes/resolve.d.ts.map +1 -0
  197. package/dist/disputes/resolve.js +171 -0
  198. package/dist/disputes/resolve.js.map +1 -0
  199. package/dist/disputes/stale.d.ts +98 -0
  200. package/dist/disputes/stale.d.ts.map +1 -0
  201. package/dist/disputes/stale.js +205 -0
  202. package/dist/disputes/stale.js.map +1 -0
  203. package/dist/disputes/types.d.ts +92 -0
  204. package/dist/disputes/types.d.ts.map +1 -0
  205. package/dist/disputes/types.js +100 -0
  206. package/dist/disputes/types.js.map +1 -0
  207. package/dist/git/push.d.ts +26 -0
  208. package/dist/git/push.d.ts.map +1 -0
  209. package/dist/git/push.js +97 -0
  210. package/dist/git/push.js.map +1 -0
  211. package/dist/git/status.d.ts +61 -0
  212. package/dist/git/status.d.ts.map +1 -0
  213. package/dist/git/status.js +251 -0
  214. package/dist/git/status.js.map +1 -0
  215. package/dist/hooks/events.d.ts +72 -0
  216. package/dist/hooks/events.d.ts.map +1 -0
  217. package/dist/hooks/events.js +120 -0
  218. package/dist/hooks/events.js.map +1 -0
  219. package/dist/hooks/index.d.ts +19 -0
  220. package/dist/hooks/index.d.ts.map +1 -0
  221. package/dist/hooks/index.js +48 -0
  222. package/dist/hooks/index.js.map +1 -0
  223. package/dist/hooks/integration.d.ts +69 -0
  224. package/dist/hooks/integration.d.ts.map +1 -0
  225. package/dist/hooks/integration.js +179 -0
  226. package/dist/hooks/integration.js.map +1 -0
  227. package/dist/hooks/merge.d.ts +115 -0
  228. package/dist/hooks/merge.d.ts.map +1 -0
  229. package/dist/hooks/merge.js +161 -0
  230. package/dist/hooks/merge.js.map +1 -0
  231. package/dist/hooks/orchestrator.d.ts +115 -0
  232. package/dist/hooks/orchestrator.d.ts.map +1 -0
  233. package/dist/hooks/orchestrator.js +226 -0
  234. package/dist/hooks/orchestrator.js.map +1 -0
  235. package/dist/hooks/payload.d.ts +294 -0
  236. package/dist/hooks/payload.d.ts.map +1 -0
  237. package/dist/hooks/payload.js +267 -0
  238. package/dist/hooks/payload.js.map +1 -0
  239. package/dist/hooks/script-runner.d.ts +63 -0
  240. package/dist/hooks/script-runner.d.ts.map +1 -0
  241. package/dist/hooks/script-runner.js +221 -0
  242. package/dist/hooks/script-runner.js.map +1 -0
  243. package/dist/hooks/templates.d.ts +104 -0
  244. package/dist/hooks/templates.d.ts.map +1 -0
  245. package/dist/hooks/templates.js +327 -0
  246. package/dist/hooks/templates.js.map +1 -0
  247. package/dist/hooks/webhook-runner.d.ts +69 -0
  248. package/dist/hooks/webhook-runner.d.ts.map +1 -0
  249. package/dist/hooks/webhook-runner.js +208 -0
  250. package/dist/hooks/webhook-runner.js.map +1 -0
  251. package/dist/index.d.ts +7 -0
  252. package/dist/index.d.ts.map +1 -0
  253. package/dist/index.js +281 -0
  254. package/dist/index.js.map +1 -0
  255. package/dist/locking/cleanup.d.ts +70 -0
  256. package/dist/locking/cleanup.d.ts.map +1 -0
  257. package/dist/locking/cleanup.js +157 -0
  258. package/dist/locking/cleanup.js.map +1 -0
  259. package/dist/locking/queries.d.ts +116 -0
  260. package/dist/locking/queries.d.ts.map +1 -0
  261. package/dist/locking/queries.js +255 -0
  262. package/dist/locking/queries.js.map +1 -0
  263. package/dist/locking/section-lock.d.ts +74 -0
  264. package/dist/locking/section-lock.d.ts.map +1 -0
  265. package/dist/locking/section-lock.js +207 -0
  266. package/dist/locking/section-lock.js.map +1 -0
  267. package/dist/locking/task-lock.d.ts +92 -0
  268. package/dist/locking/task-lock.d.ts.map +1 -0
  269. package/dist/locking/task-lock.js +246 -0
  270. package/dist/locking/task-lock.js.map +1 -0
  271. package/dist/migrations/index.d.ts +7 -0
  272. package/dist/migrations/index.d.ts.map +1 -0
  273. package/dist/migrations/index.js +37 -0
  274. package/dist/migrations/index.js.map +1 -0
  275. package/dist/migrations/manifest.d.ts +92 -0
  276. package/dist/migrations/manifest.d.ts.map +1 -0
  277. package/dist/migrations/manifest.js +270 -0
  278. package/dist/migrations/manifest.js.map +1 -0
  279. package/dist/migrations/runner.d.ts +84 -0
  280. package/dist/migrations/runner.d.ts.map +1 -0
  281. package/dist/migrations/runner.js +351 -0
  282. package/dist/migrations/runner.js.map +1 -0
  283. package/dist/orchestrator/coder.d.ts +32 -0
  284. package/dist/orchestrator/coder.d.ts.map +1 -0
  285. package/dist/orchestrator/coder.js +174 -0
  286. package/dist/orchestrator/coder.js.map +1 -0
  287. package/dist/orchestrator/coordinator.d.ts +28 -0
  288. package/dist/orchestrator/coordinator.d.ts.map +1 -0
  289. package/dist/orchestrator/coordinator.js +256 -0
  290. package/dist/orchestrator/coordinator.js.map +1 -0
  291. package/dist/orchestrator/reviewer.d.ts +35 -0
  292. package/dist/orchestrator/reviewer.d.ts.map +1 -0
  293. package/dist/orchestrator/reviewer.js +241 -0
  294. package/dist/orchestrator/reviewer.js.map +1 -0
  295. package/dist/orchestrator/task-selector.d.ts +102 -0
  296. package/dist/orchestrator/task-selector.d.ts.map +1 -0
  297. package/dist/orchestrator/task-selector.js +341 -0
  298. package/dist/orchestrator/task-selector.js.map +1 -0
  299. package/dist/prompts/coder.d.ts +36 -0
  300. package/dist/prompts/coder.d.ts.map +1 -0
  301. package/dist/prompts/coder.js +315 -0
  302. package/dist/prompts/coder.js.map +1 -0
  303. package/dist/prompts/prompt-helpers.d.ts +51 -0
  304. package/dist/prompts/prompt-helpers.d.ts.map +1 -0
  305. package/dist/prompts/prompt-helpers.js +312 -0
  306. package/dist/prompts/prompt-helpers.js.map +1 -0
  307. package/dist/prompts/reviewer.d.ts +40 -0
  308. package/dist/prompts/reviewer.d.ts.map +1 -0
  309. package/dist/prompts/reviewer.js +438 -0
  310. package/dist/prompts/reviewer.js.map +1 -0
  311. package/dist/providers/api-models.d.ts +65 -0
  312. package/dist/providers/api-models.d.ts.map +1 -0
  313. package/dist/providers/api-models.js +323 -0
  314. package/dist/providers/api-models.js.map +1 -0
  315. package/dist/providers/claude.d.ts +53 -0
  316. package/dist/providers/claude.d.ts.map +1 -0
  317. package/dist/providers/claude.js +229 -0
  318. package/dist/providers/claude.js.map +1 -0
  319. package/dist/providers/codex.d.ts +53 -0
  320. package/dist/providers/codex.d.ts.map +1 -0
  321. package/dist/providers/codex.js +214 -0
  322. package/dist/providers/codex.js.map +1 -0
  323. package/dist/providers/gemini.d.ts +58 -0
  324. package/dist/providers/gemini.d.ts.map +1 -0
  325. package/dist/providers/gemini.js +242 -0
  326. package/dist/providers/gemini.js.map +1 -0
  327. package/dist/providers/index.d.ts +13 -0
  328. package/dist/providers/index.d.ts.map +1 -0
  329. package/dist/providers/index.js +49 -0
  330. package/dist/providers/index.js.map +1 -0
  331. package/dist/providers/interface.d.ts +173 -0
  332. package/dist/providers/interface.d.ts.map +1 -0
  333. package/dist/providers/interface.js +96 -0
  334. package/dist/providers/interface.js.map +1 -0
  335. package/dist/providers/invocation-logger.d.ts +114 -0
  336. package/dist/providers/invocation-logger.d.ts.map +1 -0
  337. package/dist/providers/invocation-logger.js +298 -0
  338. package/dist/providers/invocation-logger.js.map +1 -0
  339. package/dist/providers/openai.d.ts +53 -0
  340. package/dist/providers/openai.d.ts.map +1 -0
  341. package/dist/providers/openai.js +232 -0
  342. package/dist/providers/openai.js.map +1 -0
  343. package/dist/providers/registry.d.ts +100 -0
  344. package/dist/providers/registry.d.ts.map +1 -0
  345. package/dist/providers/registry.js +178 -0
  346. package/dist/providers/registry.js.map +1 -0
  347. package/dist/runners/activity-log.d.ts +65 -0
  348. package/dist/runners/activity-log.d.ts.map +1 -0
  349. package/dist/runners/activity-log.js +148 -0
  350. package/dist/runners/activity-log.js.map +1 -0
  351. package/dist/runners/cron.d.ts +26 -0
  352. package/dist/runners/cron.d.ts.map +1 -0
  353. package/dist/runners/cron.js +176 -0
  354. package/dist/runners/cron.js.map +1 -0
  355. package/dist/runners/daemon.d.ts +71 -0
  356. package/dist/runners/daemon.d.ts.map +1 -0
  357. package/dist/runners/daemon.js +245 -0
  358. package/dist/runners/daemon.js.map +1 -0
  359. package/dist/runners/global-db.d.ts +31 -0
  360. package/dist/runners/global-db.d.ts.map +1 -0
  361. package/dist/runners/global-db.js +230 -0
  362. package/dist/runners/global-db.js.map +1 -0
  363. package/dist/runners/hang-detector.d.ts +38 -0
  364. package/dist/runners/hang-detector.d.ts.map +1 -0
  365. package/dist/runners/hang-detector.js +136 -0
  366. package/dist/runners/hang-detector.js.map +1 -0
  367. package/dist/runners/heartbeat.d.ts +39 -0
  368. package/dist/runners/heartbeat.d.ts.map +1 -0
  369. package/dist/runners/heartbeat.js +79 -0
  370. package/dist/runners/heartbeat.js.map +1 -0
  371. package/dist/runners/lock.d.ts +47 -0
  372. package/dist/runners/lock.d.ts.map +1 -0
  373. package/dist/runners/lock.js +150 -0
  374. package/dist/runners/lock.js.map +1 -0
  375. package/dist/runners/orchestrator-loop.d.ts +20 -0
  376. package/dist/runners/orchestrator-loop.d.ts.map +1 -0
  377. package/dist/runners/orchestrator-loop.js +285 -0
  378. package/dist/runners/orchestrator-loop.js.map +1 -0
  379. package/dist/runners/projects.d.ts +96 -0
  380. package/dist/runners/projects.d.ts.map +1 -0
  381. package/dist/runners/projects.js +255 -0
  382. package/dist/runners/projects.js.map +1 -0
  383. package/dist/runners/wakeup.d.ts +34 -0
  384. package/dist/runners/wakeup.d.ts.map +1 -0
  385. package/dist/runners/wakeup.js +291 -0
  386. package/dist/runners/wakeup.js.map +1 -0
  387. package/migrations/001_initial_schema.sql +106 -0
  388. package/migrations/002_add_commit_sha.sql +12 -0
  389. package/migrations/003_add_section_priority.sql +13 -0
  390. package/migrations/004_add_section_dependencies.sql +18 -0
  391. package/migrations/005_add_audit_actor_model.sql +10 -0
  392. package/migrations/006_add_task_invocations.sql +33 -0
  393. package/migrations/007_add_file_anchor.sql +14 -0
  394. package/migrations/manifest.json +62 -0
  395. package/package.json +49 -0
@@ -0,0 +1,1076 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runnersCommand = runnersCommand;
37
+ /**
38
+ * steroids runners - Manage runner daemons
39
+ */
40
+ const node_util_1 = require("node:util");
41
+ const node_child_process_1 = require("node:child_process");
42
+ const fs = __importStar(require("node:fs"));
43
+ const path = __importStar(require("node:path"));
44
+ const os = __importStar(require("node:os"));
45
+ const loader_js_1 = require("../config/loader.js");
46
+ const daemon_js_1 = require("../runners/daemon.js");
47
+ const lock_js_1 = require("../runners/lock.js");
48
+ const wakeup_js_1 = require("../runners/wakeup.js");
49
+ const cron_js_1 = require("../runners/cron.js");
50
+ const connection_js_1 = require("../database/connection.js");
51
+ const queries_js_1 = require("../database/queries.js");
52
+ const node_fs_1 = require("node:fs");
53
+ const node_path_1 = require("node:path");
54
+ const projects_js_1 = require("../runners/projects.js");
55
+ const help_js_1 = require("../cli/help.js");
56
+ const HELP = (0, help_js_1.generateHelp)({
57
+ command: 'runners',
58
+ description: 'Manage background runner daemons for automated task execution',
59
+ details: `Runners are daemon processes that execute the orchestrator loop in the background.
60
+ Each project can have one active runner processing tasks.
61
+ Runners can be started manually or managed automatically via cron.`,
62
+ usage: ['steroids runners <subcommand> [options]'],
63
+ subcommands: [
64
+ { name: 'start', description: 'Start runner daemon (foreground or background)' },
65
+ { name: 'stop', description: 'Stop runner(s) for current or all projects' },
66
+ { name: 'status', description: 'Show runner status for current project' },
67
+ { name: 'list', description: 'List all runners across all projects' },
68
+ { name: 'logs', args: '[pid]', description: 'View daemon crash/output logs' },
69
+ { name: 'wakeup', description: 'Check and restart stale runners' },
70
+ { name: 'cron', args: '<install|uninstall|status>', description: 'Manage cron job for auto-wakeup' },
71
+ ],
72
+ options: [
73
+ { long: 'detach', description: 'Run in background (daemonize) - start subcommand' },
74
+ { long: 'project', description: 'Project path to work on', values: '<path>' },
75
+ { long: 'section', description: 'Focus on specific section only', values: '<id|name>' },
76
+ { long: 'id', description: 'Stop specific runner by ID - stop subcommand', values: '<id>' },
77
+ { long: 'all', description: 'Stop all runners - stop subcommand' },
78
+ { long: 'tree', description: 'Show tree view with projects/runners/tasks - list subcommand' },
79
+ { long: 'tail', description: 'Show last n lines of logs', values: '<n>', default: '50' },
80
+ { long: 'follow', description: 'Follow log output in real-time' },
81
+ { long: 'clear', description: 'Clear all daemon logs' },
82
+ ],
83
+ examples: [
84
+ { command: 'steroids runners start', description: 'Start in foreground' },
85
+ { command: 'steroids runners start --detach', description: 'Start in background' },
86
+ { command: 'steroids runners start --section "Phase 2"', description: 'Focus on specific section' },
87
+ { command: 'steroids runners stop', description: 'Stop runner for current project' },
88
+ { command: 'steroids runners stop --all', description: 'Stop all runners' },
89
+ { command: 'steroids runners status', description: 'Show runner status' },
90
+ { command: 'steroids runners list', description: 'List all runners (all projects)' },
91
+ { command: 'steroids runners list --tree', description: 'Tree view with tasks' },
92
+ { command: 'steroids runners list --json', description: 'JSON output' },
93
+ { command: 'steroids runners logs', description: 'List available logs' },
94
+ { command: 'steroids runners logs 12345', description: 'View logs for PID 12345' },
95
+ { command: 'steroids runners logs --follow', description: 'Follow latest log' },
96
+ { command: 'steroids runners wakeup', description: 'Restart stale runners' },
97
+ { command: 'steroids runners cron install', description: 'Install cron wake-up' },
98
+ { command: 'steroids runners cron status', description: 'Check cron status' },
99
+ ],
100
+ related: [
101
+ { command: 'steroids loop', description: 'Run orchestrator loop manually' },
102
+ { command: 'steroids tasks', description: 'View tasks being processed' },
103
+ ],
104
+ sections: [
105
+ {
106
+ title: 'MULTI-PROJECT',
107
+ content: `Different projects can run runners in parallel (one per project).
108
+ The 'list' command shows runners from ALL registered projects.
109
+ Use 'wakeup' to check if any projects need runners restarted.`,
110
+ },
111
+ ],
112
+ });
113
+ async function runnersCommand(args, flags) {
114
+ if (args.length === 0 || args[0] === '-h' || args[0] === '--help') {
115
+ console.log(HELP);
116
+ return;
117
+ }
118
+ const subcommand = args[0];
119
+ const subArgs = args.slice(1);
120
+ switch (subcommand) {
121
+ case 'start':
122
+ await runStart(subArgs);
123
+ break;
124
+ case 'stop':
125
+ await runStop(subArgs);
126
+ break;
127
+ case 'status':
128
+ await runStatus(subArgs);
129
+ break;
130
+ case 'list':
131
+ await runList(subArgs, flags);
132
+ break;
133
+ case 'logs':
134
+ await runLogs(subArgs);
135
+ break;
136
+ case 'wakeup':
137
+ await runWakeup(subArgs, flags);
138
+ break;
139
+ case 'cron':
140
+ await runCron(subArgs);
141
+ break;
142
+ default:
143
+ console.error(`Unknown subcommand: ${subcommand}`);
144
+ console.log(HELP);
145
+ process.exit(1);
146
+ }
147
+ }
148
+ async function runStart(args) {
149
+ const { values } = (0, node_util_1.parseArgs)({
150
+ args,
151
+ options: {
152
+ help: { type: 'boolean', short: 'h', default: false },
153
+ json: { type: 'boolean', short: 'j', default: false },
154
+ detach: { type: 'boolean', short: 'd', default: false },
155
+ project: { type: 'string', short: 'p' },
156
+ section: { type: 'string' },
157
+ },
158
+ allowPositionals: false,
159
+ });
160
+ if (values.help) {
161
+ console.log(`
162
+ steroids runners start - Start runner daemon
163
+
164
+ USAGE:
165
+ steroids runners start [options]
166
+
167
+ OPTIONS:
168
+ --detach Run in background
169
+ --project <path> Project path
170
+ --section <id|name> Focus on a specific section only
171
+ -j, --json Output as JSON
172
+ -h, --help Show help
173
+ `);
174
+ return;
175
+ }
176
+ // Check if we can start
177
+ // Default to cwd if --project not specified, to ensure proper per-project tracking
178
+ // Always resolve to absolute path for consistent tracking across processes
179
+ const projectPath = path.resolve(values.project ?? process.cwd());
180
+ const check = (0, daemon_js_1.canStartDaemon)(projectPath);
181
+ if (!check.canStart && !check.reason?.includes('zombie')) {
182
+ if (values.json) {
183
+ console.log(JSON.stringify({
184
+ success: false,
185
+ error: check.reason,
186
+ existingPid: check.existingPid,
187
+ }));
188
+ }
189
+ else {
190
+ console.error(`Cannot start: ${check.reason}`);
191
+ if (check.existingPid) {
192
+ console.error(`Existing runner PID: ${check.existingPid}`);
193
+ }
194
+ }
195
+ process.exit(6);
196
+ }
197
+ // Resolve section if --section flag is provided
198
+ let focusedSectionId;
199
+ if (values.section) {
200
+ const sectionInput = values.section;
201
+ const { db, close } = (0, connection_js_1.openDatabase)(projectPath);
202
+ try {
203
+ // Try to resolve by ID (exact or prefix match)
204
+ let section;
205
+ try {
206
+ section = (0, queries_js_1.getSection)(db, sectionInput);
207
+ }
208
+ catch (err) {
209
+ // Handle ambiguous prefix error
210
+ const errorMsg = err instanceof Error ? err.message : String(err);
211
+ if (values.json) {
212
+ console.log(JSON.stringify({ success: false, error: errorMsg }));
213
+ }
214
+ else {
215
+ console.error(`Error: ${errorMsg}`);
216
+ console.error('');
217
+ console.error('Available sections:');
218
+ const sections = (0, queries_js_1.listSections)(db);
219
+ if (sections.length === 0) {
220
+ console.error(' (no sections defined)');
221
+ }
222
+ else {
223
+ for (const s of sections) {
224
+ console.error(` ${s.id.substring(0, 8)} ${s.name}`);
225
+ }
226
+ }
227
+ }
228
+ close();
229
+ process.exit(1);
230
+ }
231
+ // If not found by ID, try by name
232
+ if (!section) {
233
+ section = (0, queries_js_1.getSectionByName)(db, sectionInput);
234
+ }
235
+ if (!section) {
236
+ const errorMsg = `Section not found: ${sectionInput}`;
237
+ if (values.json) {
238
+ console.log(JSON.stringify({ success: false, error: errorMsg }));
239
+ }
240
+ else {
241
+ console.error(`Error: ${errorMsg}`);
242
+ console.error('');
243
+ console.error('Available sections:');
244
+ const sections = (0, queries_js_1.listSections)(db);
245
+ if (sections.length === 0) {
246
+ console.error(' (no sections defined)');
247
+ }
248
+ else {
249
+ for (const s of sections) {
250
+ console.error(` ${s.id.substring(0, 8)} ${s.name}`);
251
+ }
252
+ }
253
+ }
254
+ close();
255
+ process.exit(1);
256
+ }
257
+ // Check if section is skipped (Phase 0.6 feature)
258
+ if (section.skipped === 1) {
259
+ const errorMsg = `Section "${section.name}" is currently skipped`;
260
+ if (values.json) {
261
+ console.log(JSON.stringify({ success: false, error: errorMsg }));
262
+ }
263
+ else {
264
+ console.error(`Error: ${errorMsg}`);
265
+ console.error('');
266
+ console.error(`Run 'steroids sections unskip "${section.name}"' to re-enable it.`);
267
+ }
268
+ close();
269
+ process.exit(1);
270
+ }
271
+ focusedSectionId = section.id;
272
+ }
273
+ finally {
274
+ close();
275
+ }
276
+ }
277
+ if (values.detach) {
278
+ // Spawn detached process - always pass --project for proper tracking
279
+ const spawnArgs = [process.argv[1], 'runners', 'start', '--project', projectPath];
280
+ // Pass --section if specified
281
+ if (values.section) {
282
+ spawnArgs.push('--section', values.section);
283
+ }
284
+ // Check config for daemon logging preference
285
+ const config = (0, loader_js_1.loadConfig)(projectPath);
286
+ const daemonLogsEnabled = config.runners?.daemonLogs !== false;
287
+ let logFile;
288
+ let logFd;
289
+ if (daemonLogsEnabled) {
290
+ // Create logs directory and log file for daemon output
291
+ const logsDir = path.join(os.homedir(), '.steroids', 'runners', 'logs');
292
+ fs.mkdirSync(logsDir, { recursive: true });
293
+ // Use timestamp for now, will rename after we have PID
294
+ const tempLogPath = path.join(logsDir, `daemon-${Date.now()}.log`);
295
+ logFd = fs.openSync(tempLogPath, 'a');
296
+ logFile = tempLogPath;
297
+ }
298
+ const child = (0, node_child_process_1.spawn)(process.execPath, spawnArgs, {
299
+ detached: true,
300
+ stdio: daemonLogsEnabled && logFd !== undefined
301
+ ? ['ignore', logFd, logFd]
302
+ : 'ignore',
303
+ });
304
+ child.unref();
305
+ // Clean up file descriptor and rename log file
306
+ if (logFd !== undefined) {
307
+ fs.closeSync(logFd);
308
+ }
309
+ let finalLogPath;
310
+ if (logFile && child.pid) {
311
+ const logsDir = path.dirname(logFile);
312
+ finalLogPath = path.join(logsDir, `daemon-${child.pid}.log`);
313
+ try {
314
+ fs.renameSync(logFile, finalLogPath);
315
+ }
316
+ catch {
317
+ finalLogPath = logFile; // Keep temp name if rename fails
318
+ }
319
+ }
320
+ if (values.json) {
321
+ console.log(JSON.stringify({
322
+ success: true,
323
+ pid: child.pid,
324
+ detached: true,
325
+ logFile: finalLogPath,
326
+ }));
327
+ }
328
+ else {
329
+ console.log(`Runner started in background (PID: ${child.pid})`);
330
+ if (finalLogPath) {
331
+ console.log(` Log file: ${finalLogPath}`);
332
+ }
333
+ }
334
+ return;
335
+ }
336
+ // Start in foreground
337
+ await (0, daemon_js_1.startDaemon)({ projectPath, sectionId: focusedSectionId });
338
+ }
339
+ async function runStop(args) {
340
+ const { values } = (0, node_util_1.parseArgs)({
341
+ args,
342
+ options: {
343
+ help: { type: 'boolean', short: 'h', default: false },
344
+ json: { type: 'boolean', short: 'j', default: false },
345
+ id: { type: 'string' },
346
+ all: { type: 'boolean', default: false },
347
+ },
348
+ allowPositionals: false,
349
+ });
350
+ if (values.help) {
351
+ console.log(`
352
+ steroids runners stop - Stop runner(s)
353
+
354
+ USAGE:
355
+ steroids runners stop [options]
356
+
357
+ OPTIONS:
358
+ --id <id> Stop specific runner
359
+ --all Stop all runners
360
+ -j, --json Output as JSON
361
+ -h, --help Show help
362
+ `);
363
+ return;
364
+ }
365
+ // Capture stop context for logging
366
+ const stopContext = {
367
+ calledFrom: process.cwd(),
368
+ callerPid: process.pid,
369
+ timestamp: new Date().toISOString(),
370
+ user: process.env.USER || process.env.USERNAME || 'unknown',
371
+ args: {
372
+ id: values.id,
373
+ all: values.all,
374
+ },
375
+ };
376
+ const runners = (0, daemon_js_1.listRunners)();
377
+ let stopped = 0;
378
+ const stoppedRunners = [];
379
+ const runnersToStop = values.id
380
+ ? runners.filter((r) => r.id === values.id || r.id.startsWith(values.id))
381
+ : values.all
382
+ ? runners
383
+ : runners.filter((r) => r.pid === process.pid || r.pid !== null);
384
+ // Log stop action to daemon logs
385
+ const logsDir = path.join(os.homedir(), '.steroids', 'runners', 'logs');
386
+ const stopLogPath = path.join(logsDir, 'stop-audit.log');
387
+ fs.mkdirSync(logsDir, { recursive: true });
388
+ for (const runner of runnersToStop) {
389
+ if (runner.pid && (0, lock_js_1.isProcessAlive)(runner.pid)) {
390
+ try {
391
+ process.kill(runner.pid, 'SIGTERM');
392
+ stopped++;
393
+ stoppedRunners.push({
394
+ id: runner.id,
395
+ pid: runner.pid,
396
+ project: runner.project_path,
397
+ });
398
+ // Log each stop to audit log
399
+ const logEntry = {
400
+ ...stopContext,
401
+ action: 'stop',
402
+ runner: {
403
+ id: runner.id,
404
+ pid: runner.pid,
405
+ project: runner.project_path,
406
+ },
407
+ };
408
+ fs.appendFileSync(stopLogPath, JSON.stringify(logEntry) + '\n');
409
+ }
410
+ catch {
411
+ // Process already dead
412
+ }
413
+ }
414
+ (0, daemon_js_1.unregisterRunner)(runner.id);
415
+ }
416
+ if (values.json) {
417
+ console.log(JSON.stringify({
418
+ success: true,
419
+ stopped,
420
+ stoppedRunners,
421
+ context: stopContext,
422
+ }));
423
+ }
424
+ else {
425
+ console.log(`Stopped ${stopped} runner(s)`);
426
+ if (stopped > 0 && !values.all) {
427
+ console.log(` Called from: ${stopContext.calledFrom}`);
428
+ console.log(` Audit log: ${stopLogPath}`);
429
+ }
430
+ }
431
+ }
432
+ async function runStatus(args) {
433
+ const { values } = (0, node_util_1.parseArgs)({
434
+ args,
435
+ options: {
436
+ help: { type: 'boolean', short: 'h', default: false },
437
+ json: { type: 'boolean', short: 'j', default: false },
438
+ },
439
+ allowPositionals: false,
440
+ });
441
+ if (values.help) {
442
+ console.log(`
443
+ steroids runners status - Show runner status
444
+
445
+ USAGE:
446
+ steroids runners status [options]
447
+
448
+ OPTIONS:
449
+ -j, --json Output as JSON
450
+ -h, --help Show help
451
+ `);
452
+ return;
453
+ }
454
+ const lockStatus = (0, lock_js_1.checkLockStatus)();
455
+ const runners = (0, daemon_js_1.listRunners)();
456
+ const activeRunner = runners.find((r) => r.pid && (0, lock_js_1.isProcessAlive)(r.pid));
457
+ const status = {
458
+ locked: lockStatus.locked,
459
+ lockPid: lockStatus.pid,
460
+ isZombie: lockStatus.isZombie,
461
+ activeRunner: activeRunner
462
+ ? {
463
+ id: activeRunner.id,
464
+ pid: activeRunner.pid,
465
+ status: activeRunner.status,
466
+ project: activeRunner.project_path,
467
+ currentTask: activeRunner.current_task_id,
468
+ heartbeat: activeRunner.heartbeat_at,
469
+ }
470
+ : null,
471
+ totalRunners: runners.length,
472
+ };
473
+ if (values.json) {
474
+ console.log(JSON.stringify(status, null, 2));
475
+ return;
476
+ }
477
+ if (activeRunner) {
478
+ console.log(`Runner Status: ACTIVE`);
479
+ console.log(` ID: ${activeRunner.id}`);
480
+ console.log(` PID: ${activeRunner.pid}`);
481
+ console.log(` Status: ${activeRunner.status}`);
482
+ if (activeRunner.project_path) {
483
+ console.log(` Project: ${activeRunner.project_path}`);
484
+ }
485
+ if (activeRunner.current_task_id) {
486
+ console.log(` Current Task: ${activeRunner.current_task_id}`);
487
+ }
488
+ console.log(` Last Heartbeat: ${activeRunner.heartbeat_at}`);
489
+ }
490
+ else if (lockStatus.isZombie) {
491
+ console.log(`Runner Status: ZOMBIE`);
492
+ console.log(` Lock exists but process (PID: ${lockStatus.pid}) is dead`);
493
+ console.log(` Run 'steroids runners wakeup' to clean up`);
494
+ }
495
+ else {
496
+ console.log(`Runner Status: INACTIVE`);
497
+ console.log(` No runner is currently active`);
498
+ }
499
+ }
500
+ async function runList(args, flags) {
501
+ const { values } = (0, node_util_1.parseArgs)({
502
+ args,
503
+ options: {
504
+ help: { type: 'boolean', short: 'h', default: false },
505
+ tree: { type: 'boolean', short: 't', default: false },
506
+ },
507
+ allowPositionals: false,
508
+ });
509
+ if (values.help || flags.help) {
510
+ console.log(`
511
+ steroids runners list - List all runners
512
+
513
+ USAGE:
514
+ steroids runners list [options]
515
+
516
+ OPTIONS:
517
+ -t, --tree Show tree view with tasks
518
+ -j, --json Output as JSON (global flag)
519
+ -h, --help Show help
520
+ `);
521
+ return;
522
+ }
523
+ // Tree view mode
524
+ if (values.tree) {
525
+ await runListTree(flags.json);
526
+ return;
527
+ }
528
+ const runners = (0, daemon_js_1.listRunners)();
529
+ if (flags.json) {
530
+ // For JSON output, enrich with section names if available
531
+ const enrichedRunners = runners.map((runner) => {
532
+ if (!runner.section_id || !runner.project_path) {
533
+ return runner;
534
+ }
535
+ try {
536
+ const { db, close } = (0, connection_js_1.openDatabase)(runner.project_path);
537
+ try {
538
+ const section = (0, queries_js_1.getSection)(db, runner.section_id);
539
+ return { ...runner, section_name: section?.name };
540
+ }
541
+ finally {
542
+ close();
543
+ }
544
+ }
545
+ catch {
546
+ return runner;
547
+ }
548
+ });
549
+ console.log(JSON.stringify({ runners: enrichedRunners }, null, 2));
550
+ return;
551
+ }
552
+ if (runners.length === 0) {
553
+ console.log('No runners registered');
554
+ return;
555
+ }
556
+ console.log('RUNNERS');
557
+ console.log('─'.repeat(120));
558
+ console.log('ID STATUS PID PROJECT SECTION HEARTBEAT');
559
+ console.log('─'.repeat(120));
560
+ for (const runner of runners) {
561
+ const shortId = runner.id.substring(0, 8);
562
+ const status = runner.status.padEnd(10);
563
+ const pid = (runner.pid?.toString() ?? '-').padEnd(9);
564
+ const project = (runner.project_path ?? '-').substring(0, 30).padEnd(30);
565
+ // Fetch section name if available
566
+ let sectionDisplay = '-';
567
+ if (runner.section_id && runner.project_path) {
568
+ try {
569
+ const { db, close } = (0, connection_js_1.openDatabase)(runner.project_path);
570
+ try {
571
+ const section = (0, queries_js_1.getSection)(db, runner.section_id);
572
+ if (section) {
573
+ sectionDisplay = section.name.substring(0, 30);
574
+ }
575
+ }
576
+ finally {
577
+ close();
578
+ }
579
+ }
580
+ catch {
581
+ // If we can't fetch the section name, just show the ID prefix
582
+ sectionDisplay = runner.section_id.substring(0, 8);
583
+ }
584
+ }
585
+ const section = sectionDisplay.padEnd(30);
586
+ const heartbeat = runner.heartbeat_at.substring(11, 19);
587
+ const alive = runner.pid && (0, lock_js_1.isProcessAlive)(runner.pid) ? '' : ' (dead)';
588
+ console.log(`${shortId} ${status} ${pid} ${project} ${section} ${heartbeat}${alive}`);
589
+ }
590
+ // Check if there are multiple projects
591
+ const uniqueProjects = new Set(runners.map(r => r.project_path).filter(Boolean));
592
+ if (uniqueProjects.size > 1) {
593
+ const currentProject = process.cwd();
594
+ console.log('');
595
+ console.log('─'.repeat(120));
596
+ console.log(`⚠️ MULTI-PROJECT WARNING: ${uniqueProjects.size} different projects have runners.`);
597
+ console.log(` Your current project: ${currentProject}`);
598
+ console.log(' DO NOT modify files in other projects. Each runner works only on its own project.');
599
+ console.log('─'.repeat(120));
600
+ }
601
+ }
602
+ /**
603
+ * Tree view of runners grouped by project with their current tasks
604
+ */
605
+ async function runListTree(json) {
606
+ const runners = (0, daemon_js_1.listRunners)();
607
+ const projects = (0, projects_js_1.getRegisteredProjects)(false);
608
+ const projectMap = new Map();
609
+ // Initialize with all registered projects
610
+ for (const project of projects) {
611
+ projectMap.set(project.path, {
612
+ path: project.path,
613
+ name: project.name || (0, node_path_1.basename)(project.path),
614
+ runners: [],
615
+ activeTasks: [],
616
+ });
617
+ }
618
+ // Add runners to their projects
619
+ for (const runner of runners) {
620
+ const projectPath = runner.project_path;
621
+ if (!projectPath)
622
+ continue;
623
+ if (!projectMap.has(projectPath)) {
624
+ projectMap.set(projectPath, {
625
+ path: projectPath,
626
+ name: (0, node_path_1.basename)(projectPath),
627
+ runners: [],
628
+ activeTasks: [],
629
+ });
630
+ }
631
+ const info = projectMap.get(projectPath);
632
+ info.runners.push(runner);
633
+ }
634
+ // Fetch active tasks for each project
635
+ for (const [projectPath, info] of projectMap) {
636
+ const dbPath = `${projectPath}/.steroids/steroids.db`;
637
+ if (!(0, node_fs_1.existsSync)(dbPath))
638
+ continue;
639
+ try {
640
+ const { db, close } = (0, connection_js_1.openDatabase)(projectPath);
641
+ try {
642
+ const inProgress = (0, queries_js_1.listTasks)(db, { status: 'in_progress' });
643
+ const review = (0, queries_js_1.listTasks)(db, { status: 'review' });
644
+ info.activeTasks = [...inProgress, ...review];
645
+ }
646
+ finally {
647
+ close();
648
+ }
649
+ }
650
+ catch {
651
+ // Skip inaccessible projects
652
+ }
653
+ }
654
+ // JSON output
655
+ if (json) {
656
+ const output = Array.from(projectMap.values()).map((info) => ({
657
+ project: info.path,
658
+ name: info.name,
659
+ runners: info.runners.map((r) => ({
660
+ id: r.id,
661
+ status: r.status,
662
+ pid: r.pid,
663
+ currentTaskId: r.current_task_id,
664
+ alive: r.pid ? (0, lock_js_1.isProcessAlive)(r.pid) : false,
665
+ })),
666
+ activeTasks: info.activeTasks.map((t) => ({
667
+ id: t.id,
668
+ title: t.title,
669
+ status: t.status,
670
+ })),
671
+ }));
672
+ console.log(JSON.stringify({ projects: output }, null, 2));
673
+ return;
674
+ }
675
+ // Text tree view
676
+ const projectList = Array.from(projectMap.values());
677
+ const currentProject = process.cwd();
678
+ if (projectList.length === 0) {
679
+ console.log('No registered projects.');
680
+ return;
681
+ }
682
+ console.log('');
683
+ console.log('RUNNERS TREE');
684
+ console.log('═'.repeat(80));
685
+ for (let i = 0; i < projectList.length; i++) {
686
+ const info = projectList[i];
687
+ const isLast = i === projectList.length - 1;
688
+ const isCurrent = info.path === currentProject;
689
+ const currentMarker = isCurrent ? ' ← (current)' : '';
690
+ console.log('');
691
+ console.log(`📁 ${info.name}${currentMarker}`);
692
+ console.log(` ${info.path}`);
693
+ if (info.runners.length === 0) {
694
+ console.log(' └─ (no runners)');
695
+ }
696
+ else {
697
+ for (let j = 0; j < info.runners.length; j++) {
698
+ const runner = info.runners[j];
699
+ const isLastRunner = j === info.runners.length - 1;
700
+ const runnerPrefix = isLastRunner ? '└─' : '├─';
701
+ const childPrefix = isLastRunner ? ' ' : '│ ';
702
+ const alive = runner.pid && (0, lock_js_1.isProcessAlive)(runner.pid);
703
+ const statusIcon = alive ? '🟢' : '🔴';
704
+ const statusText = alive ? runner.status : 'dead';
705
+ const pidText = runner.pid ? ` PID ${runner.pid}` : '';
706
+ console.log(` ${runnerPrefix} ${statusIcon} Runner ${runner.id.substring(0, 8)} (${statusText}${pidText})`);
707
+ // Show section if focused
708
+ if (runner.section_id && runner.project_path) {
709
+ try {
710
+ const { db, close } = (0, connection_js_1.openDatabase)(runner.project_path);
711
+ try {
712
+ const section = (0, queries_js_1.getSection)(db, runner.section_id);
713
+ if (section) {
714
+ console.log(` ${childPrefix} Section: ${section.name}`);
715
+ }
716
+ }
717
+ finally {
718
+ close();
719
+ }
720
+ }
721
+ catch {
722
+ // Ignore section fetch errors
723
+ }
724
+ }
725
+ // Show current task if available
726
+ if (runner.current_task_id && runner.project_path) {
727
+ try {
728
+ const { db, close } = (0, connection_js_1.openDatabase)(runner.project_path);
729
+ try {
730
+ const task = (0, queries_js_1.getTask)(db, runner.current_task_id);
731
+ if (task) {
732
+ const statusMarker = task.status === 'in_progress' ? '🔧' : '👁️';
733
+ console.log(` ${childPrefix} ${statusMarker} ${task.title.substring(0, 50)}`);
734
+ console.log(` ${childPrefix} [${task.status}] ${task.id.substring(0, 8)}`);
735
+ }
736
+ }
737
+ finally {
738
+ close();
739
+ }
740
+ }
741
+ catch {
742
+ console.log(` ${childPrefix} Task: ${runner.current_task_id.substring(0, 8)}`);
743
+ }
744
+ }
745
+ else if (alive) {
746
+ console.log(` ${childPrefix} (idle - no task)`);
747
+ }
748
+ }
749
+ }
750
+ // Show other active tasks not being worked on by runners
751
+ const runnerTaskIds = new Set(info.runners.map((r) => r.current_task_id).filter(Boolean));
752
+ const unassignedTasks = info.activeTasks.filter((t) => !runnerTaskIds.has(t.id));
753
+ if (unassignedTasks.length > 0) {
754
+ console.log(' │');
755
+ console.log(' └─ 📋 Queued active tasks:');
756
+ for (const task of unassignedTasks.slice(0, 5)) {
757
+ const statusIcon = task.status === 'in_progress' ? '🔧' : '👁️';
758
+ console.log(` ${statusIcon} ${task.title.substring(0, 45)} [${task.status}]`);
759
+ }
760
+ if (unassignedTasks.length > 5) {
761
+ console.log(` ... and ${unassignedTasks.length - 5} more`);
762
+ }
763
+ }
764
+ }
765
+ console.log('');
766
+ console.log('═'.repeat(80));
767
+ // Multi-project warning
768
+ const activeProjects = projectList.filter((p) => p.runners.length > 0);
769
+ if (activeProjects.length > 1) {
770
+ console.log('');
771
+ console.log('⚠️ MULTI-PROJECT: Multiple projects have active runners.');
772
+ console.log(' Each runner works ONLY on its own project.');
773
+ }
774
+ }
775
+ async function runLogs(args) {
776
+ const { values, positionals } = (0, node_util_1.parseArgs)({
777
+ args,
778
+ options: {
779
+ help: { type: 'boolean', short: 'h', default: false },
780
+ json: { type: 'boolean', short: 'j', default: false },
781
+ tail: { type: 'string', short: 'n', default: '50' },
782
+ follow: { type: 'boolean', short: 'f', default: false },
783
+ clear: { type: 'boolean', default: false },
784
+ },
785
+ allowPositionals: true,
786
+ });
787
+ if (values.help) {
788
+ console.log(`
789
+ steroids runners logs - View daemon crash/output logs
790
+
791
+ USAGE:
792
+ steroids runners logs [pid] [options]
793
+
794
+ OPTIONS:
795
+ <pid> Show logs for specific daemon PID
796
+ --tail <n> Show last n lines (default: 50)
797
+ --follow Follow log output (latest log)
798
+ --clear Clear all daemon logs
799
+ -j, --json Output as JSON
800
+ -h, --help Show help
801
+
802
+ LOG LOCATION:
803
+ Logs are stored in ~/.steroids/runners/logs/
804
+ Each daemon gets its own log file: daemon-<pid>.log
805
+
806
+ To disable daemon logging, set in config:
807
+ steroids config set runners.daemonLogs false
808
+
809
+ EXAMPLES:
810
+ steroids runners logs # List available log files
811
+ steroids runners logs 12345 # View logs for PID 12345
812
+ steroids runners logs --follow # Follow the latest log
813
+ steroids runners logs --clear # Remove all log files
814
+ `);
815
+ return;
816
+ }
817
+ const logsDir = path.join(os.homedir(), '.steroids', 'runners', 'logs');
818
+ // Handle --clear
819
+ if (values.clear) {
820
+ if (!fs.existsSync(logsDir)) {
821
+ if (values.json) {
822
+ console.log(JSON.stringify({ success: true, cleared: 0 }));
823
+ }
824
+ else {
825
+ console.log('No logs directory found');
826
+ }
827
+ return;
828
+ }
829
+ const files = fs.readdirSync(logsDir).filter((f) => f.endsWith('.log'));
830
+ for (const file of files) {
831
+ fs.unlinkSync(path.join(logsDir, file));
832
+ }
833
+ if (values.json) {
834
+ console.log(JSON.stringify({ success: true, cleared: files.length }));
835
+ }
836
+ else {
837
+ console.log(`Cleared ${files.length} log file(s)`);
838
+ }
839
+ return;
840
+ }
841
+ // Ensure logs directory exists
842
+ if (!fs.existsSync(logsDir)) {
843
+ if (values.json) {
844
+ console.log(JSON.stringify({ logs: [], logsDir }));
845
+ }
846
+ else {
847
+ console.log('No daemon logs found');
848
+ console.log(` Logs are stored in: ${logsDir}`);
849
+ }
850
+ return;
851
+ }
852
+ const logFiles = fs.readdirSync(logsDir)
853
+ .filter((f) => f.startsWith('daemon-') && f.endsWith('.log'))
854
+ .map((f) => {
855
+ const filePath = path.join(logsDir, f);
856
+ const stats = fs.statSync(filePath);
857
+ const pidMatch = f.match(/daemon-(\d+)\.log/);
858
+ return {
859
+ file: f,
860
+ path: filePath,
861
+ pid: pidMatch ? parseInt(pidMatch[1], 10) : null,
862
+ size: stats.size,
863
+ modified: stats.mtime,
864
+ };
865
+ })
866
+ .sort((a, b) => b.modified.getTime() - a.modified.getTime());
867
+ // If a PID is specified, show that log
868
+ if (positionals.length > 0) {
869
+ const pidArg = positionals[0];
870
+ const logFile = logFiles.find((l) => l.pid?.toString() === pidArg || l.file.includes(pidArg));
871
+ if (!logFile) {
872
+ console.error(`No log found for PID: ${pidArg}`);
873
+ process.exit(1);
874
+ }
875
+ const content = fs.readFileSync(logFile.path, 'utf-8');
876
+ const lines = content.split('\n');
877
+ const tailLines = parseInt(values.tail, 10) || 50;
878
+ const output = lines.slice(-tailLines).join('\n');
879
+ if (values.json) {
880
+ console.log(JSON.stringify({ pid: logFile.pid, path: logFile.path, content: output }));
881
+ }
882
+ else {
883
+ console.log(`=== Daemon log for PID ${logFile.pid} ===`);
884
+ console.log(`File: ${logFile.path}`);
885
+ console.log(`Modified: ${logFile.modified.toISOString()}`);
886
+ console.log('─'.repeat(60));
887
+ console.log(output);
888
+ }
889
+ return;
890
+ }
891
+ // If --follow, tail the most recent log
892
+ if (values.follow) {
893
+ if (logFiles.length === 0) {
894
+ console.error('No log files to follow');
895
+ process.exit(1);
896
+ }
897
+ const latestLog = logFiles[0];
898
+ console.log(`Following: ${latestLog.path} (PID: ${latestLog.pid})`);
899
+ console.log('─'.repeat(60));
900
+ // Use spawn to tail -f
901
+ const tail = (0, node_child_process_1.spawn)('tail', ['-f', latestLog.path], { stdio: 'inherit' });
902
+ tail.on('error', (err) => {
903
+ console.error(`Error following log: ${err.message}`);
904
+ process.exit(1);
905
+ });
906
+ return;
907
+ }
908
+ // List all log files
909
+ if (values.json) {
910
+ console.log(JSON.stringify({ logs: logFiles, logsDir }, null, 2));
911
+ return;
912
+ }
913
+ if (logFiles.length === 0) {
914
+ console.log('No daemon logs found');
915
+ console.log(` Logs are stored in: ${logsDir}`);
916
+ return;
917
+ }
918
+ console.log('DAEMON LOGS');
919
+ console.log('─'.repeat(80));
920
+ console.log('PID SIZE MODIFIED FILE');
921
+ console.log('─'.repeat(80));
922
+ for (const log of logFiles) {
923
+ const pid = (log.pid?.toString() ?? 'unknown').padEnd(10);
924
+ const size = formatBytes(log.size).padEnd(9);
925
+ const modified = log.modified.toISOString().substring(0, 19).padEnd(22);
926
+ console.log(`${pid} ${size} ${modified} ${log.file}`);
927
+ }
928
+ console.log('');
929
+ console.log(`Logs directory: ${logsDir}`);
930
+ console.log(`Use 'steroids runners logs <pid>' to view a specific log`);
931
+ }
932
+ function formatBytes(bytes) {
933
+ if (bytes === 0)
934
+ return '0 B';
935
+ const k = 1024;
936
+ const sizes = ['B', 'KB', 'MB', 'GB'];
937
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
938
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
939
+ }
940
+ async function runWakeup(args, flags) {
941
+ const { values } = (0, node_util_1.parseArgs)({
942
+ args,
943
+ options: {
944
+ help: { type: 'boolean', short: 'h', default: false },
945
+ json: { type: 'boolean', short: 'j', default: false },
946
+ quiet: { type: 'boolean', short: 'q', default: false },
947
+ },
948
+ allowPositionals: false,
949
+ });
950
+ if (values.help) {
951
+ console.log(`
952
+ steroids runners wakeup - Check and restart stale runners
953
+
954
+ USAGE:
955
+ steroids runners wakeup [options]
956
+
957
+ OPTIONS:
958
+ --quiet Suppress output (for cron)
959
+ --dry-run Check without acting
960
+ -j, --json Output as JSON
961
+ -h, --help Show help
962
+ `);
963
+ return;
964
+ }
965
+ const results = await (0, wakeup_js_1.wakeup)({
966
+ quiet: values.quiet || flags.quiet || values.json || flags.json,
967
+ dryRun: flags.dryRun,
968
+ });
969
+ if (values.json || flags.json) {
970
+ console.log(JSON.stringify({ results }, null, 2));
971
+ return;
972
+ }
973
+ if (!values.quiet && !flags.quiet) {
974
+ // Summarize results
975
+ const started = results.filter(r => r.action === 'started').length;
976
+ const cleaned = results.filter(r => r.action === 'cleaned').length;
977
+ const wouldStart = results.filter(r => r.action === 'would_start').length;
978
+ if (started > 0) {
979
+ console.log(`Started ${started} runner(s)`);
980
+ }
981
+ if (cleaned > 0) {
982
+ console.log(`Cleaned ${cleaned} stale runner(s)`);
983
+ }
984
+ if (wouldStart > 0) {
985
+ console.log(`Would start ${wouldStart} runner(s) (dry-run)`);
986
+ }
987
+ if (started === 0 && cleaned === 0 && wouldStart === 0) {
988
+ console.log('No action needed');
989
+ }
990
+ // Show per-project details
991
+ for (const result of results) {
992
+ if (result.projectPath) {
993
+ const status = result.action === 'started' ? '✓' :
994
+ result.action === 'would_start' ? '~' : '-';
995
+ console.log(` ${status} ${result.projectPath}: ${result.reason}`);
996
+ }
997
+ }
998
+ }
999
+ }
1000
+ async function runCron(args) {
1001
+ if (args.length === 0 || args[0] === '-h' || args[0] === '--help') {
1002
+ console.log(`
1003
+ steroids runners cron - Manage cron job
1004
+
1005
+ USAGE:
1006
+ steroids runners cron <subcommand>
1007
+
1008
+ SUBCOMMANDS:
1009
+ install Add cron job (every minute)
1010
+ uninstall Remove cron job
1011
+ status Check cron status
1012
+
1013
+ OPTIONS:
1014
+ -j, --json Output as JSON
1015
+ -h, --help Show help
1016
+ `);
1017
+ return;
1018
+ }
1019
+ const subcommand = args[0];
1020
+ const subArgs = args.slice(1);
1021
+ const { values } = (0, node_util_1.parseArgs)({
1022
+ args: subArgs,
1023
+ options: {
1024
+ json: { type: 'boolean', short: 'j', default: false },
1025
+ },
1026
+ allowPositionals: false,
1027
+ });
1028
+ switch (subcommand) {
1029
+ case 'install': {
1030
+ const result = (0, cron_js_1.cronInstall)();
1031
+ if (values.json) {
1032
+ console.log(JSON.stringify(result, null, 2));
1033
+ }
1034
+ else {
1035
+ console.log(result.message);
1036
+ if (result.error) {
1037
+ console.error(result.error);
1038
+ }
1039
+ }
1040
+ break;
1041
+ }
1042
+ case 'uninstall': {
1043
+ const result = (0, cron_js_1.cronUninstall)();
1044
+ if (values.json) {
1045
+ console.log(JSON.stringify(result, null, 2));
1046
+ }
1047
+ else {
1048
+ console.log(result.message);
1049
+ }
1050
+ break;
1051
+ }
1052
+ case 'status': {
1053
+ const status = (0, cron_js_1.cronStatus)();
1054
+ if (values.json) {
1055
+ console.log(JSON.stringify(status, null, 2));
1056
+ }
1057
+ else {
1058
+ if (status.installed) {
1059
+ console.log('Cron job: INSTALLED');
1060
+ console.log(` Entry: ${status.entry}`);
1061
+ }
1062
+ else {
1063
+ console.log('Cron job: NOT INSTALLED');
1064
+ if (status.error) {
1065
+ console.log(` ${status.error}`);
1066
+ }
1067
+ }
1068
+ }
1069
+ break;
1070
+ }
1071
+ default:
1072
+ console.error(`Unknown cron subcommand: ${subcommand}`);
1073
+ process.exit(1);
1074
+ }
1075
+ }
1076
+ //# sourceMappingURL=runners.js.map