@phnx-labs/agents-cli 1.12.0 → 1.14.2

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 (496) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/README.md +308 -297
  3. package/dist/commands/alias.d.ts +11 -0
  4. package/dist/commands/alias.js +117 -0
  5. package/dist/commands/beta.d.ts +2 -0
  6. package/dist/commands/beta.js +53 -0
  7. package/dist/commands/cloud.d.ts +10 -0
  8. package/dist/commands/cloud.js +408 -0
  9. package/dist/commands/commands.d.ts +9 -1
  10. package/dist/commands/commands.js +24 -172
  11. package/dist/commands/daemon.d.ts +8 -1
  12. package/dist/commands/daemon.js +13 -5
  13. package/dist/commands/doctor.d.ts +15 -0
  14. package/dist/commands/doctor.js +132 -0
  15. package/dist/commands/drive.d.ts +8 -1
  16. package/dist/commands/drive.js +20 -3
  17. package/dist/commands/exec.d.ts +8 -1
  18. package/dist/commands/exec.js +207 -20
  19. package/dist/commands/factory.d.ts +19 -0
  20. package/dist/commands/factory.js +71 -0
  21. package/dist/commands/fork.d.ts +8 -1
  22. package/dist/commands/fork.js +11 -4
  23. package/dist/commands/hooks.d.ts +9 -1
  24. package/dist/commands/hooks.js +30 -182
  25. package/dist/commands/init.d.ts +15 -1
  26. package/dist/commands/init.js +168 -74
  27. package/dist/commands/mcp.d.ts +9 -1
  28. package/dist/commands/mcp.js +11 -7
  29. package/dist/commands/models.d.ts +8 -1
  30. package/dist/commands/models.js +45 -6
  31. package/dist/commands/packages.d.ts +8 -1
  32. package/dist/commands/packages.js +13 -7
  33. package/dist/commands/permissions.d.ts +9 -1
  34. package/dist/commands/permissions.js +3 -3
  35. package/dist/commands/plugins.d.ts +8 -1
  36. package/dist/commands/plugins.js +13 -2
  37. package/dist/commands/profiles.d.ts +11 -0
  38. package/dist/commands/profiles.js +291 -0
  39. package/dist/commands/prune.d.ts +22 -0
  40. package/dist/commands/prune.js +191 -0
  41. package/dist/commands/pty.d.ts +1 -1
  42. package/dist/commands/pty.js +2 -1
  43. package/dist/commands/pull.d.ts +8 -1
  44. package/dist/commands/pull.js +93 -129
  45. package/dist/commands/refresh-memory.d.ts +7 -1
  46. package/dist/commands/refresh-memory.js +7 -1
  47. package/dist/commands/repo.d.ts +15 -0
  48. package/dist/commands/repo.js +570 -0
  49. package/dist/commands/resource-view.d.ts +10 -3
  50. package/dist/commands/resource-view.js +18 -5
  51. package/dist/commands/routines.d.ts +8 -1
  52. package/dist/commands/routines.js +17 -4
  53. package/dist/commands/rules.d.ts +9 -1
  54. package/dist/commands/rules.js +16 -11
  55. package/dist/commands/secrets.d.ts +10 -0
  56. package/dist/commands/secrets.js +518 -0
  57. package/dist/commands/sessions-picker.d.ts +2 -1
  58. package/dist/commands/sessions-picker.js +88 -11
  59. package/dist/commands/sessions-tail.d.ts +19 -0
  60. package/dist/commands/sessions-tail.js +235 -0
  61. package/dist/commands/sessions.d.ts +2 -1
  62. package/dist/commands/sessions.js +288 -7
  63. package/dist/commands/skills.d.ts +9 -1
  64. package/dist/commands/skills.js +28 -178
  65. package/dist/commands/status.d.ts +7 -1
  66. package/dist/commands/status.js +7 -1
  67. package/dist/commands/subagents.d.ts +8 -1
  68. package/dist/commands/subagents.js +11 -1
  69. package/dist/commands/sync.d.ts +8 -1
  70. package/dist/commands/sync.js +8 -1
  71. package/dist/commands/teams-picker.d.ts +4 -1
  72. package/dist/commands/teams-picker.js +55 -3
  73. package/dist/commands/teams.d.ts +15 -1
  74. package/dist/commands/teams.js +323 -69
  75. package/dist/commands/usage.d.ts +11 -0
  76. package/dist/commands/usage.js +60 -0
  77. package/dist/commands/utils.d.ts +6 -1
  78. package/dist/commands/utils.js +6 -1
  79. package/dist/commands/versions.d.ts +8 -1
  80. package/dist/commands/versions.js +4 -3
  81. package/dist/commands/view.d.ts +47 -2
  82. package/dist/commands/view.js +353 -20
  83. package/dist/index.d.ts +7 -2
  84. package/dist/index.js +205 -38
  85. package/dist/lib/acp/client.d.ts +31 -0
  86. package/dist/lib/acp/client.js +117 -0
  87. package/dist/lib/acp/harnesses.d.ts +26 -0
  88. package/dist/lib/acp/harnesses.js +65 -0
  89. package/dist/lib/acp/run.d.ts +18 -0
  90. package/dist/lib/acp/run.js +39 -0
  91. package/dist/lib/agents.d.ts +74 -2
  92. package/dist/lib/agents.js +207 -23
  93. package/dist/lib/artifact-actions.d.ts +8 -4
  94. package/dist/lib/artifact-actions.js +8 -6
  95. package/dist/lib/auto-pull-worker.d.ts +11 -0
  96. package/dist/lib/auto-pull-worker.js +121 -0
  97. package/dist/lib/auto-pull.d.ts +31 -0
  98. package/dist/lib/auto-pull.js +97 -0
  99. package/dist/lib/beta.d.ts +23 -0
  100. package/dist/lib/beta.js +90 -0
  101. package/dist/lib/capabilities.d.ts +29 -0
  102. package/dist/lib/capabilities.js +74 -0
  103. package/dist/lib/cloud/codex.d.ts +25 -0
  104. package/dist/lib/cloud/codex.js +250 -0
  105. package/dist/lib/cloud/factory.d.ts +31 -0
  106. package/dist/lib/cloud/factory.js +53 -0
  107. package/dist/lib/cloud/registry.d.ts +15 -0
  108. package/dist/lib/cloud/registry.js +67 -0
  109. package/dist/lib/cloud/rush.d.ts +75 -0
  110. package/dist/lib/cloud/rush.js +438 -0
  111. package/dist/lib/cloud/store.d.ts +22 -0
  112. package/dist/lib/cloud/store.js +115 -0
  113. package/dist/lib/cloud/stream.d.ts +23 -0
  114. package/dist/lib/cloud/stream.js +194 -0
  115. package/dist/lib/cloud/types.d.ts +205 -0
  116. package/dist/lib/cloud/types.js +34 -0
  117. package/dist/lib/command-skills.d.ts +20 -0
  118. package/dist/lib/command-skills.js +142 -0
  119. package/dist/lib/commands.d.ts +22 -2
  120. package/dist/lib/commands.js +51 -11
  121. package/dist/lib/convert.d.ts +10 -1
  122. package/dist/lib/convert.js +9 -1
  123. package/dist/lib/daemon.d.ts +21 -1
  124. package/dist/lib/daemon.js +97 -4
  125. package/dist/lib/drive-sync.d.ts +18 -1
  126. package/dist/lib/drive-sync.js +57 -15
  127. package/dist/lib/exec.d.ts +25 -5
  128. package/dist/lib/exec.js +72 -27
  129. package/dist/lib/fs-walk.d.ts +2 -0
  130. package/dist/lib/fs-walk.js +40 -0
  131. package/dist/lib/fuzzy.d.ts +53 -0
  132. package/dist/lib/fuzzy.js +72 -0
  133. package/dist/lib/gemini-settings.d.ts +4 -0
  134. package/dist/lib/gemini-settings.js +33 -0
  135. package/dist/lib/git.d.ts +12 -2
  136. package/dist/lib/git.js +17 -6
  137. package/dist/lib/help.d.ts +20 -1
  138. package/dist/lib/help.js +45 -6
  139. package/dist/lib/hooks/match.d.ts +32 -0
  140. package/dist/lib/hooks/match.js +120 -0
  141. package/dist/lib/hooks.d.ts +17 -4
  142. package/dist/lib/hooks.js +191 -21
  143. package/dist/lib/manifest.d.ts +6 -1
  144. package/dist/lib/manifest.js +15 -4
  145. package/dist/lib/markdown.d.ts +0 -1
  146. package/dist/lib/markdown.js +6 -1
  147. package/dist/lib/mcp.d.ts +0 -1
  148. package/dist/lib/mcp.js +29 -33
  149. package/dist/lib/memory-compile.d.ts +13 -3
  150. package/dist/lib/memory-compile.js +31 -9
  151. package/dist/lib/memory.d.ts +14 -7
  152. package/dist/lib/memory.js +67 -38
  153. package/dist/lib/migrate.d.ts +8 -0
  154. package/dist/lib/migrate.js +85 -0
  155. package/dist/lib/models.d.ts +25 -11
  156. package/dist/lib/models.js +405 -16
  157. package/dist/lib/onepassword.d.ts +63 -0
  158. package/dist/lib/onepassword.js +186 -0
  159. package/dist/lib/paths.d.ts +8 -0
  160. package/dist/lib/paths.js +20 -0
  161. package/dist/lib/permissions.d.ts +24 -2
  162. package/dist/lib/permissions.js +117 -48
  163. package/dist/lib/picker.d.ts +10 -1
  164. package/dist/lib/picker.js +15 -1
  165. package/dist/lib/plugins.d.ts +7 -1
  166. package/dist/lib/plugins.js +10 -1
  167. package/dist/lib/profiles-presets.d.ts +24 -0
  168. package/dist/lib/profiles-presets.js +103 -0
  169. package/dist/lib/profiles.d.ts +69 -0
  170. package/dist/lib/profiles.js +144 -0
  171. package/dist/lib/pty-client.d.ts +1 -1
  172. package/dist/lib/pty-client.js +0 -1
  173. package/dist/lib/pty-server.d.ts +16 -2
  174. package/dist/lib/pty-server.js +92 -3
  175. package/dist/lib/registry.d.ts +23 -3
  176. package/dist/lib/registry.js +153 -8
  177. package/dist/lib/resources.d.ts +28 -1
  178. package/dist/lib/resources.js +79 -1
  179. package/dist/lib/rotate.d.ts +89 -0
  180. package/dist/lib/rotate.js +327 -0
  181. package/dist/lib/routines.d.ts +29 -1
  182. package/dist/lib/routines.js +32 -5
  183. package/dist/lib/runner.d.ts +14 -1
  184. package/dist/lib/runner.js +22 -3
  185. package/dist/lib/sandbox.d.ts +16 -1
  186. package/dist/lib/sandbox.js +39 -16
  187. package/dist/lib/scheduler.d.ts +8 -1
  188. package/dist/lib/scheduler.js +8 -1
  189. package/dist/lib/secrets/AgentsKeychain.app/Contents/CodeResources +0 -0
  190. package/dist/lib/secrets/AgentsKeychain.app/Contents/Info.plist +22 -0
  191. package/dist/lib/secrets/AgentsKeychain.app/Contents/MacOS/AgentsKeychain +0 -0
  192. package/dist/lib/secrets/AgentsKeychain.app/Contents/_CodeSignature/CodeResources +123 -0
  193. package/dist/lib/secrets/AgentsKeychain.app/Contents/embedded.provisionprofile +0 -0
  194. package/dist/lib/secrets/bundles.d.ts +39 -0
  195. package/dist/lib/secrets/bundles.js +189 -0
  196. package/dist/lib/secrets/index.d.ts +55 -0
  197. package/dist/lib/secrets/index.js +211 -0
  198. package/dist/lib/secrets/profiles.d.ts +10 -0
  199. package/dist/lib/secrets/profiles.js +13 -0
  200. package/dist/lib/session/active.d.ts +43 -0
  201. package/dist/lib/session/active.js +392 -0
  202. package/dist/lib/session/artifacts.d.ts +16 -0
  203. package/dist/lib/session/artifacts.js +95 -0
  204. package/dist/lib/session/cloud.d.ts +30 -0
  205. package/dist/lib/session/cloud.js +121 -0
  206. package/dist/lib/session/db.d.ts +23 -2
  207. package/dist/lib/session/db.js +76 -12
  208. package/dist/lib/session/discover.d.ts +19 -4
  209. package/dist/lib/session/discover.js +344 -48
  210. package/dist/lib/session/parse.d.ts +28 -1
  211. package/dist/lib/session/parse.js +267 -9
  212. package/dist/lib/session/prompt.d.ts +9 -1
  213. package/dist/lib/session/prompt.js +17 -3
  214. package/dist/lib/session/render.d.ts +13 -1
  215. package/dist/lib/session/render.js +20 -1
  216. package/dist/lib/session/team-filter.d.ts +9 -1
  217. package/dist/lib/session/team-filter.js +11 -2
  218. package/dist/lib/session/types.d.ts +24 -2
  219. package/dist/lib/session/types.js +10 -2
  220. package/dist/lib/shims.d.ts +93 -5
  221. package/dist/lib/shims.js +380 -67
  222. package/dist/lib/skills.d.ts +27 -2
  223. package/dist/lib/skills.js +127 -65
  224. package/dist/lib/sqlite.d.ts +43 -0
  225. package/dist/lib/sqlite.js +94 -0
  226. package/dist/lib/state.d.ts +114 -22
  227. package/dist/lib/state.js +323 -138
  228. package/dist/lib/subagents.d.ts +9 -1
  229. package/dist/lib/subagents.js +70 -63
  230. package/dist/lib/sync-manifest.d.ts +81 -0
  231. package/dist/lib/sync-manifest.js +450 -0
  232. package/dist/lib/teams/agents.d.ts +103 -5
  233. package/dist/lib/teams/agents.js +414 -91
  234. package/dist/lib/teams/api.d.ts +26 -3
  235. package/dist/lib/teams/api.js +63 -3
  236. package/dist/lib/teams/debug.d.ts +6 -1
  237. package/dist/lib/teams/debug.js +6 -1
  238. package/dist/lib/teams/file_ops.d.ts +7 -1
  239. package/dist/lib/teams/file_ops.js +7 -1
  240. package/dist/lib/teams/index.d.ts +15 -0
  241. package/dist/lib/teams/index.js +14 -0
  242. package/dist/lib/teams/parsers.d.ts +4 -1
  243. package/dist/lib/teams/parsers.js +11 -1
  244. package/dist/lib/teams/persistence.d.ts +15 -1
  245. package/dist/lib/teams/persistence.js +102 -20
  246. package/dist/lib/teams/registry.d.ts +12 -1
  247. package/dist/lib/teams/registry.js +116 -33
  248. package/dist/lib/teams/summarizer.d.ts +15 -1
  249. package/dist/lib/teams/summarizer.js +14 -1
  250. package/dist/lib/teams/supervisor.d.ts +48 -0
  251. package/dist/lib/teams/supervisor.js +73 -0
  252. package/dist/lib/template.d.ts +8 -6
  253. package/dist/lib/template.js +8 -6
  254. package/dist/lib/types.d.ts +147 -8
  255. package/dist/lib/types.js +26 -3
  256. package/dist/lib/usage.d.ts +48 -1
  257. package/dist/lib/usage.js +97 -16
  258. package/dist/lib/version-duplicates.d.ts +21 -0
  259. package/dist/lib/version-duplicates.js +90 -0
  260. package/dist/lib/versions.d.ts +39 -4
  261. package/dist/lib/versions.js +401 -111
  262. package/package.json +33 -18
  263. package/scripts/postinstall.js +126 -30
  264. package/dist/commands/__tests__/sessions.test.d.ts +0 -2
  265. package/dist/commands/__tests__/sessions.test.d.ts.map +0 -1
  266. package/dist/commands/__tests__/sessions.test.js +0 -636
  267. package/dist/commands/__tests__/sessions.test.js.map +0 -1
  268. package/dist/commands/commands.d.ts.map +0 -1
  269. package/dist/commands/commands.js.map +0 -1
  270. package/dist/commands/daemon.d.ts.map +0 -1
  271. package/dist/commands/daemon.js.map +0 -1
  272. package/dist/commands/drive.d.ts.map +0 -1
  273. package/dist/commands/drive.js.map +0 -1
  274. package/dist/commands/exec.d.ts.map +0 -1
  275. package/dist/commands/exec.js.map +0 -1
  276. package/dist/commands/fork.d.ts.map +0 -1
  277. package/dist/commands/fork.js.map +0 -1
  278. package/dist/commands/hooks.d.ts.map +0 -1
  279. package/dist/commands/hooks.js.map +0 -1
  280. package/dist/commands/init.d.ts.map +0 -1
  281. package/dist/commands/init.js.map +0 -1
  282. package/dist/commands/mcp.d.ts.map +0 -1
  283. package/dist/commands/mcp.js.map +0 -1
  284. package/dist/commands/models.d.ts.map +0 -1
  285. package/dist/commands/models.js.map +0 -1
  286. package/dist/commands/packages.d.ts.map +0 -1
  287. package/dist/commands/packages.js.map +0 -1
  288. package/dist/commands/permissions.d.ts.map +0 -1
  289. package/dist/commands/permissions.js.map +0 -1
  290. package/dist/commands/plugins.d.ts.map +0 -1
  291. package/dist/commands/plugins.js.map +0 -1
  292. package/dist/commands/pty.d.ts.map +0 -1
  293. package/dist/commands/pty.js.map +0 -1
  294. package/dist/commands/pull.d.ts.map +0 -1
  295. package/dist/commands/pull.js.map +0 -1
  296. package/dist/commands/push.d.ts +0 -3
  297. package/dist/commands/push.d.ts.map +0 -1
  298. package/dist/commands/push.js +0 -180
  299. package/dist/commands/push.js.map +0 -1
  300. package/dist/commands/refresh-memory.d.ts.map +0 -1
  301. package/dist/commands/refresh-memory.js.map +0 -1
  302. package/dist/commands/resource-view.d.ts.map +0 -1
  303. package/dist/commands/resource-view.js.map +0 -1
  304. package/dist/commands/routines.d.ts.map +0 -1
  305. package/dist/commands/routines.js.map +0 -1
  306. package/dist/commands/rules.d.ts.map +0 -1
  307. package/dist/commands/rules.js.map +0 -1
  308. package/dist/commands/sessions-picker.d.ts.map +0 -1
  309. package/dist/commands/sessions-picker.js.map +0 -1
  310. package/dist/commands/sessions.d.ts.map +0 -1
  311. package/dist/commands/sessions.js.map +0 -1
  312. package/dist/commands/skills.d.ts.map +0 -1
  313. package/dist/commands/skills.js.map +0 -1
  314. package/dist/commands/status.d.ts.map +0 -1
  315. package/dist/commands/status.js.map +0 -1
  316. package/dist/commands/subagents.d.ts.map +0 -1
  317. package/dist/commands/subagents.js.map +0 -1
  318. package/dist/commands/sync.d.ts.map +0 -1
  319. package/dist/commands/sync.js.map +0 -1
  320. package/dist/commands/teams-picker.d.ts.map +0 -1
  321. package/dist/commands/teams-picker.js.map +0 -1
  322. package/dist/commands/teams.d.ts.map +0 -1
  323. package/dist/commands/teams.js.map +0 -1
  324. package/dist/commands/utils.d.ts.map +0 -1
  325. package/dist/commands/utils.js.map +0 -1
  326. package/dist/commands/versions.d.ts.map +0 -1
  327. package/dist/commands/versions.js.map +0 -1
  328. package/dist/commands/view.d.ts.map +0 -1
  329. package/dist/commands/view.js.map +0 -1
  330. package/dist/index.d.ts.map +0 -1
  331. package/dist/index.js.map +0 -1
  332. package/dist/lib/__tests__/bugfixes.test.d.ts +0 -2
  333. package/dist/lib/__tests__/bugfixes.test.d.ts.map +0 -1
  334. package/dist/lib/__tests__/bugfixes.test.js +0 -192
  335. package/dist/lib/__tests__/bugfixes.test.js.map +0 -1
  336. package/dist/lib/__tests__/exec.test.d.ts +0 -2
  337. package/dist/lib/__tests__/exec.test.d.ts.map +0 -1
  338. package/dist/lib/__tests__/exec.test.js +0 -446
  339. package/dist/lib/__tests__/exec.test.js.map +0 -1
  340. package/dist/lib/__tests__/git-sync.test.d.ts +0 -2
  341. package/dist/lib/__tests__/git-sync.test.d.ts.map +0 -1
  342. package/dist/lib/__tests__/git-sync.test.js +0 -138
  343. package/dist/lib/__tests__/git-sync.test.js.map +0 -1
  344. package/dist/lib/__tests__/hooks.test.d.ts +0 -2
  345. package/dist/lib/__tests__/hooks.test.d.ts.map +0 -1
  346. package/dist/lib/__tests__/hooks.test.js +0 -203
  347. package/dist/lib/__tests__/hooks.test.js.map +0 -1
  348. package/dist/lib/__tests__/memory-compile.test.d.ts +0 -2
  349. package/dist/lib/__tests__/memory-compile.test.d.ts.map +0 -1
  350. package/dist/lib/__tests__/memory-compile.test.js +0 -95
  351. package/dist/lib/__tests__/memory-compile.test.js.map +0 -1
  352. package/dist/lib/__tests__/models.test.d.ts +0 -2
  353. package/dist/lib/__tests__/models.test.d.ts.map +0 -1
  354. package/dist/lib/__tests__/models.test.js +0 -184
  355. package/dist/lib/__tests__/models.test.js.map +0 -1
  356. package/dist/lib/__tests__/usage.test.d.ts +0 -2
  357. package/dist/lib/__tests__/usage.test.d.ts.map +0 -1
  358. package/dist/lib/__tests__/usage.test.js +0 -218
  359. package/dist/lib/__tests__/usage.test.js.map +0 -1
  360. package/dist/lib/agents.d.ts.map +0 -1
  361. package/dist/lib/agents.js.map +0 -1
  362. package/dist/lib/artifact-actions.d.ts.map +0 -1
  363. package/dist/lib/artifact-actions.js.map +0 -1
  364. package/dist/lib/commands.d.ts.map +0 -1
  365. package/dist/lib/commands.js.map +0 -1
  366. package/dist/lib/convert.d.ts.map +0 -1
  367. package/dist/lib/convert.js.map +0 -1
  368. package/dist/lib/daemon.d.ts.map +0 -1
  369. package/dist/lib/daemon.js.map +0 -1
  370. package/dist/lib/drive-sync.d.ts.map +0 -1
  371. package/dist/lib/drive-sync.js.map +0 -1
  372. package/dist/lib/exec.d.ts.map +0 -1
  373. package/dist/lib/exec.js.map +0 -1
  374. package/dist/lib/factory.d.ts +0 -57
  375. package/dist/lib/factory.d.ts.map +0 -1
  376. package/dist/lib/factory.js +0 -110
  377. package/dist/lib/factory.js.map +0 -1
  378. package/dist/lib/git.d.ts.map +0 -1
  379. package/dist/lib/git.js.map +0 -1
  380. package/dist/lib/help.d.ts.map +0 -1
  381. package/dist/lib/help.js.map +0 -1
  382. package/dist/lib/hooks.d.ts.map +0 -1
  383. package/dist/lib/hooks.js.map +0 -1
  384. package/dist/lib/manifest.d.ts.map +0 -1
  385. package/dist/lib/manifest.js.map +0 -1
  386. package/dist/lib/markdown.d.ts.map +0 -1
  387. package/dist/lib/markdown.js.map +0 -1
  388. package/dist/lib/mcp.d.ts.map +0 -1
  389. package/dist/lib/mcp.js.map +0 -1
  390. package/dist/lib/memory-compile.d.ts.map +0 -1
  391. package/dist/lib/memory-compile.js.map +0 -1
  392. package/dist/lib/memory.d.ts.map +0 -1
  393. package/dist/lib/memory.js.map +0 -1
  394. package/dist/lib/models.d.ts.map +0 -1
  395. package/dist/lib/models.js.map +0 -1
  396. package/dist/lib/permissions.d.ts.map +0 -1
  397. package/dist/lib/permissions.js.map +0 -1
  398. package/dist/lib/picker.d.ts.map +0 -1
  399. package/dist/lib/picker.js.map +0 -1
  400. package/dist/lib/plugins.d.ts.map +0 -1
  401. package/dist/lib/plugins.js.map +0 -1
  402. package/dist/lib/pty-client.d.ts.map +0 -1
  403. package/dist/lib/pty-client.js.map +0 -1
  404. package/dist/lib/pty-server.d.ts.map +0 -1
  405. package/dist/lib/pty-server.js.map +0 -1
  406. package/dist/lib/registry.d.ts.map +0 -1
  407. package/dist/lib/registry.js.map +0 -1
  408. package/dist/lib/resources.d.ts.map +0 -1
  409. package/dist/lib/resources.js.map +0 -1
  410. package/dist/lib/routines.d.ts.map +0 -1
  411. package/dist/lib/routines.js.map +0 -1
  412. package/dist/lib/runner.d.ts.map +0 -1
  413. package/dist/lib/runner.js.map +0 -1
  414. package/dist/lib/sandbox.d.ts.map +0 -1
  415. package/dist/lib/sandbox.js.map +0 -1
  416. package/dist/lib/scheduler.d.ts.map +0 -1
  417. package/dist/lib/scheduler.js.map +0 -1
  418. package/dist/lib/session/__tests__/db.test.d.ts +0 -2
  419. package/dist/lib/session/__tests__/db.test.d.ts.map +0 -1
  420. package/dist/lib/session/__tests__/db.test.js +0 -54
  421. package/dist/lib/session/__tests__/db.test.js.map +0 -1
  422. package/dist/lib/session/__tests__/discover.test.d.ts +0 -2
  423. package/dist/lib/session/__tests__/discover.test.d.ts.map +0 -1
  424. package/dist/lib/session/__tests__/discover.test.js +0 -63
  425. package/dist/lib/session/__tests__/discover.test.js.map +0 -1
  426. package/dist/lib/session/__tests__/prompt.test.d.ts +0 -2
  427. package/dist/lib/session/__tests__/prompt.test.d.ts.map +0 -1
  428. package/dist/lib/session/__tests__/prompt.test.js +0 -44
  429. package/dist/lib/session/__tests__/prompt.test.js.map +0 -1
  430. package/dist/lib/session/__tests__/render.test.d.ts +0 -2
  431. package/dist/lib/session/__tests__/render.test.d.ts.map +0 -1
  432. package/dist/lib/session/__tests__/render.test.js +0 -602
  433. package/dist/lib/session/__tests__/render.test.js.map +0 -1
  434. package/dist/lib/session/db.d.ts.map +0 -1
  435. package/dist/lib/session/db.js.map +0 -1
  436. package/dist/lib/session/discover.d.ts.map +0 -1
  437. package/dist/lib/session/discover.js.map +0 -1
  438. package/dist/lib/session/parse.d.ts.map +0 -1
  439. package/dist/lib/session/parse.js.map +0 -1
  440. package/dist/lib/session/prompt.d.ts.map +0 -1
  441. package/dist/lib/session/prompt.js.map +0 -1
  442. package/dist/lib/session/prompt.test.d.ts +0 -2
  443. package/dist/lib/session/prompt.test.d.ts.map +0 -1
  444. package/dist/lib/session/prompt.test.js +0 -57
  445. package/dist/lib/session/prompt.test.js.map +0 -1
  446. package/dist/lib/session/render.d.ts.map +0 -1
  447. package/dist/lib/session/render.js.map +0 -1
  448. package/dist/lib/session/team-filter.d.ts.map +0 -1
  449. package/dist/lib/session/team-filter.js.map +0 -1
  450. package/dist/lib/session/team-filter.test.d.ts +0 -2
  451. package/dist/lib/session/team-filter.test.d.ts.map +0 -1
  452. package/dist/lib/session/team-filter.test.js +0 -157
  453. package/dist/lib/session/team-filter.test.js.map +0 -1
  454. package/dist/lib/session/types.d.ts.map +0 -1
  455. package/dist/lib/session/types.js.map +0 -1
  456. package/dist/lib/shims.d.ts.map +0 -1
  457. package/dist/lib/shims.js.map +0 -1
  458. package/dist/lib/skills.d.ts.map +0 -1
  459. package/dist/lib/skills.js.map +0 -1
  460. package/dist/lib/state.d.ts.map +0 -1
  461. package/dist/lib/state.js.map +0 -1
  462. package/dist/lib/subagents.d.ts.map +0 -1
  463. package/dist/lib/subagents.js.map +0 -1
  464. package/dist/lib/teams/agents.d.ts.map +0 -1
  465. package/dist/lib/teams/agents.js.map +0 -1
  466. package/dist/lib/teams/api.d.ts.map +0 -1
  467. package/dist/lib/teams/api.js.map +0 -1
  468. package/dist/lib/teams/cloud.d.ts +0 -11
  469. package/dist/lib/teams/cloud.d.ts.map +0 -1
  470. package/dist/lib/teams/cloud.js +0 -169
  471. package/dist/lib/teams/cloud.js.map +0 -1
  472. package/dist/lib/teams/debug.d.ts.map +0 -1
  473. package/dist/lib/teams/debug.js.map +0 -1
  474. package/dist/lib/teams/file_ops.d.ts.map +0 -1
  475. package/dist/lib/teams/file_ops.js.map +0 -1
  476. package/dist/lib/teams/parsers.d.ts.map +0 -1
  477. package/dist/lib/teams/parsers.js.map +0 -1
  478. package/dist/lib/teams/persistence.d.ts.map +0 -1
  479. package/dist/lib/teams/persistence.js.map +0 -1
  480. package/dist/lib/teams/ralph.d.ts +0 -8
  481. package/dist/lib/teams/ralph.d.ts.map +0 -1
  482. package/dist/lib/teams/ralph.js +0 -59
  483. package/dist/lib/teams/ralph.js.map +0 -1
  484. package/dist/lib/teams/registry.d.ts.map +0 -1
  485. package/dist/lib/teams/registry.js.map +0 -1
  486. package/dist/lib/teams/summarizer.d.ts.map +0 -1
  487. package/dist/lib/teams/summarizer.js.map +0 -1
  488. package/dist/lib/template.d.ts.map +0 -1
  489. package/dist/lib/template.js.map +0 -1
  490. package/dist/lib/types.d.ts.map +0 -1
  491. package/dist/lib/types.js.map +0 -1
  492. package/dist/lib/usage.d.ts.map +0 -1
  493. package/dist/lib/usage.js.map +0 -1
  494. package/dist/lib/versions.d.ts.map +0 -1
  495. package/dist/lib/versions.js.map +0 -1
  496. package/scripts/rebuild-sqlite.sh +0 -46
@@ -0,0 +1,327 @@
1
+ /**
2
+ * Account rotation across agent versions.
3
+ *
4
+ * Detects which installed versions have expired credentials and rotates
5
+ * authentication tokens so users maintain active sessions across version switches.
6
+ */
7
+ import * as fs from 'fs';
8
+ import * as path from 'path';
9
+ import * as yaml from 'yaml';
10
+ import { getAccountInfo } from './agents.js';
11
+ import { readMeta, writeMeta, getAgentsDir } from './state.js';
12
+ import { listInstalledVersions, getVersionHomePath, resolveVersion } from './versions.js';
13
+ import { getUsageInfoByIdentity, getUsageLookupKey, isClaudeAuthValid, } from './usage.js';
14
+ export const RUN_STRATEGIES = ['pinned', 'available', 'balanced'];
15
+ /**
16
+ * Return a run strategy when the input is valid, otherwise null.
17
+ *
18
+ * `'rotate'` is accepted as a deprecated alias for `'balanced'` so old yaml
19
+ * configs and `--strategy rotate` invocations keep working. The legacy alias
20
+ * normalizes to `'balanced'` and uses the weighted-random algorithm.
21
+ */
22
+ export function normalizeRunStrategy(value) {
23
+ if (typeof value !== 'string')
24
+ return null;
25
+ if (value === 'rotate')
26
+ return 'balanced';
27
+ return RUN_STRATEGIES.includes(value) ? value : null;
28
+ }
29
+ /** Read project-local run strategy from the nearest agents.yaml, if present. */
30
+ export function getProjectRunStrategy(agent, startPath) {
31
+ let dir = path.resolve(startPath);
32
+ const userAgentsYaml = path.join(getAgentsDir(), 'agents.yaml');
33
+ while (dir !== path.dirname(dir)) {
34
+ const manifestPath = path.join(dir, 'agents.yaml');
35
+ if (manifestPath !== userAgentsYaml && fs.existsSync(manifestPath)) {
36
+ try {
37
+ const parsed = yaml.parse(fs.readFileSync(manifestPath, 'utf-8'));
38
+ const strategy = normalizeRunStrategy(parsed?.run?.[agent]?.strategy);
39
+ if (strategy)
40
+ return strategy;
41
+ }
42
+ catch {
43
+ // Ignore malformed project config and keep walking, matching version resolution.
44
+ }
45
+ }
46
+ dir = path.dirname(dir);
47
+ }
48
+ return null;
49
+ }
50
+ /** Resolve the configured strategy: project agents.yaml, then ~/.agents-system/agents.yaml, then pinned. */
51
+ export function getConfiguredRunStrategy(agent, startPath = process.cwd()) {
52
+ return getProjectRunStrategy(agent, startPath)
53
+ ?? normalizeRunStrategy(readMeta().run?.[agent]?.strategy)
54
+ ?? 'pinned';
55
+ }
56
+ /** Persist the global run strategy used by bare `agents run <agent>`. */
57
+ export function setGlobalRunStrategy(agent, strategy) {
58
+ const meta = readMeta();
59
+ if (!meta.run)
60
+ meta.run = {};
61
+ meta.run[agent] = { ...(meta.run[agent] ?? {}), strategy };
62
+ writeMeta(meta);
63
+ }
64
+ function isRotationEligible(candidate) {
65
+ return !!candidate.email
66
+ && candidate.authValid
67
+ && hasUsageAvailable(candidate);
68
+ }
69
+ function isAvailableEligible(candidate) {
70
+ return !!candidate.email
71
+ && candidate.authValid
72
+ && hasUsageAvailable(candidate);
73
+ }
74
+ function hasUsageAvailable(candidate) {
75
+ const usedPercent = getRoutingUsedPercent(candidate.usageSnapshot);
76
+ if (usedPercent !== null) {
77
+ return usedPercent < 100;
78
+ }
79
+ if (candidate.usageStatus === 'out_of_credits' || candidate.usageStatus === 'rate_limited') {
80
+ return false;
81
+ }
82
+ return true;
83
+ }
84
+ function getRoutingUsedPercent(snapshot) {
85
+ if (!snapshot || snapshot.windows.length === 0)
86
+ return null;
87
+ const routingWindows = snapshot.windows.filter((window) => window.key !== 'session');
88
+ const windows = routingWindows.length > 0 ? routingWindows : snapshot.windows;
89
+ return Math.max(...windows.map((window) => window.usedPercent));
90
+ }
91
+ function compareCandidates(a, b) {
92
+ const au = getRoutingUsedPercent(a.usageSnapshot);
93
+ const bu = getRoutingUsedPercent(b.usageSnapshot);
94
+ if (au !== null || bu !== null) {
95
+ if (au === null)
96
+ return 1;
97
+ if (bu === null)
98
+ return -1;
99
+ if (au !== bu)
100
+ return au - bu;
101
+ }
102
+ const ta = a.lastActive ? a.lastActive.getTime() : 0;
103
+ const tb = b.lastActive ? b.lastActive.getTime() : 0;
104
+ if (ta !== tb)
105
+ return ta - tb;
106
+ return Math.random() - 0.5;
107
+ }
108
+ function dedupeAndSortCandidates(candidates) {
109
+ const byEmail = new Map();
110
+ for (const c of candidates) {
111
+ const email = c.email;
112
+ const existing = byEmail.get(email);
113
+ if (!existing) {
114
+ byEmail.set(email, c);
115
+ continue;
116
+ }
117
+ if (compareCandidates(c, existing) < 0)
118
+ byEmail.set(email, c);
119
+ }
120
+ return [...byEmail.values()].sort(compareCandidates);
121
+ }
122
+ /**
123
+ * Pick a healthy candidate using weighted random by remaining capacity.
124
+ *
125
+ * Each healthy candidate gets weight = max(1, 100 - usedPercent) where
126
+ * usedPercent is the highest-utilized non-session window (week / sonnet_week
127
+ * for Claude). An account at 10% used gets weight 90; one at 90% used gets
128
+ * weight 10 — so the fresher account is 9× more likely to be picked. Over N
129
+ * calls, traffic distributes across healthy accounts proportional to their
130
+ * headroom, with no stampede on the lowest-usage one. Stateless — parallel
131
+ * callers naturally fan out via the random roll.
132
+ *
133
+ * Eligibility: signed in (email present), auth valid, and usage available
134
+ * (any non-session window strictly under 100%, or local flag not exhausted
135
+ * when no live snapshot exists).
136
+ *
137
+ * Dedupe: when multiple versions share an email, collapse to one candidate
138
+ * per email (the least-recently-active version). Prevents two parallel pods
139
+ * from "balancing" to different versions but hitting the same Anthropic
140
+ * account and both 429ing.
141
+ *
142
+ * Returns null if no candidate is eligible — callers fall back to the pinned
143
+ * version so behavior stays predictable.
144
+ */
145
+ export function pickBalancedCandidate(candidates) {
146
+ const healthy = [];
147
+ const excluded = [];
148
+ for (const c of candidates) {
149
+ if (!isRotationEligible(c)) {
150
+ excluded.push(c);
151
+ continue;
152
+ }
153
+ healthy.push(c);
154
+ }
155
+ if (healthy.length === 0)
156
+ return null;
157
+ const sorted = dedupeAndSortCandidates(healthy);
158
+ const deduped = new Set(sorted);
159
+ for (const c of healthy) {
160
+ if (!deduped.has(c))
161
+ excluded.push(c);
162
+ }
163
+ const picked = weightedRandomByCapacity(sorted);
164
+ return { picked, healthy: sorted, excluded };
165
+ }
166
+ /**
167
+ * Pick one candidate from `sorted` using weights proportional to remaining
168
+ * routing capacity. Floor each weight at 1 so a near-exhausted-but-still-
169
+ * eligible candidate can still be picked occasionally. When usage is unknown
170
+ * (no live snapshot), treat the candidate as full-capacity (weight 100) — we
171
+ * have no signal to deprioritize it.
172
+ */
173
+ function weightedRandomByCapacity(sorted) {
174
+ const weights = sorted.map((c) => {
175
+ const used = getRoutingUsedPercent(c.usageSnapshot);
176
+ if (used === null)
177
+ return 100;
178
+ return Math.max(1, 100 - used);
179
+ });
180
+ const total = weights.reduce((sum, w) => sum + w, 0);
181
+ if (total <= 0)
182
+ return sorted[0];
183
+ let roll = Math.random() * total;
184
+ for (let i = 0; i < sorted.length; i++) {
185
+ roll -= weights[i];
186
+ if (roll <= 0)
187
+ return sorted[i];
188
+ }
189
+ return sorted[sorted.length - 1];
190
+ }
191
+ /**
192
+ * Pick an available candidate. Prefers the configured pinned version when that
193
+ * version has usage available; otherwise routes to the candidate with the most
194
+ * usage headroom.
195
+ */
196
+ export function pickAvailableCandidate(candidates, preferredVersion) {
197
+ const healthy = [];
198
+ const excluded = [];
199
+ for (const c of candidates) {
200
+ if (!isAvailableEligible(c)) {
201
+ excluded.push(c);
202
+ continue;
203
+ }
204
+ healthy.push(c);
205
+ }
206
+ if (healthy.length === 0)
207
+ return null;
208
+ const sorted = dedupeAndSortCandidates(healthy);
209
+ const deduped = new Set(sorted);
210
+ for (const c of healthy) {
211
+ if (!deduped.has(c))
212
+ excluded.push(c);
213
+ }
214
+ const preferred = preferredVersion
215
+ ? sorted.find((candidate) => candidate.version === preferredVersion)
216
+ : undefined;
217
+ return { picked: preferred ?? sorted[0], healthy: sorted, excluded };
218
+ }
219
+ async function collectRunCandidates(agent) {
220
+ const versions = listInstalledVersions(agent);
221
+ const rows = await Promise.all(versions.map(async (version) => {
222
+ const home = getVersionHomePath(agent, version);
223
+ const info = await getAccountInfo(agent, home);
224
+ const authValid = info.email
225
+ ? agent === 'claude' ? await isClaudeAuthValid(home) : true
226
+ : false;
227
+ return {
228
+ agent,
229
+ version,
230
+ home,
231
+ info,
232
+ email: info.email,
233
+ usageStatus: info.usageStatus,
234
+ authValid,
235
+ lastActive: info.lastActive,
236
+ };
237
+ }));
238
+ const { usageByKey } = await getUsageInfoByIdentity(rows.map(({ home, info, version }) => ({
239
+ agentId: agent,
240
+ home,
241
+ cliVersion: version,
242
+ info,
243
+ })));
244
+ return rows.map(({ home: _home, info, ...candidate }) => {
245
+ const usageKey = getUsageLookupKey(info);
246
+ const usageSnapshot = usageKey
247
+ ? usageByKey.get(usageKey)?.snapshot ?? null
248
+ : null;
249
+ return { ...candidate, usageSnapshot };
250
+ });
251
+ }
252
+ /**
253
+ * Pick a healthy version for `agent` using weighted random by remaining
254
+ * capacity. See `pickBalancedCandidate` for algorithm details.
255
+ *
256
+ * No external state — health and capacity are both read off per-version
257
+ * AccountInfo (same data `agents view` surfaces). The weighted random roll
258
+ * keeps parallel callers fanned out without rotation files or locks.
259
+ *
260
+ * Returns null if no installed version is eligible. Callers fall back to the
261
+ * global default so behavior stays predictable — we never refuse to run.
262
+ */
263
+ export async function selectBalancedVersion(agent) {
264
+ return pickBalancedCandidate(await collectRunCandidates(agent));
265
+ }
266
+ /** Select the configured version if available, otherwise another available version. */
267
+ export async function selectAvailableVersion(agent, preferredVersion) {
268
+ return pickAvailableCandidate(await collectRunCandidates(agent), preferredVersion);
269
+ }
270
+ /**
271
+ * Resolve the version `agents run` should use when the caller did not pin
272
+ * one with `@version`. The caller supplies the effective strategy; if that
273
+ * strategy cannot find a usable candidate, fall back to the pinned
274
+ * workspace/global version.
275
+ */
276
+ /**
277
+ * Record a rotation pick so parallel callers see it as recently-used.
278
+ * Writes a stamp file per agent — lightweight, no locking needed since
279
+ * a torn write just means the next reader sees a stale timestamp (harmless).
280
+ */
281
+ function recordRotationPick(agent, version) {
282
+ const stampPath = path.join(getAgentsDir(), `rotate-stamp-${agent}.json`);
283
+ try {
284
+ fs.writeFileSync(stampPath, JSON.stringify({ version, ts: Date.now() }), 'utf-8');
285
+ }
286
+ catch { /* best effort — doesn't block the run */ }
287
+ }
288
+ /**
289
+ * Read the most recent rotation pick for an agent. Returns null if no stamp
290
+ * or stamp is older than 60 seconds (stale).
291
+ */
292
+ function readRotationStamp(agent) {
293
+ const stampPath = path.join(getAgentsDir(), `rotate-stamp-${agent}.json`);
294
+ try {
295
+ const raw = JSON.parse(fs.readFileSync(stampPath, 'utf-8'));
296
+ if (Date.now() - raw.ts < 60_000)
297
+ return raw.version;
298
+ }
299
+ catch { /* missing or corrupt — treat as no stamp */ }
300
+ return null;
301
+ }
302
+ export async function resolveRunVersion(agent, strategy, cwd = process.cwd()) {
303
+ const fallback = resolveVersion(agent, cwd);
304
+ if (strategy === 'pinned') {
305
+ return { version: fallback, rotation: null };
306
+ }
307
+ const rotation = strategy === 'available'
308
+ ? await selectAvailableVersion(agent, fallback)
309
+ : await selectBalancedVersion(agent);
310
+ if (rotation) {
311
+ // `available` is sticky to the pinned default when healthy. Use the 60s
312
+ // anti-collision stamp to nudge parallel callers off the same version.
313
+ // `balanced` doesn't need this — its weighted random roll already
314
+ // distributes naturally across healthy accounts.
315
+ if (strategy === 'available') {
316
+ const recentPick = readRotationStamp(agent);
317
+ if (recentPick === rotation.picked.version && rotation.healthy.length > 1) {
318
+ const alt = rotation.healthy.find(c => c.version !== recentPick);
319
+ if (alt)
320
+ rotation.picked = alt;
321
+ }
322
+ recordRotationPick(agent, rotation.picked.version);
323
+ }
324
+ return { version: rotation.picked.version, rotation };
325
+ }
326
+ return { version: fallback, rotation: null };
327
+ }
@@ -1,9 +1,19 @@
1
+ /**
2
+ * Scheduled job (routine) configuration and run history management.
3
+ *
4
+ * Routines are YAML files in ~/.agents/routines/ that define recurring or
5
+ * one-shot agent tasks. This module handles CRUD operations on job configs,
6
+ * run metadata persistence, prompt variable expansion, and one-shot "at" time
7
+ * scheduling.
8
+ */
1
9
  import type { AgentId } from './types.js';
10
+ /** Tool/site/directory allow-list for sandboxed job execution. */
2
11
  export interface JobAllowConfig {
3
12
  tools?: string[];
4
13
  sites?: string[];
5
14
  dirs?: string[];
6
15
  }
16
+ /** Full configuration for a scheduled routine (persisted as YAML). */
7
17
  export interface JobConfig {
8
18
  name: string;
9
19
  schedule: string;
@@ -21,6 +31,7 @@ export interface JobConfig {
21
31
  version?: string;
22
32
  runOnce?: boolean;
23
33
  }
34
+ /** Metadata for a single job execution, persisted as JSON in the run directory. */
24
35
  export interface RunMeta {
25
36
  jobName: string;
26
37
  runId: string;
@@ -31,24 +42,40 @@ export interface RunMeta {
31
42
  completedAt: string | null;
32
43
  exitCode: number | null;
33
44
  }
45
+ /** List all job configs from ~/.agents/routines/. */
34
46
  export declare function listJobs(): JobConfig[];
47
+ /** Read a single job config by name. Returns null if not found. */
35
48
  export declare function readJob(name: string): JobConfig | null;
49
+ /** Write a job config to disk, omitting fields that match defaults. */
36
50
  export declare function writeJob(config: JobConfig): void;
51
+ /** Delete a job config file by name. Returns true if the file existed. */
37
52
  export declare function deleteJob(name: string): boolean;
53
+ /** Enable or disable a job by name. */
38
54
  export declare function setJobEnabled(name: string, enabled: boolean): void;
55
+ /** Validate a partial job config, returning a list of human-readable errors. */
39
56
  export declare function validateJob(config: Partial<JobConfig>): string[];
57
+ /** Expand built-in and user-defined template variables in a job's prompt string. */
40
58
  export declare function resolveJobPrompt(config: JobConfig): string;
59
+ /** Parse a human-readable timeout string (e.g. "30m", "2h", "1h30m") into milliseconds. */
41
60
  export declare function parseTimeout(timeout: string): number | null;
61
+ /** List all run metadata entries for a job, sorted chronologically. */
42
62
  export declare function listRuns(jobName: string): RunMeta[];
63
+ /** Get the most recent run for a job, or null if never run. */
43
64
  export declare function getLatestRun(jobName: string): RunMeta | null;
65
+ /** Persist run metadata to its run directory as meta.json. */
44
66
  export declare function writeRunMeta(meta: RunMeta): void;
67
+ /** Read run metadata from disk. Returns null if missing or corrupt. */
45
68
  export declare function readRunMeta(jobName: string, runId: string): RunMeta | null;
69
+ /** Get the filesystem path for a specific run's directory. */
46
70
  export declare function getRunDir(jobName: string, runId: string): string;
71
+ /** Discover routine YAML files in a repository's routines/ directory. */
47
72
  export declare function discoverJobsFromRepo(repoPath: string): Array<{
48
73
  name: string;
49
74
  path: string;
50
75
  }>;
76
+ /** Check whether a job with the given name exists on disk. */
51
77
  export declare function jobExists(name: string): boolean;
78
+ /** Get the filesystem path of a job's YAML config file, or null if not found. */
52
79
  export declare function getJobPath(name: string): string | null;
53
80
  /**
54
81
  * Parse an "at" time string into a one-shot cron expression.
@@ -62,9 +89,10 @@ export declare function parseAtTime(atTime: string): {
62
89
  schedule: string;
63
90
  runOnce: boolean;
64
91
  } | null;
92
+ /** Check if an installed job's normalized YAML matches the source file. */
65
93
  export declare function jobContentMatches(name: string, sourcePath: string): boolean;
94
+ /** Install a job by reading and validating a YAML source file. */
66
95
  export declare function installJobFromSource(sourcePath: string, name: string): {
67
96
  success: boolean;
68
97
  error?: string;
69
98
  };
70
- //# sourceMappingURL=routines.d.ts.map
@@ -1,15 +1,26 @@
1
+ /**
2
+ * Scheduled job (routine) configuration and run history management.
3
+ *
4
+ * Routines are YAML files in ~/.agents/routines/ that define recurring or
5
+ * one-shot agent tasks. This module handles CRUD operations on job configs,
6
+ * run metadata persistence, prompt variable expansion, and one-shot "at" time
7
+ * scheduling.
8
+ */
1
9
  import * as fs from 'fs';
2
10
  import * as path from 'path';
3
11
  import * as yaml from 'yaml';
4
12
  import { Cron } from 'croner';
5
13
  import { getRoutinesDir, getRunsDir, ensureAgentsDir } from './state.js';
14
+ import { safeJoin } from './paths.js';
6
15
  import { ALL_AGENT_IDS } from './agents.js';
16
+ /** Default values applied to every job config when fields are omitted. */
7
17
  const JOB_DEFAULTS = {
8
18
  mode: 'plan',
9
19
  effort: 'auto',
10
20
  timeout: '30m',
11
21
  enabled: true,
12
22
  };
23
+ /** List all job configs from ~/.agents/routines/. */
13
24
  export function listJobs() {
14
25
  ensureAgentsDir();
15
26
  const jobsDir = getRoutinesDir();
@@ -24,11 +35,12 @@ export function listJobs() {
24
35
  }
25
36
  return jobs;
26
37
  }
38
+ /** Read a single job config by name. Returns null if not found. */
27
39
  export function readJob(name) {
28
40
  ensureAgentsDir();
29
41
  const jobsDir = getRoutinesDir();
30
42
  for (const ext of ['.yml', '.yaml']) {
31
- const filePath = path.join(jobsDir, name + ext);
43
+ const filePath = safeJoin(jobsDir, name + ext);
32
44
  if (fs.existsSync(filePath)) {
33
45
  return readJobFile(filePath);
34
46
  }
@@ -51,10 +63,11 @@ function readJobFile(filePath) {
51
63
  return null;
52
64
  }
53
65
  }
66
+ /** Write a job config to disk, omitting fields that match defaults. */
54
67
  export function writeJob(config) {
55
68
  ensureAgentsDir();
56
69
  const jobsDir = getRoutinesDir();
57
- const filePath = path.join(jobsDir, config.name + '.yml');
70
+ const filePath = safeJoin(jobsDir, config.name + '.yml');
58
71
  const output = { ...config };
59
72
  if (output.mode === 'plan')
60
73
  delete output.mode;
@@ -68,10 +81,11 @@ export function writeJob(config) {
68
81
  delete output.runOnce;
69
82
  fs.writeFileSync(filePath, yaml.stringify(output), 'utf-8');
70
83
  }
84
+ /** Delete a job config file by name. Returns true if the file existed. */
71
85
  export function deleteJob(name) {
72
86
  const jobsDir = getRoutinesDir();
73
87
  for (const ext of ['.yml', '.yaml']) {
74
- const filePath = path.join(jobsDir, name + ext);
88
+ const filePath = safeJoin(jobsDir, name + ext);
75
89
  if (fs.existsSync(filePath)) {
76
90
  fs.unlinkSync(filePath);
77
91
  return true;
@@ -79,6 +93,7 @@ export function deleteJob(name) {
79
93
  }
80
94
  return false;
81
95
  }
96
+ /** Enable or disable a job by name. */
82
97
  export function setJobEnabled(name, enabled) {
83
98
  const job = readJob(name);
84
99
  if (!job)
@@ -86,6 +101,7 @@ export function setJobEnabled(name, enabled) {
86
101
  job.enabled = enabled;
87
102
  writeJob(job);
88
103
  }
104
+ /** Validate a partial job config, returning a list of human-readable errors. */
89
105
  export function validateJob(config) {
90
106
  const errors = [];
91
107
  if (!config.name || typeof config.name !== 'string') {
@@ -123,6 +139,7 @@ export function validateJob(config) {
123
139
  }
124
140
  return errors;
125
141
  }
142
+ /** Expand built-in and user-defined template variables in a job's prompt string. */
126
143
  export function resolveJobPrompt(config) {
127
144
  const now = new Date();
128
145
  const tz = config.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone;
@@ -162,6 +179,7 @@ export function resolveJobPrompt(config) {
162
179
  }
163
180
  return prompt;
164
181
  }
182
+ /** Parse a human-readable timeout string (e.g. "30m", "2h", "1h30m") into milliseconds. */
165
183
  export function parseTimeout(timeout) {
166
184
  const match = timeout.match(/^(?:(\d+)h)?(?:(\d+)m)?$/);
167
185
  if (!match)
@@ -171,6 +189,7 @@ export function parseTimeout(timeout) {
171
189
  const ms = (hours * 60 + minutes) * 60 * 1000;
172
190
  return ms > 0 ? ms : null;
173
191
  }
192
+ /** List all run metadata entries for a job, sorted chronologically. */
174
193
  export function listRuns(jobName) {
175
194
  const runsDir = getRunsDir();
176
195
  const jobRunsDir = path.join(runsDir, jobName);
@@ -188,16 +207,19 @@ export function listRuns(jobName) {
188
207
  }
189
208
  return runs;
190
209
  }
210
+ /** Get the most recent run for a job, or null if never run. */
191
211
  export function getLatestRun(jobName) {
192
212
  const runs = listRuns(jobName);
193
213
  return runs.length > 0 ? runs[runs.length - 1] : null;
194
214
  }
215
+ /** Persist run metadata to its run directory as meta.json. */
195
216
  export function writeRunMeta(meta) {
196
217
  ensureAgentsDir();
197
218
  const runDir = path.join(getRunsDir(), meta.jobName, meta.runId);
198
219
  fs.mkdirSync(runDir, { recursive: true });
199
220
  fs.writeFileSync(path.join(runDir, 'meta.json'), JSON.stringify(meta, null, 2), 'utf-8');
200
221
  }
222
+ /** Read run metadata from disk. Returns null if missing or corrupt. */
201
223
  export function readRunMeta(jobName, runId) {
202
224
  const metaPath = path.join(getRunsDir(), jobName, runId, 'meta.json');
203
225
  if (!fs.existsSync(metaPath))
@@ -209,9 +231,11 @@ export function readRunMeta(jobName, runId) {
209
231
  return null;
210
232
  }
211
233
  }
234
+ /** Get the filesystem path for a specific run's directory. */
212
235
  export function getRunDir(jobName, runId) {
213
236
  return path.join(getRunsDir(), jobName, runId);
214
237
  }
238
+ /** Discover routine YAML files in a repository's routines/ directory. */
215
239
  export function discoverJobsFromRepo(repoPath) {
216
240
  const jobsPath = path.join(repoPath, 'routines');
217
241
  if (!fs.existsSync(jobsPath))
@@ -223,13 +247,15 @@ export function discoverJobsFromRepo(repoPath) {
223
247
  path: path.join(jobsPath, f),
224
248
  }));
225
249
  }
250
+ /** Check whether a job with the given name exists on disk. */
226
251
  export function jobExists(name) {
227
252
  return readJob(name) !== null;
228
253
  }
254
+ /** Get the filesystem path of a job's YAML config file, or null if not found. */
229
255
  export function getJobPath(name) {
230
256
  const jobsDir = getRoutinesDir();
231
257
  for (const ext of ['.yml', '.yaml']) {
232
- const filePath = path.join(jobsDir, name + ext);
258
+ const filePath = safeJoin(jobsDir, name + ext);
233
259
  if (fs.existsSync(filePath)) {
234
260
  return filePath;
235
261
  }
@@ -282,6 +308,7 @@ export function parseAtTime(atTime) {
282
308
  }
283
309
  return null;
284
310
  }
311
+ /** Check if an installed job's normalized YAML matches the source file. */
285
312
  export function jobContentMatches(name, sourcePath) {
286
313
  const existing = readJob(name);
287
314
  if (!existing)
@@ -300,6 +327,7 @@ export function jobContentMatches(name, sourcePath) {
300
327
  return false;
301
328
  }
302
329
  }
330
+ /** Install a job by reading and validating a YAML source file. */
303
331
  export function installJobFromSource(sourcePath, name) {
304
332
  try {
305
333
  const content = fs.readFileSync(sourcePath, 'utf-8');
@@ -322,4 +350,3 @@ export function installJobFromSource(sourcePath, name) {
322
350
  return { success: false, error: err.message };
323
351
  }
324
352
  }
325
- //# sourceMappingURL=routines.js.map
@@ -1,12 +1,25 @@
1
+ /**
2
+ * Job execution engine for routines.
3
+ *
4
+ * Builds agent-specific CLI commands from job configs, spawns them with
5
+ * sandboxed or unsandboxed environments, captures stdout to log files,
6
+ * enforces timeouts, and extracts the final assistant report from the
7
+ * agent's stream-JSON output.
8
+ */
1
9
  import type { JobConfig, RunMeta } from './routines.js';
2
10
  import type { AgentId } from './types.js';
11
+ /** Result of a completed job execution, including metadata and optional report. */
3
12
  export interface RunResult {
4
13
  meta: RunMeta;
5
14
  reportPath: string | null;
6
15
  }
16
+ /** Build the full CLI argv for executing a job, applying mode, model, and permission flags. */
7
17
  export declare function buildJobCommand(config: JobConfig, resolvedPrompt: string): string[];
18
+ /** Execute a job synchronously (waits for completion or timeout before resolving). */
8
19
  export declare function executeJob(config: JobConfig): Promise<RunResult>;
20
+ /** Spawn a job as a detached process and return immediately with run metadata. */
9
21
  export declare function executeJobDetached(config: JobConfig): Promise<RunMeta>;
22
+ /** Extract the final assistant message from a stream-JSON log file as a markdown report. */
10
23
  export declare function extractReport(stdoutPath: string, agentType: AgentId): string | null;
24
+ /** Scan all runs marked "running" and finalize any whose process has exited. */
11
25
  export declare function monitorRunningJobs(): void;
12
- //# sourceMappingURL=runner.d.ts.map