@herdctl/core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (520) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/.turbo/turbo-test.log +219 -0
  3. package/.turbo/turbo-typecheck.log +4 -0
  4. package/coverage/base.css +224 -0
  5. package/coverage/block-navigation.js +87 -0
  6. package/coverage/coverage-final.json +51 -0
  7. package/coverage/favicon.png +0 -0
  8. package/coverage/index.html +251 -0
  9. package/coverage/prettify.css +1 -0
  10. package/coverage/prettify.js +2 -0
  11. package/coverage/sort-arrow-sprite.png +0 -0
  12. package/coverage/sorter.js +210 -0
  13. package/coverage/src/config/index.html +191 -0
  14. package/coverage/src/config/index.ts.html +442 -0
  15. package/coverage/src/config/interpolate.ts.html +652 -0
  16. package/coverage/src/config/loader.ts.html +1501 -0
  17. package/coverage/src/config/merge.ts.html +823 -0
  18. package/coverage/src/config/parser.ts.html +1213 -0
  19. package/coverage/src/config/schema.ts.html +1123 -0
  20. package/coverage/src/fleet-manager/errors.ts.html +2326 -0
  21. package/coverage/src/fleet-manager/event-types.ts.html +1219 -0
  22. package/coverage/src/fleet-manager/fleet-manager.ts.html +7030 -0
  23. package/coverage/src/fleet-manager/index.html +206 -0
  24. package/coverage/src/fleet-manager/index.ts.html +469 -0
  25. package/coverage/src/fleet-manager/job-manager.ts.html +2074 -0
  26. package/coverage/src/fleet-manager/job-queue.ts.html +2479 -0
  27. package/coverage/src/fleet-manager/types.ts.html +2602 -0
  28. package/coverage/src/index.html +116 -0
  29. package/coverage/src/index.ts.html +181 -0
  30. package/coverage/src/runner/errors.ts.html +1006 -0
  31. package/coverage/src/runner/index.html +191 -0
  32. package/coverage/src/runner/index.ts.html +256 -0
  33. package/coverage/src/runner/job-executor.ts.html +1429 -0
  34. package/coverage/src/runner/message-processor.ts.html +1150 -0
  35. package/coverage/src/runner/sdk-adapter.ts.html +658 -0
  36. package/coverage/src/runner/types.ts.html +559 -0
  37. package/coverage/src/scheduler/errors.ts.html +388 -0
  38. package/coverage/src/scheduler/index.html +206 -0
  39. package/coverage/src/scheduler/index.ts.html +244 -0
  40. package/coverage/src/scheduler/interval.ts.html +652 -0
  41. package/coverage/src/scheduler/schedule-runner.ts.html +1411 -0
  42. package/coverage/src/scheduler/schedule-state.ts.html +718 -0
  43. package/coverage/src/scheduler/scheduler.ts.html +1795 -0
  44. package/coverage/src/scheduler/types.ts.html +733 -0
  45. package/coverage/src/state/directory.ts.html +736 -0
  46. package/coverage/src/state/errors.ts.html +376 -0
  47. package/coverage/src/state/fleet-state.ts.html +937 -0
  48. package/coverage/src/state/index.html +221 -0
  49. package/coverage/src/state/index.ts.html +322 -0
  50. package/coverage/src/state/job-metadata.ts.html +1420 -0
  51. package/coverage/src/state/job-output.ts.html +1033 -0
  52. package/coverage/src/state/schemas/fleet-state.ts.html +445 -0
  53. package/coverage/src/state/schemas/index.html +176 -0
  54. package/coverage/src/state/schemas/index.ts.html +286 -0
  55. package/coverage/src/state/schemas/job-metadata.ts.html +628 -0
  56. package/coverage/src/state/schemas/job-output.ts.html +616 -0
  57. package/coverage/src/state/schemas/session-info.ts.html +361 -0
  58. package/coverage/src/state/session.ts.html +844 -0
  59. package/coverage/src/state/types.ts.html +262 -0
  60. package/coverage/src/state/utils/atomic.ts.html +748 -0
  61. package/coverage/src/state/utils/index.html +146 -0
  62. package/coverage/src/state/utils/index.ts.html +103 -0
  63. package/coverage/src/state/utils/reads.ts.html +1621 -0
  64. package/coverage/src/work-sources/adapters/github.ts.html +3583 -0
  65. package/coverage/src/work-sources/adapters/index.html +131 -0
  66. package/coverage/src/work-sources/adapters/index.ts.html +277 -0
  67. package/coverage/src/work-sources/errors.ts.html +298 -0
  68. package/coverage/src/work-sources/index.html +176 -0
  69. package/coverage/src/work-sources/index.ts.html +529 -0
  70. package/coverage/src/work-sources/manager.ts.html +1324 -0
  71. package/coverage/src/work-sources/registry.ts.html +619 -0
  72. package/coverage/src/work-sources/types.ts.html +568 -0
  73. package/dist/config/__tests__/agent.test.d.ts +2 -0
  74. package/dist/config/__tests__/agent.test.d.ts.map +1 -0
  75. package/dist/config/__tests__/agent.test.js +752 -0
  76. package/dist/config/__tests__/agent.test.js.map +1 -0
  77. package/dist/config/__tests__/interpolate.test.d.ts +2 -0
  78. package/dist/config/__tests__/interpolate.test.d.ts.map +1 -0
  79. package/dist/config/__tests__/interpolate.test.js +509 -0
  80. package/dist/config/__tests__/interpolate.test.js.map +1 -0
  81. package/dist/config/__tests__/loader.test.d.ts +2 -0
  82. package/dist/config/__tests__/loader.test.d.ts.map +1 -0
  83. package/dist/config/__tests__/loader.test.js +631 -0
  84. package/dist/config/__tests__/loader.test.js.map +1 -0
  85. package/dist/config/__tests__/merge.test.d.ts +2 -0
  86. package/dist/config/__tests__/merge.test.d.ts.map +1 -0
  87. package/dist/config/__tests__/merge.test.js +672 -0
  88. package/dist/config/__tests__/merge.test.js.map +1 -0
  89. package/dist/config/__tests__/parser.test.d.ts +2 -0
  90. package/dist/config/__tests__/parser.test.d.ts.map +1 -0
  91. package/dist/config/__tests__/parser.test.js +476 -0
  92. package/dist/config/__tests__/parser.test.js.map +1 -0
  93. package/dist/config/__tests__/schema.test.d.ts +2 -0
  94. package/dist/config/__tests__/schema.test.d.ts.map +1 -0
  95. package/dist/config/__tests__/schema.test.js +776 -0
  96. package/dist/config/__tests__/schema.test.js.map +1 -0
  97. package/dist/config/index.d.ts +11 -0
  98. package/dist/config/index.d.ts.map +1 -0
  99. package/dist/config/index.js +26 -0
  100. package/dist/config/index.js.map +1 -0
  101. package/dist/config/interpolate.d.ts +76 -0
  102. package/dist/config/interpolate.d.ts.map +1 -0
  103. package/dist/config/interpolate.js +143 -0
  104. package/dist/config/interpolate.js.map +1 -0
  105. package/dist/config/loader.d.ts +147 -0
  106. package/dist/config/loader.d.ts.map +1 -0
  107. package/dist/config/loader.js +336 -0
  108. package/dist/config/loader.js.map +1 -0
  109. package/dist/config/merge.d.ts +84 -0
  110. package/dist/config/merge.d.ts.map +1 -0
  111. package/dist/config/merge.js +138 -0
  112. package/dist/config/merge.js.map +1 -0
  113. package/dist/config/parser.d.ts +143 -0
  114. package/dist/config/parser.d.ts.map +1 -0
  115. package/dist/config/parser.js +316 -0
  116. package/dist/config/parser.js.map +1 -0
  117. package/dist/config/schema.d.ts +1906 -0
  118. package/dist/config/schema.d.ts.map +1 -0
  119. package/dist/config/schema.js +268 -0
  120. package/dist/config/schema.js.map +1 -0
  121. package/dist/fleet-manager/__tests__/coverage.test.d.ts +13 -0
  122. package/dist/fleet-manager/__tests__/coverage.test.d.ts.map +1 -0
  123. package/dist/fleet-manager/__tests__/coverage.test.js +2282 -0
  124. package/dist/fleet-manager/__tests__/coverage.test.js.map +1 -0
  125. package/dist/fleet-manager/__tests__/errors.test.d.ts +7 -0
  126. package/dist/fleet-manager/__tests__/errors.test.d.ts.map +1 -0
  127. package/dist/fleet-manager/__tests__/errors.test.js +557 -0
  128. package/dist/fleet-manager/__tests__/errors.test.js.map +1 -0
  129. package/dist/fleet-manager/__tests__/event-helpers.test.d.ts +7 -0
  130. package/dist/fleet-manager/__tests__/event-helpers.test.d.ts.map +1 -0
  131. package/dist/fleet-manager/__tests__/event-helpers.test.js +368 -0
  132. package/dist/fleet-manager/__tests__/event-helpers.test.js.map +1 -0
  133. package/dist/fleet-manager/__tests__/integration.test.d.ts +11 -0
  134. package/dist/fleet-manager/__tests__/integration.test.d.ts.map +1 -0
  135. package/dist/fleet-manager/__tests__/integration.test.js +949 -0
  136. package/dist/fleet-manager/__tests__/integration.test.js.map +1 -0
  137. package/dist/fleet-manager/__tests__/job-control.test.d.ts +7 -0
  138. package/dist/fleet-manager/__tests__/job-control.test.d.ts.map +1 -0
  139. package/dist/fleet-manager/__tests__/job-control.test.js +215 -0
  140. package/dist/fleet-manager/__tests__/job-control.test.js.map +1 -0
  141. package/dist/fleet-manager/__tests__/job-manager.test.d.ts +7 -0
  142. package/dist/fleet-manager/__tests__/job-manager.test.d.ts.map +1 -0
  143. package/dist/fleet-manager/__tests__/job-manager.test.js +659 -0
  144. package/dist/fleet-manager/__tests__/job-manager.test.js.map +1 -0
  145. package/dist/fleet-manager/__tests__/job-queue.test.d.ts +5 -0
  146. package/dist/fleet-manager/__tests__/job-queue.test.d.ts.map +1 -0
  147. package/dist/fleet-manager/__tests__/job-queue.test.js +315 -0
  148. package/dist/fleet-manager/__tests__/job-queue.test.js.map +1 -0
  149. package/dist/fleet-manager/__tests__/reload.test.d.ts +7 -0
  150. package/dist/fleet-manager/__tests__/reload.test.d.ts.map +1 -0
  151. package/dist/fleet-manager/__tests__/reload.test.js +609 -0
  152. package/dist/fleet-manager/__tests__/reload.test.js.map +1 -0
  153. package/dist/fleet-manager/__tests__/status-queries.test.d.ts +7 -0
  154. package/dist/fleet-manager/__tests__/status-queries.test.d.ts.map +1 -0
  155. package/dist/fleet-manager/__tests__/status-queries.test.js +488 -0
  156. package/dist/fleet-manager/__tests__/status-queries.test.js.map +1 -0
  157. package/dist/fleet-manager/__tests__/trigger.test.d.ts +7 -0
  158. package/dist/fleet-manager/__tests__/trigger.test.d.ts.map +1 -0
  159. package/dist/fleet-manager/__tests__/trigger.test.js +471 -0
  160. package/dist/fleet-manager/__tests__/trigger.test.js.map +1 -0
  161. package/dist/fleet-manager/errors.d.ts +407 -0
  162. package/dist/fleet-manager/errors.d.ts.map +1 -0
  163. package/dist/fleet-manager/errors.js +569 -0
  164. package/dist/fleet-manager/errors.js.map +1 -0
  165. package/dist/fleet-manager/event-types.d.ts +302 -0
  166. package/dist/fleet-manager/event-types.d.ts.map +1 -0
  167. package/dist/fleet-manager/event-types.js +9 -0
  168. package/dist/fleet-manager/event-types.js.map +1 -0
  169. package/dist/fleet-manager/fleet-manager.d.ts +699 -0
  170. package/dist/fleet-manager/fleet-manager.d.ts.map +1 -0
  171. package/dist/fleet-manager/fleet-manager.js +1906 -0
  172. package/dist/fleet-manager/fleet-manager.js.map +1 -0
  173. package/dist/fleet-manager/index.d.ts +17 -0
  174. package/dist/fleet-manager/index.d.ts.map +1 -0
  175. package/dist/fleet-manager/index.js +29 -0
  176. package/dist/fleet-manager/index.js.map +1 -0
  177. package/dist/fleet-manager/job-manager.d.ts +271 -0
  178. package/dist/fleet-manager/job-manager.d.ts.map +1 -0
  179. package/dist/fleet-manager/job-manager.js +443 -0
  180. package/dist/fleet-manager/job-manager.js.map +1 -0
  181. package/dist/fleet-manager/job-queue.d.ts +422 -0
  182. package/dist/fleet-manager/job-queue.d.ts.map +1 -0
  183. package/dist/fleet-manager/job-queue.js +448 -0
  184. package/dist/fleet-manager/job-queue.js.map +1 -0
  185. package/dist/fleet-manager/types.d.ts +680 -0
  186. package/dist/fleet-manager/types.d.ts.map +1 -0
  187. package/dist/fleet-manager/types.js +8 -0
  188. package/dist/fleet-manager/types.js.map +1 -0
  189. package/dist/index.d.ts +20 -0
  190. package/dist/index.d.ts.map +1 -0
  191. package/dist/index.js +26 -0
  192. package/dist/index.js.map +1 -0
  193. package/dist/runner/__tests__/errors.test.d.ts +2 -0
  194. package/dist/runner/__tests__/errors.test.d.ts.map +1 -0
  195. package/dist/runner/__tests__/errors.test.js +264 -0
  196. package/dist/runner/__tests__/errors.test.js.map +1 -0
  197. package/dist/runner/__tests__/job-executor.test.d.ts +2 -0
  198. package/dist/runner/__tests__/job-executor.test.d.ts.map +1 -0
  199. package/dist/runner/__tests__/job-executor.test.js +1345 -0
  200. package/dist/runner/__tests__/job-executor.test.js.map +1 -0
  201. package/dist/runner/__tests__/message-processor.test.d.ts +2 -0
  202. package/dist/runner/__tests__/message-processor.test.d.ts.map +1 -0
  203. package/dist/runner/__tests__/message-processor.test.js +768 -0
  204. package/dist/runner/__tests__/message-processor.test.js.map +1 -0
  205. package/dist/runner/__tests__/sdk-adapter.test.d.ts +2 -0
  206. package/dist/runner/__tests__/sdk-adapter.test.d.ts.map +1 -0
  207. package/dist/runner/__tests__/sdk-adapter.test.js +554 -0
  208. package/dist/runner/__tests__/sdk-adapter.test.js.map +1 -0
  209. package/dist/runner/errors.d.ts +121 -0
  210. package/dist/runner/errors.d.ts.map +1 -0
  211. package/dist/runner/errors.js +212 -0
  212. package/dist/runner/errors.js.map +1 -0
  213. package/dist/runner/index.d.ts +12 -0
  214. package/dist/runner/index.d.ts.map +1 -0
  215. package/dist/runner/index.js +15 -0
  216. package/dist/runner/index.js.map +1 -0
  217. package/dist/runner/job-executor.d.ts +98 -0
  218. package/dist/runner/job-executor.d.ts.map +1 -0
  219. package/dist/runner/job-executor.js +333 -0
  220. package/dist/runner/job-executor.js.map +1 -0
  221. package/dist/runner/message-processor.d.ts +45 -0
  222. package/dist/runner/message-processor.d.ts.map +1 -0
  223. package/dist/runner/message-processor.js +294 -0
  224. package/dist/runner/message-processor.js.map +1 -0
  225. package/dist/runner/sdk-adapter.d.ts +60 -0
  226. package/dist/runner/sdk-adapter.d.ts.map +1 -0
  227. package/dist/runner/sdk-adapter.js +138 -0
  228. package/dist/runner/sdk-adapter.js.map +1 -0
  229. package/dist/runner/types.d.ts +135 -0
  230. package/dist/runner/types.d.ts.map +1 -0
  231. package/dist/runner/types.js +7 -0
  232. package/dist/runner/types.js.map +1 -0
  233. package/dist/scheduler/__tests__/errors.test.d.ts +2 -0
  234. package/dist/scheduler/__tests__/errors.test.d.ts.map +1 -0
  235. package/dist/scheduler/__tests__/errors.test.js +101 -0
  236. package/dist/scheduler/__tests__/errors.test.js.map +1 -0
  237. package/dist/scheduler/__tests__/interval.test.d.ts +2 -0
  238. package/dist/scheduler/__tests__/interval.test.d.ts.map +1 -0
  239. package/dist/scheduler/__tests__/interval.test.js +419 -0
  240. package/dist/scheduler/__tests__/interval.test.js.map +1 -0
  241. package/dist/scheduler/__tests__/schedule-runner.test.d.ts +2 -0
  242. package/dist/scheduler/__tests__/schedule-runner.test.d.ts.map +1 -0
  243. package/dist/scheduler/__tests__/schedule-runner.test.js +634 -0
  244. package/dist/scheduler/__tests__/schedule-runner.test.js.map +1 -0
  245. package/dist/scheduler/__tests__/schedule-state.test.d.ts +2 -0
  246. package/dist/scheduler/__tests__/schedule-state.test.d.ts.map +1 -0
  247. package/dist/scheduler/__tests__/schedule-state.test.js +572 -0
  248. package/dist/scheduler/__tests__/schedule-state.test.js.map +1 -0
  249. package/dist/scheduler/__tests__/scheduler.test.d.ts +2 -0
  250. package/dist/scheduler/__tests__/scheduler.test.d.ts.map +1 -0
  251. package/dist/scheduler/__tests__/scheduler.test.js +987 -0
  252. package/dist/scheduler/__tests__/scheduler.test.js.map +1 -0
  253. package/dist/scheduler/errors.d.ts +61 -0
  254. package/dist/scheduler/errors.d.ts.map +1 -0
  255. package/dist/scheduler/errors.js +81 -0
  256. package/dist/scheduler/errors.js.map +1 -0
  257. package/dist/scheduler/index.d.ts +13 -0
  258. package/dist/scheduler/index.d.ts.map +1 -0
  259. package/dist/scheduler/index.js +17 -0
  260. package/dist/scheduler/index.js.map +1 -0
  261. package/dist/scheduler/interval.d.ts +64 -0
  262. package/dist/scheduler/interval.d.ts.map +1 -0
  263. package/dist/scheduler/interval.js +139 -0
  264. package/dist/scheduler/interval.js.map +1 -0
  265. package/dist/scheduler/schedule-runner.d.ts +149 -0
  266. package/dist/scheduler/schedule-runner.d.ts.map +1 -0
  267. package/dist/scheduler/schedule-runner.js +277 -0
  268. package/dist/scheduler/schedule-runner.js.map +1 -0
  269. package/dist/scheduler/schedule-state.d.ts +105 -0
  270. package/dist/scheduler/schedule-state.d.ts.map +1 -0
  271. package/dist/scheduler/schedule-state.js +151 -0
  272. package/dist/scheduler/schedule-state.js.map +1 -0
  273. package/dist/scheduler/scheduler.d.ts +138 -0
  274. package/dist/scheduler/scheduler.d.ts.map +1 -0
  275. package/dist/scheduler/scheduler.js +423 -0
  276. package/dist/scheduler/scheduler.js.map +1 -0
  277. package/dist/scheduler/types.d.ts +160 -0
  278. package/dist/scheduler/types.d.ts.map +1 -0
  279. package/dist/scheduler/types.js +8 -0
  280. package/dist/scheduler/types.js.map +1 -0
  281. package/dist/state/__tests__/directory.test.d.ts +2 -0
  282. package/dist/state/__tests__/directory.test.d.ts.map +1 -0
  283. package/dist/state/__tests__/directory.test.js +414 -0
  284. package/dist/state/__tests__/directory.test.js.map +1 -0
  285. package/dist/state/__tests__/fleet-state.test.d.ts +2 -0
  286. package/dist/state/__tests__/fleet-state.test.d.ts.map +1 -0
  287. package/dist/state/__tests__/fleet-state.test.js +696 -0
  288. package/dist/state/__tests__/fleet-state.test.js.map +1 -0
  289. package/dist/state/__tests__/job-metadata-schema.test.d.ts +2 -0
  290. package/dist/state/__tests__/job-metadata-schema.test.d.ts.map +1 -0
  291. package/dist/state/__tests__/job-metadata-schema.test.js +329 -0
  292. package/dist/state/__tests__/job-metadata-schema.test.js.map +1 -0
  293. package/dist/state/__tests__/job-metadata.test.d.ts +2 -0
  294. package/dist/state/__tests__/job-metadata.test.d.ts.map +1 -0
  295. package/dist/state/__tests__/job-metadata.test.js +667 -0
  296. package/dist/state/__tests__/job-metadata.test.js.map +1 -0
  297. package/dist/state/__tests__/job-output.test.d.ts +2 -0
  298. package/dist/state/__tests__/job-output.test.d.ts.map +1 -0
  299. package/dist/state/__tests__/job-output.test.js +672 -0
  300. package/dist/state/__tests__/job-output.test.js.map +1 -0
  301. package/dist/state/__tests__/session-schema.test.d.ts +2 -0
  302. package/dist/state/__tests__/session-schema.test.d.ts.map +1 -0
  303. package/dist/state/__tests__/session-schema.test.js +323 -0
  304. package/dist/state/__tests__/session-schema.test.js.map +1 -0
  305. package/dist/state/__tests__/session.test.d.ts +2 -0
  306. package/dist/state/__tests__/session.test.d.ts.map +1 -0
  307. package/dist/state/__tests__/session.test.js +468 -0
  308. package/dist/state/__tests__/session.test.js.map +1 -0
  309. package/dist/state/directory.d.ts +42 -0
  310. package/dist/state/directory.d.ts.map +1 -0
  311. package/dist/state/directory.js +170 -0
  312. package/dist/state/directory.js.map +1 -0
  313. package/dist/state/errors.d.ts +44 -0
  314. package/dist/state/errors.d.ts.map +1 -0
  315. package/dist/state/errors.js +82 -0
  316. package/dist/state/errors.js.map +1 -0
  317. package/dist/state/fleet-state.d.ts +126 -0
  318. package/dist/state/fleet-state.d.ts.map +1 -0
  319. package/dist/state/fleet-state.js +196 -0
  320. package/dist/state/fleet-state.js.map +1 -0
  321. package/dist/state/index.d.ts +21 -0
  322. package/dist/state/index.d.ts.map +1 -0
  323. package/dist/state/index.js +30 -0
  324. package/dist/state/index.js.map +1 -0
  325. package/dist/state/job-metadata.d.ts +151 -0
  326. package/dist/state/job-metadata.d.ts.map +1 -0
  327. package/dist/state/job-metadata.js +287 -0
  328. package/dist/state/job-metadata.js.map +1 -0
  329. package/dist/state/job-output.d.ts +116 -0
  330. package/dist/state/job-output.d.ts.map +1 -0
  331. package/dist/state/job-output.js +218 -0
  332. package/dist/state/job-output.js.map +1 -0
  333. package/dist/state/schemas/__tests__/job-output.test.d.ts +2 -0
  334. package/dist/state/schemas/__tests__/job-output.test.d.ts.map +1 -0
  335. package/dist/state/schemas/__tests__/job-output.test.js +279 -0
  336. package/dist/state/schemas/__tests__/job-output.test.js.map +1 -0
  337. package/dist/state/schemas/fleet-state.d.ts +249 -0
  338. package/dist/state/schemas/fleet-state.d.ts.map +1 -0
  339. package/dist/state/schemas/fleet-state.js +97 -0
  340. package/dist/state/schemas/fleet-state.js.map +1 -0
  341. package/dist/state/schemas/index.d.ts +10 -0
  342. package/dist/state/schemas/index.d.ts.map +1 -0
  343. package/dist/state/schemas/index.js +10 -0
  344. package/dist/state/schemas/index.js.map +1 -0
  345. package/dist/state/schemas/job-metadata.d.ts +118 -0
  346. package/dist/state/schemas/job-metadata.d.ts.map +1 -0
  347. package/dist/state/schemas/job-metadata.js +123 -0
  348. package/dist/state/schemas/job-metadata.js.map +1 -0
  349. package/dist/state/schemas/job-output.d.ts +291 -0
  350. package/dist/state/schemas/job-output.d.ts.map +1 -0
  351. package/dist/state/schemas/job-output.js +132 -0
  352. package/dist/state/schemas/job-output.js.map +1 -0
  353. package/dist/state/schemas/session-info.d.ts +65 -0
  354. package/dist/state/schemas/session-info.d.ts.map +1 -0
  355. package/dist/state/schemas/session-info.js +58 -0
  356. package/dist/state/schemas/session-info.js.map +1 -0
  357. package/dist/state/session.d.ts +92 -0
  358. package/dist/state/session.d.ts.map +1 -0
  359. package/dist/state/session.js +173 -0
  360. package/dist/state/session.js.map +1 -0
  361. package/dist/state/types.d.ts +54 -0
  362. package/dist/state/types.d.ts.map +1 -0
  363. package/dist/state/types.js +18 -0
  364. package/dist/state/types.js.map +1 -0
  365. package/dist/state/utils/__tests__/atomic.test.d.ts +2 -0
  366. package/dist/state/utils/__tests__/atomic.test.d.ts.map +1 -0
  367. package/dist/state/utils/__tests__/atomic.test.js +537 -0
  368. package/dist/state/utils/__tests__/atomic.test.js.map +1 -0
  369. package/dist/state/utils/__tests__/reads.test.d.ts +2 -0
  370. package/dist/state/utils/__tests__/reads.test.d.ts.map +1 -0
  371. package/dist/state/utils/__tests__/reads.test.js +792 -0
  372. package/dist/state/utils/__tests__/reads.test.js.map +1 -0
  373. package/dist/state/utils/atomic.d.ts +89 -0
  374. package/dist/state/utils/atomic.d.ts.map +1 -0
  375. package/dist/state/utils/atomic.js +157 -0
  376. package/dist/state/utils/atomic.js.map +1 -0
  377. package/dist/state/utils/index.d.ts +6 -0
  378. package/dist/state/utils/index.d.ts.map +1 -0
  379. package/dist/state/utils/index.js +6 -0
  380. package/dist/state/utils/index.js.map +1 -0
  381. package/dist/state/utils/reads.d.ts +196 -0
  382. package/dist/state/utils/reads.d.ts.map +1 -0
  383. package/dist/state/utils/reads.js +346 -0
  384. package/dist/state/utils/reads.js.map +1 -0
  385. package/dist/work-sources/__tests__/github.test.d.ts +2 -0
  386. package/dist/work-sources/__tests__/github.test.d.ts.map +1 -0
  387. package/dist/work-sources/__tests__/github.test.js +1334 -0
  388. package/dist/work-sources/__tests__/github.test.js.map +1 -0
  389. package/dist/work-sources/__tests__/manager.test.d.ts +2 -0
  390. package/dist/work-sources/__tests__/manager.test.d.ts.map +1 -0
  391. package/dist/work-sources/__tests__/manager.test.js +424 -0
  392. package/dist/work-sources/__tests__/manager.test.js.map +1 -0
  393. package/dist/work-sources/__tests__/registry.test.d.ts +2 -0
  394. package/dist/work-sources/__tests__/registry.test.d.ts.map +1 -0
  395. package/dist/work-sources/__tests__/registry.test.js +381 -0
  396. package/dist/work-sources/__tests__/registry.test.js.map +1 -0
  397. package/dist/work-sources/__tests__/types.test.d.ts +2 -0
  398. package/dist/work-sources/__tests__/types.test.d.ts.map +1 -0
  399. package/dist/work-sources/__tests__/types.test.js +406 -0
  400. package/dist/work-sources/__tests__/types.test.js.map +1 -0
  401. package/dist/work-sources/adapters/github.d.ts +290 -0
  402. package/dist/work-sources/adapters/github.d.ts.map +1 -0
  403. package/dist/work-sources/adapters/github.js +803 -0
  404. package/dist/work-sources/adapters/github.js.map +1 -0
  405. package/dist/work-sources/adapters/index.d.ts +10 -0
  406. package/dist/work-sources/adapters/index.d.ts.map +1 -0
  407. package/dist/work-sources/adapters/index.js +31 -0
  408. package/dist/work-sources/adapters/index.js.map +1 -0
  409. package/dist/work-sources/errors.d.ts +40 -0
  410. package/dist/work-sources/errors.d.ts.map +1 -0
  411. package/dist/work-sources/errors.js +54 -0
  412. package/dist/work-sources/errors.js.map +1 -0
  413. package/dist/work-sources/index.d.ts +105 -0
  414. package/dist/work-sources/index.d.ts.map +1 -0
  415. package/dist/work-sources/index.js +24 -0
  416. package/dist/work-sources/index.js.map +1 -0
  417. package/dist/work-sources/manager.d.ts +370 -0
  418. package/dist/work-sources/manager.d.ts.map +1 -0
  419. package/dist/work-sources/manager.js +61 -0
  420. package/dist/work-sources/manager.js.map +1 -0
  421. package/dist/work-sources/registry.d.ts +128 -0
  422. package/dist/work-sources/registry.d.ts.map +1 -0
  423. package/dist/work-sources/registry.js +132 -0
  424. package/dist/work-sources/registry.js.map +1 -0
  425. package/dist/work-sources/types.d.ts +127 -0
  426. package/dist/work-sources/types.d.ts.map +1 -0
  427. package/dist/work-sources/types.js +8 -0
  428. package/dist/work-sources/types.js.map +1 -0
  429. package/package.json +23 -0
  430. package/src/config/__tests__/agent.test.ts +864 -0
  431. package/src/config/__tests__/interpolate.test.ts +644 -0
  432. package/src/config/__tests__/loader.test.ts +784 -0
  433. package/src/config/__tests__/merge.test.ts +751 -0
  434. package/src/config/__tests__/parser.test.ts +533 -0
  435. package/src/config/__tests__/schema.test.ts +873 -0
  436. package/src/config/index.ts +119 -0
  437. package/src/config/interpolate.ts +189 -0
  438. package/src/config/loader.ts +472 -0
  439. package/src/config/merge.ts +246 -0
  440. package/src/config/parser.ts +376 -0
  441. package/src/config/schema.ts +346 -0
  442. package/src/fleet-manager/__tests__/coverage.test.ts +2869 -0
  443. package/src/fleet-manager/__tests__/errors.test.ts +660 -0
  444. package/src/fleet-manager/__tests__/event-helpers.test.ts +448 -0
  445. package/src/fleet-manager/__tests__/integration.test.ts +1209 -0
  446. package/src/fleet-manager/__tests__/job-control.test.ts +283 -0
  447. package/src/fleet-manager/__tests__/job-manager.test.ts +869 -0
  448. package/src/fleet-manager/__tests__/job-queue.test.ts +401 -0
  449. package/src/fleet-manager/__tests__/reload.test.ts +751 -0
  450. package/src/fleet-manager/__tests__/status-queries.test.ts +595 -0
  451. package/src/fleet-manager/__tests__/trigger.test.ts +601 -0
  452. package/src/fleet-manager/errors.ts +747 -0
  453. package/src/fleet-manager/event-types.ts +378 -0
  454. package/src/fleet-manager/fleet-manager.ts +2315 -0
  455. package/src/fleet-manager/index.ts +128 -0
  456. package/src/fleet-manager/job-manager.ts +663 -0
  457. package/src/fleet-manager/job-queue.ts +798 -0
  458. package/src/fleet-manager/types.ts +839 -0
  459. package/src/index.ts +32 -0
  460. package/src/runner/__tests__/errors.test.ts +382 -0
  461. package/src/runner/__tests__/job-executor.test.ts +1708 -0
  462. package/src/runner/__tests__/message-processor.test.ts +960 -0
  463. package/src/runner/__tests__/sdk-adapter.test.ts +626 -0
  464. package/src/runner/errors.ts +307 -0
  465. package/src/runner/index.ts +57 -0
  466. package/src/runner/job-executor.ts +448 -0
  467. package/src/runner/message-processor.ts +355 -0
  468. package/src/runner/sdk-adapter.ts +191 -0
  469. package/src/runner/types.ts +158 -0
  470. package/src/scheduler/__tests__/errors.test.ts +159 -0
  471. package/src/scheduler/__tests__/interval.test.ts +515 -0
  472. package/src/scheduler/__tests__/schedule-runner.test.ts +798 -0
  473. package/src/scheduler/__tests__/schedule-state.test.ts +671 -0
  474. package/src/scheduler/__tests__/scheduler.test.ts +1280 -0
  475. package/src/scheduler/errors.ts +101 -0
  476. package/src/scheduler/index.ts +53 -0
  477. package/src/scheduler/interval.ts +189 -0
  478. package/src/scheduler/schedule-runner.ts +442 -0
  479. package/src/scheduler/schedule-state.ts +211 -0
  480. package/src/scheduler/scheduler.ts +570 -0
  481. package/src/scheduler/types.ts +216 -0
  482. package/src/state/__tests__/directory.test.ts +595 -0
  483. package/src/state/__tests__/fleet-state.test.ts +868 -0
  484. package/src/state/__tests__/job-metadata-schema.test.ts +414 -0
  485. package/src/state/__tests__/job-metadata.test.ts +831 -0
  486. package/src/state/__tests__/job-output.test.ts +856 -0
  487. package/src/state/__tests__/session-schema.test.ts +378 -0
  488. package/src/state/__tests__/session.test.ts +604 -0
  489. package/src/state/directory.ts +217 -0
  490. package/src/state/errors.ts +97 -0
  491. package/src/state/fleet-state.ts +284 -0
  492. package/src/state/index.ts +79 -0
  493. package/src/state/job-metadata.ts +445 -0
  494. package/src/state/job-output.ts +316 -0
  495. package/src/state/schemas/__tests__/job-output.test.ts +338 -0
  496. package/src/state/schemas/fleet-state.ts +120 -0
  497. package/src/state/schemas/index.ts +67 -0
  498. package/src/state/schemas/job-metadata.ts +181 -0
  499. package/src/state/schemas/job-output.ts +177 -0
  500. package/src/state/schemas/session-info.ts +92 -0
  501. package/src/state/session.ts +253 -0
  502. package/src/state/types.ts +59 -0
  503. package/src/state/utils/__tests__/atomic.test.ts +723 -0
  504. package/src/state/utils/__tests__/reads.test.ts +1071 -0
  505. package/src/state/utils/atomic.ts +221 -0
  506. package/src/state/utils/index.ts +6 -0
  507. package/src/state/utils/reads.ts +512 -0
  508. package/src/work-sources/__tests__/github.test.ts +1800 -0
  509. package/src/work-sources/__tests__/manager.test.ts +529 -0
  510. package/src/work-sources/__tests__/registry.test.ts +477 -0
  511. package/src/work-sources/__tests__/types.test.ts +479 -0
  512. package/src/work-sources/adapters/github.ts +1166 -0
  513. package/src/work-sources/adapters/index.ts +64 -0
  514. package/src/work-sources/errors.ts +71 -0
  515. package/src/work-sources/index.ts +148 -0
  516. package/src/work-sources/manager.ts +413 -0
  517. package/src/work-sources/registry.ts +178 -0
  518. package/src/work-sources/types.ts +161 -0
  519. package/tsconfig.json +9 -0
  520. package/vitest.config.ts +19 -0
@@ -0,0 +1,570 @@
1
+ /**
2
+ * Scheduler class for managing agent schedule execution
3
+ *
4
+ * The Scheduler continuously checks all agents' interval schedules and triggers
5
+ * due agents according to their configured intervals.
6
+ */
7
+
8
+ import type { ResolvedAgent } from "../config/index.js";
9
+ import { calculateNextTrigger, isScheduleDue } from "./interval.js";
10
+ import {
11
+ getScheduleState,
12
+ updateScheduleState,
13
+ type ScheduleStateLogger,
14
+ } from "./schedule-state.js";
15
+ import type {
16
+ SchedulerOptions,
17
+ SchedulerStatus,
18
+ SchedulerState,
19
+ SchedulerLogger,
20
+ ScheduleCheckResult,
21
+ ScheduleSkipReason,
22
+ TriggerInfo,
23
+ SchedulerTriggerCallback,
24
+ StopOptions,
25
+ } from "./types.js";
26
+ import { SchedulerShutdownError } from "./errors.js";
27
+
28
+ // =============================================================================
29
+ // Constants
30
+ // =============================================================================
31
+
32
+ /**
33
+ * Default check interval in milliseconds (1 second)
34
+ */
35
+ const DEFAULT_CHECK_INTERVAL = 1000;
36
+
37
+ /**
38
+ * Default shutdown timeout in milliseconds (30 seconds)
39
+ */
40
+ const DEFAULT_SHUTDOWN_TIMEOUT = 30000;
41
+
42
+ // =============================================================================
43
+ // Default Logger
44
+ // =============================================================================
45
+
46
+ /**
47
+ * Create a default console-based logger
48
+ */
49
+ function createDefaultLogger(): SchedulerLogger {
50
+ return {
51
+ debug: (message: string) => console.debug(`[scheduler] ${message}`),
52
+ info: (message: string) => console.info(`[scheduler] ${message}`),
53
+ warn: (message: string) => console.warn(`[scheduler] ${message}`),
54
+ error: (message: string) => console.error(`[scheduler] ${message}`),
55
+ };
56
+ }
57
+
58
+ // =============================================================================
59
+ // Scheduler Class
60
+ // =============================================================================
61
+
62
+ /**
63
+ * Scheduler for managing agent schedule execution
64
+ *
65
+ * The Scheduler runs a polling loop that:
66
+ * 1. Checks all agents' interval schedules on each iteration
67
+ * 2. Skips non-interval schedule types (cron, webhook, chat)
68
+ * 3. Skips disabled schedules
69
+ * 4. Skips agents at max_concurrent capacity
70
+ * 5. Triggers due schedules via the onTrigger callback
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * const scheduler = new Scheduler({
75
+ * stateDir: '.herdctl',
76
+ * checkInterval: 1000, // 1 second
77
+ * onTrigger: async (info) => {
78
+ * console.log(`Triggering ${info.agent.name}/${info.scheduleName}`);
79
+ * await runAgent(info.agent, info.schedule);
80
+ * },
81
+ * });
82
+ *
83
+ * // Start the scheduler
84
+ * await scheduler.start(agents);
85
+ *
86
+ * // Later, stop the scheduler
87
+ * await scheduler.stop();
88
+ * ```
89
+ */
90
+ export class Scheduler {
91
+ private readonly checkInterval: number;
92
+ private readonly stateDir: string;
93
+ private readonly logger: SchedulerLogger;
94
+ private readonly onTrigger?: SchedulerTriggerCallback;
95
+
96
+ private status: SchedulerStatus = "stopped";
97
+ private abortController: AbortController | null = null;
98
+ private agents: ResolvedAgent[] = [];
99
+ private runningSchedules: Map<string, Set<string>> = new Map();
100
+ private runningJobs: Map<string, Promise<void>> = new Map();
101
+
102
+ private startedAt: string | null = null;
103
+ private checkCount = 0;
104
+ private triggerCount = 0;
105
+ private lastCheckAt: string | null = null;
106
+
107
+ constructor(options: SchedulerOptions) {
108
+ this.checkInterval = options.checkInterval ?? DEFAULT_CHECK_INTERVAL;
109
+ this.stateDir = options.stateDir;
110
+ this.logger = options.logger ?? createDefaultLogger();
111
+ this.onTrigger = options.onTrigger;
112
+ }
113
+
114
+ /**
115
+ * Check if the scheduler is currently running
116
+ */
117
+ isRunning(): boolean {
118
+ return this.status === "running";
119
+ }
120
+
121
+ /**
122
+ * Get the current scheduler status
123
+ */
124
+ getStatus(): SchedulerStatus {
125
+ return this.status;
126
+ }
127
+
128
+ /**
129
+ * Get detailed scheduler state for monitoring
130
+ */
131
+ getState(): SchedulerState {
132
+ return {
133
+ status: this.status,
134
+ startedAt: this.startedAt,
135
+ checkCount: this.checkCount,
136
+ triggerCount: this.triggerCount,
137
+ lastCheckAt: this.lastCheckAt,
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Start the scheduler polling loop
143
+ *
144
+ * @param agents - The agents to schedule
145
+ * @throws Error if scheduler is already running
146
+ */
147
+ async start(agents: ResolvedAgent[]): Promise<void> {
148
+ if (this.status === "running") {
149
+ throw new Error("Scheduler is already running");
150
+ }
151
+
152
+ if (this.status === "stopping") {
153
+ throw new Error("Scheduler is stopping, wait for it to complete");
154
+ }
155
+
156
+ this.agents = agents;
157
+ this.status = "running";
158
+ this.abortController = new AbortController();
159
+ this.startedAt = new Date().toISOString();
160
+ this.checkCount = 0;
161
+ this.triggerCount = 0;
162
+ this.runningSchedules.clear();
163
+ this.runningJobs.clear();
164
+
165
+ this.logger.info(
166
+ `Scheduler started with ${agents.length} agents, check interval: ${this.checkInterval}ms`
167
+ );
168
+
169
+ // Run the polling loop
170
+ await this.runLoop();
171
+ }
172
+
173
+ /**
174
+ * Stop the scheduler gracefully
175
+ *
176
+ * Signals the polling loop to stop and optionally waits for running jobs to complete.
177
+ *
178
+ * @param options - Options for shutdown behavior
179
+ * @param options.waitForJobs - Whether to wait for running jobs to complete (default: true)
180
+ * @param options.timeout - Maximum time to wait for jobs in milliseconds (default: 30000)
181
+ * @throws SchedulerShutdownError if timeout is reached while waiting for jobs
182
+ */
183
+ async stop(options?: StopOptions): Promise<void> {
184
+ if (this.status !== "running") {
185
+ return;
186
+ }
187
+
188
+ const waitForJobs = options?.waitForJobs ?? true;
189
+ const timeout = options?.timeout ?? DEFAULT_SHUTDOWN_TIMEOUT;
190
+
191
+ this.status = "stopping";
192
+ this.logger.info("Scheduler stopping...");
193
+
194
+ // Signal the loop to stop - this prevents new triggers from starting
195
+ this.abortController?.abort();
196
+
197
+ // Wait a tick for the loop to recognize the abort
198
+ await new Promise((resolve) => setImmediate(resolve));
199
+
200
+ // Optionally wait for running jobs to complete
201
+ if (waitForJobs && this.runningJobs.size > 0) {
202
+ this.logger.info(
203
+ `Waiting for ${this.runningJobs.size} running job(s) to complete...`
204
+ );
205
+
206
+ const runningJobPromises = Array.from(this.runningJobs.values());
207
+
208
+ // Create a timeout promise
209
+ const timeoutPromise = new Promise<"timeout">((resolve) => {
210
+ setTimeout(() => resolve("timeout"), timeout);
211
+ });
212
+
213
+ // Race all running jobs against the timeout
214
+ const result = await Promise.race([
215
+ Promise.all(runningJobPromises).then(() => "completed" as const),
216
+ timeoutPromise,
217
+ ]);
218
+
219
+ if (result === "timeout") {
220
+ const runningJobCount = this.runningJobs.size;
221
+ this.status = "stopped";
222
+ this.abortController = null;
223
+ this.logger.error(
224
+ `Shutdown timed out with ${runningJobCount} job(s) still running`
225
+ );
226
+ throw new SchedulerShutdownError(
227
+ `Scheduler shutdown timed out after ${timeout}ms with ${runningJobCount} job(s) still running`,
228
+ { timedOut: true, runningJobCount }
229
+ );
230
+ }
231
+
232
+ this.logger.info("All running jobs completed");
233
+ }
234
+
235
+ this.status = "stopped";
236
+ this.abortController = null;
237
+ this.logger.info("Scheduler stopped");
238
+ }
239
+
240
+ /**
241
+ * Update the list of agents to schedule
242
+ *
243
+ * Can be called while the scheduler is running to add/remove agents.
244
+ */
245
+ setAgents(agents: ResolvedAgent[]): void {
246
+ this.agents = agents;
247
+ this.logger.debug(`Updated agents list: ${agents.length} agents`);
248
+ }
249
+
250
+ /**
251
+ * Main polling loop
252
+ */
253
+ private async runLoop(): Promise<void> {
254
+ const signal = this.abortController?.signal;
255
+
256
+ while (this.status === "running" && !signal?.aborted) {
257
+ try {
258
+ await this.checkAllSchedules();
259
+ } catch (error) {
260
+ this.logger.error(
261
+ `Error during schedule check: ${error instanceof Error ? error.message : String(error)}`
262
+ );
263
+ }
264
+
265
+ // Sleep until next check, but allow interruption via AbortController
266
+ if (this.status === "running" && !signal?.aborted) {
267
+ await this.sleep(this.checkInterval, signal);
268
+ }
269
+ }
270
+ }
271
+
272
+ /**
273
+ * Sleep for the specified duration, interruptible via AbortSignal
274
+ */
275
+ private sleep(ms: number, signal?: AbortSignal): Promise<void> {
276
+ return new Promise((resolve) => {
277
+ const timeout = setTimeout(resolve, ms);
278
+
279
+ signal?.addEventListener(
280
+ "abort",
281
+ () => {
282
+ clearTimeout(timeout);
283
+ resolve();
284
+ },
285
+ { once: true }
286
+ );
287
+ });
288
+ }
289
+
290
+ /**
291
+ * Check all agents' schedules and trigger due ones
292
+ */
293
+ private async checkAllSchedules(): Promise<void> {
294
+ this.checkCount++;
295
+ this.lastCheckAt = new Date().toISOString();
296
+
297
+ for (const agent of this.agents) {
298
+ if (!agent.schedules) {
299
+ continue;
300
+ }
301
+
302
+ for (const [scheduleName, schedule] of Object.entries(agent.schedules)) {
303
+ const result = await this.checkSchedule(agent, scheduleName, schedule);
304
+
305
+ if (result.shouldTrigger) {
306
+ await this.triggerSchedule(agent, scheduleName, schedule);
307
+ }
308
+ }
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Check if a single schedule should be triggered
314
+ */
315
+ private async checkSchedule(
316
+ agent: ResolvedAgent,
317
+ scheduleName: string,
318
+ schedule: { type: string; interval?: string }
319
+ ): Promise<ScheduleCheckResult> {
320
+ const baseResult = {
321
+ agentName: agent.name,
322
+ scheduleName,
323
+ };
324
+
325
+ // Skip non-interval schedule types (cron, webhook, chat reserved for future)
326
+ if (schedule.type !== "interval") {
327
+ return {
328
+ ...baseResult,
329
+ shouldTrigger: false,
330
+ skipReason: "not_interval" as ScheduleSkipReason,
331
+ };
332
+ }
333
+
334
+ // Get current schedule state
335
+ const stateLogger: ScheduleStateLogger = { warn: this.logger.warn };
336
+ const scheduleState = await getScheduleState(
337
+ this.stateDir,
338
+ agent.name,
339
+ scheduleName,
340
+ { logger: stateLogger }
341
+ );
342
+
343
+ // Skip disabled schedules
344
+ if (scheduleState.status === "disabled") {
345
+ this.logger.debug(
346
+ `Skipping ${agent.name}/${scheduleName}: schedule is disabled`
347
+ );
348
+ return {
349
+ ...baseResult,
350
+ shouldTrigger: false,
351
+ skipReason: "disabled" as ScheduleSkipReason,
352
+ };
353
+ }
354
+
355
+ // Skip if already running (tracked locally)
356
+ const agentRunning = this.runningSchedules.get(agent.name);
357
+ if (agentRunning?.has(scheduleName)) {
358
+ this.logger.debug(
359
+ `Skipping ${agent.name}/${scheduleName}: already running`
360
+ );
361
+ return {
362
+ ...baseResult,
363
+ shouldTrigger: false,
364
+ skipReason: "already_running" as ScheduleSkipReason,
365
+ };
366
+ }
367
+
368
+ // Check max_concurrent capacity
369
+ const maxConcurrent = agent.session?.max_turns
370
+ ? 1
371
+ : this.getMaxConcurrent(agent);
372
+ const runningCount = agentRunning?.size ?? 0;
373
+
374
+ if (runningCount >= maxConcurrent) {
375
+ this.logger.debug(
376
+ `Skipping ${agent.name}/${scheduleName}: at max capacity (${runningCount}/${maxConcurrent})`
377
+ );
378
+ return {
379
+ ...baseResult,
380
+ shouldTrigger: false,
381
+ skipReason: "at_capacity" as ScheduleSkipReason,
382
+ };
383
+ }
384
+
385
+ // Calculate next trigger time
386
+ const lastRunAt = scheduleState.last_run_at
387
+ ? new Date(scheduleState.last_run_at)
388
+ : null;
389
+
390
+ if (!schedule.interval) {
391
+ this.logger.warn(
392
+ `Skipping ${agent.name}/${scheduleName}: interval schedule missing interval value`
393
+ );
394
+ return {
395
+ ...baseResult,
396
+ shouldTrigger: false,
397
+ skipReason: "not_interval" as ScheduleSkipReason,
398
+ };
399
+ }
400
+
401
+ const nextTrigger = calculateNextTrigger(lastRunAt, schedule.interval);
402
+
403
+ // Check if schedule is due
404
+ if (!isScheduleDue(nextTrigger)) {
405
+ return {
406
+ ...baseResult,
407
+ shouldTrigger: false,
408
+ skipReason: "not_due" as ScheduleSkipReason,
409
+ };
410
+ }
411
+
412
+ return {
413
+ ...baseResult,
414
+ shouldTrigger: true,
415
+ };
416
+ }
417
+
418
+ /**
419
+ * Get max_concurrent for an agent, defaulting to 1
420
+ *
421
+ * Reads from agent.instances.max_concurrent, which may come from:
422
+ * - Agent-specific config
423
+ * - Fleet defaults (merged during config loading)
424
+ */
425
+ private getMaxConcurrent(agent: ResolvedAgent): number {
426
+ return agent.instances?.max_concurrent ?? 1;
427
+ }
428
+
429
+ /**
430
+ * Get the count of currently running jobs for a specific agent
431
+ *
432
+ * This is useful for monitoring and debugging concurrency behavior.
433
+ *
434
+ * @param agentName - The name of the agent to check
435
+ * @returns The number of currently running jobs for this agent
436
+ */
437
+ getRunningJobCount(agentName: string): number {
438
+ return this.runningSchedules.get(agentName)?.size ?? 0;
439
+ }
440
+
441
+ /**
442
+ * Get the total count of running jobs across all agents
443
+ *
444
+ * This is useful for monitoring overall scheduler load.
445
+ *
446
+ * @returns The total number of currently running jobs
447
+ */
448
+ getTotalRunningJobCount(): number {
449
+ return this.runningJobs.size;
450
+ }
451
+
452
+ /**
453
+ * Trigger a schedule and update state
454
+ */
455
+ private async triggerSchedule(
456
+ agent: ResolvedAgent,
457
+ scheduleName: string,
458
+ schedule: { type: string; interval?: string; prompt?: string }
459
+ ): Promise<void> {
460
+ this.logger.info(`Triggering ${agent.name}/${scheduleName}`);
461
+ this.triggerCount++;
462
+
463
+ // Create a unique key for this job
464
+ const jobKey = `${agent.name}/${scheduleName}`;
465
+
466
+ // Mark schedule as running
467
+ if (!this.runningSchedules.has(agent.name)) {
468
+ this.runningSchedules.set(agent.name, new Set());
469
+ }
470
+ this.runningSchedules.get(agent.name)!.add(scheduleName);
471
+
472
+ const stateLogger: ScheduleStateLogger = { warn: this.logger.warn };
473
+
474
+ // Update schedule state to running
475
+ await updateScheduleState(
476
+ this.stateDir,
477
+ agent.name,
478
+ scheduleName,
479
+ {
480
+ status: "running",
481
+ last_run_at: new Date().toISOString(),
482
+ },
483
+ { logger: stateLogger }
484
+ );
485
+
486
+ // Create and track the job promise
487
+ const jobPromise = this.executeJob(agent, scheduleName, schedule);
488
+ this.runningJobs.set(jobKey, jobPromise);
489
+
490
+ try {
491
+ await jobPromise;
492
+ } finally {
493
+ // Remove from running jobs tracking
494
+ this.runningJobs.delete(jobKey);
495
+ }
496
+ }
497
+
498
+ /**
499
+ * Execute the actual job logic
500
+ */
501
+ private async executeJob(
502
+ agent: ResolvedAgent,
503
+ scheduleName: string,
504
+ schedule: { type: string; interval?: string; prompt?: string }
505
+ ): Promise<void> {
506
+ const stateLogger: ScheduleStateLogger = { warn: this.logger.warn };
507
+
508
+ try {
509
+ // Get current schedule state for trigger info
510
+ const scheduleState = await getScheduleState(
511
+ this.stateDir,
512
+ agent.name,
513
+ scheduleName,
514
+ { logger: stateLogger }
515
+ );
516
+
517
+ // Invoke the trigger callback if provided
518
+ if (this.onTrigger) {
519
+ const triggerInfo: TriggerInfo = {
520
+ agent,
521
+ scheduleName,
522
+ schedule: schedule as TriggerInfo["schedule"],
523
+ scheduleState,
524
+ };
525
+
526
+ await this.onTrigger(triggerInfo);
527
+ }
528
+
529
+ // Calculate next trigger time
530
+ const nextTrigger = schedule.interval
531
+ ? calculateNextTrigger(new Date(), schedule.interval)
532
+ : null;
533
+
534
+ // Update schedule state to idle with next run time
535
+ await updateScheduleState(
536
+ this.stateDir,
537
+ agent.name,
538
+ scheduleName,
539
+ {
540
+ status: "idle",
541
+ next_run_at: nextTrigger?.toISOString() ?? null,
542
+ last_error: null,
543
+ },
544
+ { logger: stateLogger }
545
+ );
546
+
547
+ this.logger.info(`Completed ${agent.name}/${scheduleName}`);
548
+ } catch (error) {
549
+ const errorMessage =
550
+ error instanceof Error ? error.message : String(error);
551
+
552
+ // Update schedule state with error
553
+ await updateScheduleState(
554
+ this.stateDir,
555
+ agent.name,
556
+ scheduleName,
557
+ {
558
+ status: "idle",
559
+ last_error: errorMessage,
560
+ },
561
+ { logger: stateLogger }
562
+ );
563
+
564
+ this.logger.error(`Error in ${agent.name}/${scheduleName}: ${errorMessage}`);
565
+ } finally {
566
+ // Mark schedule as no longer running
567
+ this.runningSchedules.get(agent.name)?.delete(scheduleName);
568
+ }
569
+ }
570
+ }