@xopcai/xopc 0.0.110 → 0.0.112

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 (583) hide show
  1. package/README.md +46 -4
  2. package/README.zh-CN.md +46 -4
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  5. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  6. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  7. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  8. package/dist/extensions/telegram/src/plugin.js +1 -1
  9. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  10. package/dist/extensions/telegram/src/update-offset-store.js +1 -1
  11. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  12. package/dist/extensions/telegram/xopc.extension.json +1 -1
  13. package/dist/extensions/weixin/src/api/api.js +2 -2
  14. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  15. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  16. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  17. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  18. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  19. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  20. package/dist/extensions/weixin/src/plugin.js +1 -1
  21. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  22. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  23. package/dist/gateway/static/root/apple-touch-icon.png +0 -0
  24. package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +41 -0
  25. package/dist/gateway/static/root/assets/agent-avatar-dicebear-EhRp-ZMa.js +1 -0
  26. package/dist/gateway/static/root/assets/agent-browser-settings-page-H4foVCiS.js +6 -0
  27. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-DDNw2oNU.js +1 -0
  28. package/dist/gateway/static/root/assets/agents-E_X2kzS1.js +71 -0
  29. package/dist/gateway/static/root/assets/app-management-settings-panel-BIy7KEsM.js +1 -0
  30. package/dist/gateway/static/root/assets/appearance-settings-DGQG8NwA.js +1 -0
  31. package/dist/gateway/static/root/assets/apps-page-BZLvInLr.js +1 -0
  32. package/dist/gateway/static/root/assets/archive-plugin-uuQPupqx.js +1 -0
  33. package/dist/gateway/static/root/assets/attachment-load-DBkv0cAv.js +2 -0
  34. package/dist/gateway/static/root/assets/{attachment-preview-renderer-CybMSIoS.js → attachment-preview-renderer-DonnL2dL.js} +1 -1
  35. package/dist/gateway/static/root/assets/binary-plugins-DxxN_VAR.js +2 -0
  36. package/dist/gateway/static/root/assets/block-editor-CwnUlRmO.js +180 -0
  37. package/dist/gateway/static/root/assets/channels-settings-BHvUKlzw.js +1 -0
  38. package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +1 -0
  39. package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +1 -0
  40. package/dist/gateway/static/root/assets/config-api-BD-NcD5d.js +3 -0
  41. package/dist/gateway/static/root/assets/config-reload-event-Bjh2zoKp.js +1 -0
  42. package/dist/gateway/static/root/assets/connectors-settings-VBzXcEXL.js +2 -0
  43. package/dist/gateway/static/root/assets/cron-api-C5DoipZA.js +1 -0
  44. package/dist/gateway/static/root/assets/cron-dreaming-jobs-nCMWCf0p.js +1 -0
  45. package/dist/gateway/static/root/assets/cron-page-BLTpdm34.js +3 -0
  46. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
  47. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
  48. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
  49. package/dist/gateway/static/root/assets/dreaming-scene-BHMRVEUS.js +4585 -0
  50. package/dist/gateway/static/root/assets/dreaming-settings-DSVhXTPq.js +1 -0
  51. package/dist/gateway/static/root/assets/extension-debug-page-BDHA9o_e.js +1 -0
  52. package/dist/gateway/static/root/assets/{extension-page-W1wiG38F.js → extension-page-DmDLVSPE.js} +1 -1
  53. package/dist/gateway/static/root/assets/extension-settings-page-1124aHw_.js +1 -0
  54. package/dist/gateway/static/root/assets/fetch-DOe56Wmy.js +1 -0
  55. package/dist/gateway/static/root/assets/format-cron-label-BsotZDO5.js +2 -0
  56. package/dist/gateway/static/root/assets/format-interval-label-tsMSvBSR.js +1 -0
  57. package/dist/gateway/static/root/assets/gateway-config-api-CsD4FC9D.js +1 -0
  58. package/dist/gateway/static/root/assets/gateway-settings-HQ8FBhY2.js +1 -0
  59. package/dist/gateway/static/root/assets/gateway-startup-retry-C1zg7pH3.js +1 -0
  60. package/dist/gateway/static/root/assets/goal-detail-page-BG3Onph0.js +1 -0
  61. package/dist/gateway/static/root/assets/goals-page-DgeKn8zL.js +2 -0
  62. package/dist/gateway/static/root/assets/goals-settings-B5nI6lgz.js +1 -0
  63. package/dist/gateway/static/root/assets/heartbeat-config-api-CIv42nJD.js +1 -0
  64. package/dist/gateway/static/root/assets/heartbeat-settings-DFcVuJ3M.js +1 -0
  65. package/dist/gateway/static/root/assets/html-workspace-editor-CQLWDiwE.js +1 -0
  66. package/dist/gateway/static/root/assets/index-5A_ZaABy.css +1 -0
  67. package/dist/gateway/static/root/assets/index-BTmbp2AU.js +121 -0
  68. package/dist/gateway/static/root/assets/interval-presets-DGP3S7OB.js +1 -0
  69. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-fETaDYQP.js +1 -0
  70. package/dist/gateway/static/root/assets/locale-store-DjbfSsfA.js +1 -0
  71. package/dist/gateway/static/root/assets/logs-page-B1-b27lK.js +2 -0
  72. package/dist/gateway/static/root/assets/markdown-editor-AssmZFx4.js +2 -0
  73. package/dist/gateway/static/root/assets/markdown-split-CgeBJMOD.js +1 -0
  74. package/dist/gateway/static/root/assets/media-plugins-C30GzlV2.js +1 -0
  75. package/dist/gateway/static/root/assets/mermaid-render-BbqDc_LQ.js +134 -0
  76. package/dist/gateway/static/root/assets/messages-BUUfPaZ9.js +3 -0
  77. package/dist/gateway/static/root/assets/middleware-Pd0e8Igk.js +1 -0
  78. package/dist/gateway/static/root/assets/models-hub-panel-DPcTS1-u.js +2 -0
  79. package/dist/gateway/static/root/assets/note-detail-page-xeGb4owe.js +2 -0
  80. package/dist/gateway/static/root/assets/note-image-lightbox-t1g0qZYh.js +1 -0
  81. package/dist/gateway/static/root/assets/note-time-hm6JO_Wi.js +1 -0
  82. package/dist/gateway/static/root/assets/notes-page-C_TdnKBe.js +1 -0
  83. package/dist/gateway/static/root/assets/preview-open-alternatives-DeWp9x5g.js +1 -0
  84. package/dist/gateway/static/root/assets/remote-access-hub-BtkPmJIN.js +1 -0
  85. package/dist/gateway/static/root/assets/save-bar-controls-BOaAOJI3.js +1 -0
  86. package/dist/gateway/static/root/assets/schedule-field-BLWLKqgw.js +1 -0
  87. package/dist/gateway/static/root/assets/schema-form-plqRFYT8.js +1 -0
  88. package/dist/gateway/static/root/assets/sessions-page-DOUjxzJm.js +1 -0
  89. package/dist/gateway/static/root/assets/settings-advanced-gate-qK_bnTrw.js +1 -0
  90. package/dist/gateway/static/root/assets/settings-collapsible-section-BP5zRrDI.js +1 -0
  91. package/dist/gateway/static/root/assets/settings-form-section-Bv8MZplG.js +1 -0
  92. package/dist/gateway/static/root/assets/settings-page-DmDfE1ww.js +1 -0
  93. package/dist/gateway/static/root/assets/setup-status-panel-BEFwNcIZ.js +1 -0
  94. package/dist/gateway/static/root/assets/share-preview-page-4OX1YCgp.js +2 -0
  95. package/dist/gateway/static/root/assets/shares-settings-CbKmJZot.js +1 -0
  96. package/dist/gateway/static/root/assets/skill-reload-api-YdtnUHtK.js +1 -0
  97. package/dist/gateway/static/root/assets/skills-page-DwW1IzQ0.js +2 -0
  98. package/dist/gateway/static/root/assets/system-settings-panel-CGy4f_s2.js +1 -0
  99. package/dist/gateway/static/root/assets/theme-store-CD2wtgZV.js +1 -0
  100. package/dist/gateway/static/root/assets/use-agent-defaults-form-BMuMvzl_.js +1 -0
  101. package/dist/gateway/static/root/assets/use-blob-object-url-D4BFuzZB.js +1 -0
  102. package/dist/gateway/static/root/assets/use-channel-catalog-CjGHnDvN.js +1 -0
  103. package/dist/gateway/static/root/assets/use-settings-tab-guard-BMMFa0oA.js +1 -0
  104. package/dist/gateway/static/root/assets/vendor-codemirror-CNP1wPe7.js +45 -0
  105. package/dist/gateway/static/root/assets/voice-api-key-field-DnRbhMNq.js +1 -0
  106. package/dist/gateway/static/root/assets/voice-player-store-D5vzWwls.js +1 -0
  107. package/dist/gateway/static/root/assets/{workflow-page.utils-EYg_xBQS.js → workflow-page.utils-tjGpRVnw.js} +1 -1
  108. package/dist/gateway/static/root/assets/workflows-page-DqqHKGj2.js +18 -0
  109. package/dist/gateway/static/root/favicon-16x16.png +0 -0
  110. package/dist/gateway/static/root/favicon-32x32.png +0 -0
  111. package/dist/gateway/static/root/favicon.ico +0 -0
  112. package/dist/gateway/static/root/favicon.svg +14 -12
  113. package/dist/gateway/static/root/index.html +18 -15
  114. package/dist/package.js +1 -1
  115. package/dist/src/agent/agent-manager.d.ts +28 -2
  116. package/dist/src/agent/agent-manager.js +82 -11
  117. package/dist/src/agent/agent-manager.js.map +1 -1
  118. package/dist/src/agent/agent-scope.js +1 -1
  119. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  120. package/dist/src/agent/context/workspace-seed.js +2 -2
  121. package/dist/src/agent/context/workspace-state.js +1 -1
  122. package/dist/src/agent/context/workspace.js +1 -1
  123. package/dist/src/agent/goals/checklist-judge.d.ts +5 -0
  124. package/dist/src/agent/goals/checklist-judge.js +26 -2
  125. package/dist/src/agent/goals/checklist-judge.js.map +1 -1
  126. package/dist/src/agent/goals/evaluate-turn.d.ts +5 -1
  127. package/dist/src/agent/goals/evaluate-turn.js +29 -3
  128. package/dist/src/agent/goals/evaluate-turn.js.map +1 -1
  129. package/dist/src/agent/goals/goal-locale.d.ts +0 -2
  130. package/dist/src/agent/goals/goal-locale.js +3 -16
  131. package/dist/src/agent/goals/goal-locale.js.map +1 -1
  132. package/dist/src/agent/goals/persistent-goal-service.d.ts +9 -0
  133. package/dist/src/agent/goals/persistent-goal-service.js +3 -2
  134. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
  135. package/dist/src/agent/goals/post-turn.d.ts +7 -0
  136. package/dist/src/agent/goals/post-turn.js +70 -25
  137. package/dist/src/agent/goals/post-turn.js.map +1 -1
  138. package/dist/src/agent/goals/state.d.ts +0 -5
  139. package/dist/src/agent/goals/state.js +1 -96
  140. package/dist/src/agent/goals/state.js.map +1 -1
  141. package/dist/src/agent/image/load-image-media.js +2 -2
  142. package/dist/src/agent/ipc/inbox.js +3 -3
  143. package/dist/src/agent/ipc/socket.js +1 -1
  144. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  145. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  146. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  147. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  148. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  149. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  150. package/dist/src/agent/memory/dreaming/events.js +1 -1
  151. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  152. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  153. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  154. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  155. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  156. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  157. package/dist/src/agent/memory/memory-flush.js +1 -1
  158. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  159. package/dist/src/agent/messaging/command-handler.d.ts +7 -0
  160. package/dist/src/agent/messaging/command-handler.js +11 -2
  161. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  162. package/dist/src/agent/models/manager.js +1 -1
  163. package/dist/src/agent/prompt/memory/index.js +1 -1
  164. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  165. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  166. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  167. package/dist/src/agent/sandbox/path-policy.js +2 -2
  168. package/dist/src/agent/service/direct-turn-helpers.d.ts +2 -0
  169. package/dist/src/agent/service/direct-turn-helpers.js +3 -2
  170. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  171. package/dist/src/agent/service/process-direct-streaming.js +10 -1
  172. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  173. package/dist/src/agent/service/reconcile-dreaming-cron.js +8 -5
  174. package/dist/src/agent/service/reconcile-dreaming-cron.js.map +1 -1
  175. package/dist/src/agent/service.d.ts +2 -1
  176. package/dist/src/agent/service.js +30 -6
  177. package/dist/src/agent/service.js.map +1 -1
  178. package/dist/src/agent/service.types.d.ts +12 -0
  179. package/dist/src/agent/session/session-config-service.d.ts +8 -0
  180. package/dist/src/agent/session/session-config-service.js +20 -0
  181. package/dist/src/agent/session/session-config-service.js.map +1 -1
  182. package/dist/src/agent/session/session-inspector.js +1 -1
  183. package/dist/src/agent/skills/config.js +2 -2
  184. package/dist/src/agent/skills/filesystem-watcher.d.ts +19 -0
  185. package/dist/src/agent/skills/filesystem-watcher.js +182 -0
  186. package/dist/src/agent/skills/filesystem-watcher.js.map +1 -0
  187. package/dist/src/agent/skills/hub-hash.js +2 -2
  188. package/dist/src/agent/skills/hub-lock.js +1 -1
  189. package/dist/src/agent/skills/hub-pull.js +30 -36
  190. package/dist/src/agent/skills/hub-pull.js.map +1 -1
  191. package/dist/src/agent/skills/index.js +82 -38
  192. package/dist/src/agent/skills/index.js.map +1 -1
  193. package/dist/src/agent/skills/installer.js +2 -2
  194. package/dist/src/agent/skills/managed-store.d.ts +19 -0
  195. package/dist/src/agent/skills/managed-store.js +97 -38
  196. package/dist/src/agent/skills/managed-store.js.map +1 -1
  197. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  198. package/dist/src/agent/skills/skill-manager.d.ts +16 -6
  199. package/dist/src/agent/skills/skill-manager.js +79 -24
  200. package/dist/src/agent/skills/skill-manager.js.map +1 -1
  201. package/dist/src/agent/skills/skill-view-path.js +1 -1
  202. package/dist/src/agent/skills/test-framework.js +1 -1
  203. package/dist/src/agent/skills/types.d.ts +11 -0
  204. package/dist/src/agent/skills/watcher.js +1 -1
  205. package/dist/src/agent/starter-agents.js +1 -1
  206. package/dist/src/agent/tools/cronjob-tool.d.ts +8 -3
  207. package/dist/src/agent/tools/cronjob-tool.js +82 -24
  208. package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
  209. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  210. package/dist/src/agent/tools/edit.d.ts +2 -0
  211. package/dist/src/agent/tools/edit.js +10 -0
  212. package/dist/src/agent/tools/edit.js.map +1 -1
  213. package/dist/src/agent/tools/factory.js +17 -4
  214. package/dist/src/agent/tools/factory.js.map +1 -1
  215. package/dist/src/agent/tools/find.js +1 -1
  216. package/dist/src/agent/tools/goal-evidence-recorder.d.ts +6 -0
  217. package/dist/src/agent/tools/goal-evidence-recorder.js +34 -0
  218. package/dist/src/agent/tools/goal-evidence-recorder.js.map +1 -0
  219. package/dist/src/agent/tools/goal-tool.d.ts +19 -0
  220. package/dist/src/agent/tools/goal-tool.js +101 -0
  221. package/dist/src/agent/tools/goal-tool.js.map +1 -0
  222. package/dist/src/agent/tools/grep.js +1 -1
  223. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  224. package/dist/src/agent/tools/index.d.ts +1 -0
  225. package/dist/src/agent/tools/index.js +2 -1
  226. package/dist/src/agent/tools/shell.d.ts +2 -0
  227. package/dist/src/agent/tools/shell.js +17 -2
  228. package/dist/src/agent/tools/shell.js.map +1 -1
  229. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  230. package/dist/src/agent/tools/workflow-tool.d.ts +1 -0
  231. package/dist/src/agent/tools/workflow-tool.js +11 -3
  232. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  233. package/dist/src/agent/tools/write.d.ts +2 -0
  234. package/dist/src/agent/tools/write.js +11 -0
  235. package/dist/src/agent/tools/write.js.map +1 -1
  236. package/dist/src/agent/workflow/catalog.js +1 -1
  237. package/dist/src/agent/workspace-runtime/registry.d.ts +5 -0
  238. package/dist/src/agent/workspace-runtime/registry.js +7 -0
  239. package/dist/src/agent/workspace-runtime/registry.js.map +1 -1
  240. package/dist/src/ai-assist/text-assist.d.ts +39 -0
  241. package/dist/src/ai-assist/text-assist.js +234 -0
  242. package/dist/src/ai-assist/text-assist.js.map +1 -0
  243. package/dist/src/auth/credentials.js +2 -2
  244. package/dist/src/auth/profiles/store.js +2 -2
  245. package/dist/src/auth/sync-provider-auth.js +1 -1
  246. package/dist/src/browser/cache-dir-policy.js +1 -1
  247. package/dist/src/browser/cdp-local-launcher.js +2 -2
  248. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  249. package/dist/src/browser/providers/cloakbrowser.js +5 -5
  250. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  251. package/dist/src/browser/stealth.js +1 -1
  252. package/dist/src/channels/attachments/inbound-persist.d.ts +7 -0
  253. package/dist/src/channels/attachments/inbound-persist.js +20 -2
  254. package/dist/src/channels/attachments/inbound-persist.js.map +1 -1
  255. package/dist/src/channels/outbound/persist-store.js +1 -1
  256. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  257. package/dist/src/channels/pairing/pairing-store.js +2 -2
  258. package/dist/src/chat-commands/agent-edit.js +2 -2
  259. package/dist/src/chat-commands/builtins/config.js +3 -3
  260. package/dist/src/chat-commands/builtins/goal.d.ts +1 -1
  261. package/dist/src/chat-commands/builtins/goal.js +55 -97
  262. package/dist/src/chat-commands/builtins/goal.js.map +1 -1
  263. package/dist/src/chat-commands/builtins/subgoal.d.ts +1 -1
  264. package/dist/src/chat-commands/builtins/subgoal.js +49 -108
  265. package/dist/src/chat-commands/builtins/subgoal.js.map +1 -1
  266. package/dist/src/chat-commands/builtins/system.js +11 -4
  267. package/dist/src/chat-commands/builtins/system.js.map +1 -1
  268. package/dist/src/chat-commands/builtins/workflow.js +132 -8
  269. package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
  270. package/dist/src/chat-commands/context.d.ts +6 -0
  271. package/dist/src/chat-commands/context.js +12 -0
  272. package/dist/src/chat-commands/context.js.map +1 -1
  273. package/dist/src/chat-commands/types.d.ts +7 -0
  274. package/dist/src/cli/command-catalog.js +43 -0
  275. package/dist/src/cli/command-catalog.js.map +1 -1
  276. package/dist/src/cli/command-loaders.js +1 -0
  277. package/dist/src/cli/command-loaders.js.map +1 -1
  278. package/dist/src/cli/command-manifest.js +4 -0
  279. package/dist/src/cli/command-manifest.js.map +1 -1
  280. package/dist/src/cli/commands/config.js +1 -1
  281. package/dist/src/cli/commands/cron.js +55 -16
  282. package/dist/src/cli/commands/cron.js.map +1 -1
  283. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  284. package/dist/src/cli/commands/doctor/checks/cron-health.js +2 -83
  285. package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -1
  286. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  287. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  288. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  289. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  290. package/dist/src/cli/commands/extension-create.js +1 -1
  291. package/dist/src/cli/commands/extension-dev.js +2 -2
  292. package/dist/src/cli/commands/extension-marketplace.js +2 -2
  293. package/dist/src/cli/commands/extension-pack.js +2 -2
  294. package/dist/src/cli/commands/extension.js +3 -3
  295. package/dist/src/cli/commands/gateway/logs.js +1 -1
  296. package/dist/src/cli/commands/goal.d.ts +4 -0
  297. package/dist/src/cli/commands/goal.js +213 -0
  298. package/dist/src/cli/commands/goal.js.map +1 -0
  299. package/dist/src/cli/commands/image.js +1 -1
  300. package/dist/src/cli/commands/init.js +2 -2
  301. package/dist/src/cli/commands/models.js +1 -1
  302. package/dist/src/cli/commands/onboard.js +11 -5
  303. package/dist/src/cli/commands/onboard.js.map +1 -1
  304. package/dist/src/cli/commands/skills-test.js +1 -1
  305. package/dist/src/cli/templates.js +1 -1
  306. package/dist/src/cli/utils/gateway-client.js +1 -1
  307. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  308. package/dist/src/config/agent-profile.js +1 -1
  309. package/dist/src/config/agent-typed-models.js +1 -1
  310. package/dist/src/config/gateway-bind.js +1 -1
  311. package/dist/src/config/index.js +8 -8
  312. package/dist/src/config/loader.js +4 -4
  313. package/dist/src/config/models-json.js +2 -2
  314. package/dist/src/config/paths-state.js +1 -1
  315. package/dist/src/config/paths.js +1 -1
  316. package/dist/src/config/profile.js +1 -1
  317. package/dist/src/config/reload.js +1 -1
  318. package/dist/src/config/schema.d.ts +115 -2
  319. package/dist/src/config/schema.js +63 -7
  320. package/dist/src/config/schema.js.map +1 -1
  321. package/dist/src/config/web-patch.d.ts +14 -1
  322. package/dist/src/config/web-patch.js +45 -8
  323. package/dist/src/config/web-patch.js.map +1 -1
  324. package/dist/src/config/workspace-path.js +1 -1
  325. package/dist/src/cron/executor.d.ts +2 -0
  326. package/dist/src/cron/executor.js +126 -70
  327. package/dist/src/cron/executor.js.map +1 -1
  328. package/dist/src/cron/index.d.ts +1 -1
  329. package/dist/src/cron/index.js +3 -3
  330. package/dist/src/cron/job-content.js +1 -0
  331. package/dist/src/cron/job-content.js.map +1 -1
  332. package/dist/src/cron/run-log-store.d.ts +1 -0
  333. package/dist/src/cron/run-log-store.js +4 -2
  334. package/dist/src/cron/run-log-store.js.map +1 -1
  335. package/dist/src/cron/schedule.d.ts +10 -0
  336. package/dist/src/cron/schedule.js +85 -0
  337. package/dist/src/cron/schedule.js.map +1 -0
  338. package/dist/src/cron/service.d.ts +34 -77
  339. package/dist/src/cron/service.js +327 -264
  340. package/dist/src/cron/service.js.map +1 -1
  341. package/dist/src/cron/types.d.ts +97 -49
  342. package/dist/src/cron/validation.d.ts +374 -86
  343. package/dist/src/cron/validation.js +156 -129
  344. package/dist/src/cron/validation.js.map +1 -1
  345. package/dist/src/cron/workflow-run-completion.js +1 -1
  346. package/dist/src/daemon/constants.js +1 -1
  347. package/dist/src/daemon/install-plan.js +2 -2
  348. package/dist/src/daemon/launchd.js +2 -2
  349. package/dist/src/daemon/schtasks.js +2 -2
  350. package/dist/src/daemon/systemd.js +2 -2
  351. package/dist/src/extensions/bundle-mcp.js +1 -1
  352. package/dist/src/extensions/discover-extensions.js +2 -2
  353. package/dist/src/extensions/health.js +1 -1
  354. package/dist/src/extensions/install.js +2 -2
  355. package/dist/src/extensions/loader.js +2 -2
  356. package/dist/src/extensions/lockfile.js +3 -3
  357. package/dist/src/extensions/security.js +1 -1
  358. package/dist/src/extensions/update.js +2 -2
  359. package/dist/src/gateway/agents-admin.js +2 -2
  360. package/dist/src/gateway/chat-stream/mapper.d.ts +1 -0
  361. package/dist/src/gateway/chat-stream/mapper.js +6 -2
  362. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  363. package/dist/src/gateway/chat-stream/protocol.d.ts +2 -0
  364. package/dist/src/gateway/file-path-classifier.js +2 -2
  365. package/dist/src/gateway/hono/lib/config-payload.d.ts +14 -1
  366. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  367. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  368. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  369. package/dist/src/gateway/hono/oauth-async.js +1 -1
  370. package/dist/src/gateway/hono/routes/agents.js +1 -1
  371. package/dist/src/gateway/hono/routes/ai-assist.d.ts +3 -0
  372. package/dist/src/gateway/hono/routes/ai-assist.js +66 -0
  373. package/dist/src/gateway/hono/routes/ai-assist.js.map +1 -0
  374. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  375. package/dist/src/gateway/hono/routes/commands-skills.js +7 -0
  376. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  377. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  378. package/dist/src/gateway/hono/routes/cron.js +24 -5
  379. package/dist/src/gateway/hono/routes/cron.js.map +1 -1
  380. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  381. package/dist/src/gateway/hono/routes/goals.d.ts +1 -1
  382. package/dist/src/gateway/hono/routes/goals.js +670 -173
  383. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  384. package/dist/src/gateway/hono/routes/home.d.ts +5 -0
  385. package/dist/src/gateway/hono/routes/home.js +90 -3
  386. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  387. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  388. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  389. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  390. package/dist/src/gateway/hono/routes/models.js +1 -1
  391. package/dist/src/gateway/hono/routes/notes.js +20 -14
  392. package/dist/src/gateway/hono/routes/notes.js.map +1 -1
  393. package/dist/src/gateway/hono/routes/shares.js +1 -1
  394. package/dist/src/gateway/hono/routes/workflows.js +8 -4
  395. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  396. package/dist/src/gateway/hono/routes/workspace.js +2 -2
  397. package/dist/src/gateway/hono/sse.js.map +1 -1
  398. package/dist/src/gateway/lock.js +3 -3
  399. package/dist/src/gateway/ports.js +1 -1
  400. package/dist/src/gateway/service/agent-runner.d.ts +2 -0
  401. package/dist/src/gateway/service/agent-runner.js +8 -4
  402. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  403. package/dist/src/gateway/service/config-coordinator.js +1 -1
  404. package/dist/src/gateway/service/marketplace-service.d.ts +22 -10
  405. package/dist/src/gateway/service/marketplace-service.js +46 -5
  406. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  407. package/dist/src/gateway/service/run-gateway-agent.d.ts +3 -0
  408. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  409. package/dist/src/gateway/service.d.ts +8 -0
  410. package/dist/src/gateway/service.js +79 -6
  411. package/dist/src/gateway/service.js.map +1 -1
  412. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  413. package/dist/src/goals/goal-notifications.d.ts +29 -0
  414. package/dist/src/goals/goal-notifications.js +154 -0
  415. package/dist/src/goals/goal-notifications.js.map +1 -0
  416. package/dist/src/goals/goal-queue-store.d.ts +16 -0
  417. package/dist/src/goals/goal-queue-store.js +131 -0
  418. package/dist/src/goals/goal-queue-store.js.map +1 -0
  419. package/dist/src/goals/goal-queue-types.d.ts +31 -0
  420. package/dist/src/goals/goal-queue-types.js +1 -0
  421. package/dist/src/goals/goal-runner.d.ts +17 -0
  422. package/dist/src/goals/goal-runner.js +127 -0
  423. package/dist/src/goals/goal-runner.js.map +1 -0
  424. package/dist/src/goals/goal-service.d.ts +77 -0
  425. package/dist/src/goals/goal-service.js +261 -0
  426. package/dist/src/goals/goal-service.js.map +1 -0
  427. package/dist/src/goals/goal-store.d.ts +38 -0
  428. package/dist/src/goals/goal-store.js +404 -0
  429. package/dist/src/goals/goal-store.js.map +1 -0
  430. package/dist/src/goals/goal-workflow-judge.d.ts +13 -0
  431. package/dist/src/goals/goal-workflow-judge.js +147 -0
  432. package/dist/src/goals/goal-workflow-judge.js.map +1 -0
  433. package/dist/src/goals/index.d.ts +10 -0
  434. package/dist/src/goals/index.js +7 -0
  435. package/dist/src/goals/types.d.ts +119 -0
  436. package/dist/src/goals/types.js +1 -0
  437. package/dist/src/i18n/goals-bundle.js +1 -1
  438. package/dist/src/i18n/index.js +1 -1
  439. package/dist/src/i18n/share-tool-bundle.js +2 -2
  440. package/dist/src/infra/brew.js +1 -1
  441. package/dist/src/infra/package-json.js +1 -1
  442. package/dist/src/infra/package-update-steps.js +1 -1
  443. package/dist/src/infra/path-env.js +2 -2
  444. package/dist/src/infra/restart.js +1 -1
  445. package/dist/src/infra/stable-node-path.js +1 -1
  446. package/dist/src/infra/update-check.js +1 -1
  447. package/dist/src/infra/update-global.js +1 -1
  448. package/dist/src/infra/update-lock.js +2 -2
  449. package/dist/src/infra/update-restart.js +1 -1
  450. package/dist/src/infra/update-runner.js +1 -1
  451. package/dist/src/infra/update-startup.js +1 -1
  452. package/dist/src/infra/write-file-atomic.js +2 -2
  453. package/dist/src/media/store.js +1 -1
  454. package/dist/src/notes/agent-context.js +1 -1
  455. package/dist/src/notes/service.js +1 -1
  456. package/dist/src/notes/store.js +2 -2
  457. package/dist/src/project-trust/trust-store.js +2 -2
  458. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  459. package/dist/src/providers/index.js +1 -1
  460. package/dist/src/providers/model-registry.js +4 -4
  461. package/dist/src/session/init-session-turn.js +2 -2
  462. package/dist/src/session/resolve-session.js +3 -3
  463. package/dist/src/session/session-title.js +2 -2
  464. package/dist/src/session/store.js +1 -1
  465. package/dist/src/share/share-auto.js +2 -2
  466. package/dist/src/share/share-store.js +3 -3
  467. package/dist/src/share/share-thumbnail.js +2 -2
  468. package/dist/src/share/share-zip.js +1 -1
  469. package/dist/src/share/site-share-store.js +3 -3
  470. package/dist/src/share/site-static-serve.js +1 -1
  471. package/dist/src/storage/sqlite/connection.js +1 -1
  472. package/dist/src/storage/sqlite/cron-job-repository.d.ts +6 -0
  473. package/dist/src/storage/sqlite/cron-job-repository.js +70 -0
  474. package/dist/src/storage/sqlite/cron-job-repository.js.map +1 -0
  475. package/dist/src/storage/sqlite/cron-run-repository.js +0 -1
  476. package/dist/src/storage/sqlite/cron-run-repository.js.map +1 -1
  477. package/dist/src/storage/sqlite/index.d.ts +1 -0
  478. package/dist/src/storage/sqlite/index.js +2 -1
  479. package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
  480. package/dist/src/storage/sqlite/migrations/006_add_goals.sql +108 -0
  481. package/dist/src/storage/sqlite/migrations/007_goal_run_judge_schema.sql +4 -0
  482. package/dist/src/storage/sqlite/migrations/008_goal_queue_workflow_runs.sql +53 -0
  483. package/dist/src/storage/sqlite/migrations/009_cron_jobs.sql +24 -0
  484. package/dist/src/storage/sqlite/migrations/discover.js +1 -1
  485. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  486. package/dist/src/storage/sqlite/migrations/runner.js +4 -4
  487. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  488. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  489. package/dist/src/storage/sqlite/schema.js +2 -2
  490. package/dist/src/storage/sqlite/schema.sql +188 -0
  491. package/dist/src/tui/clipboard-image.js +3 -3
  492. package/dist/src/tui/extension-host/load-extensions.js +1 -1
  493. package/dist/src/tui/theme-manager.js +1 -1
  494. package/dist/src/tui/tui-command-formatters.js +4 -4
  495. package/dist/src/tui/tui-commands.js +2 -2
  496. package/dist/src/tui/tui-keybindings-file.js +1 -1
  497. package/dist/src/tui/tui-scoped-models.js +2 -2
  498. package/dist/src/tui/tui-settings.js +1 -1
  499. package/dist/src/tui/tui-startup-resources.js +1 -1
  500. package/dist/src/tui/tui.js +6 -6
  501. package/dist/src/tunnel/frpc-binary.js +4 -4
  502. package/dist/src/tunnel/frpc-config.js +1 -1
  503. package/dist/src/tunnel/frpc-extract.js +1 -1
  504. package/dist/src/tunnel/tunnel-state.js +1 -1
  505. package/dist/src/utils/logger/audit.js +1 -1
  506. package/dist/src/utils/logger/log-store.js +1 -1
  507. package/dist/src/utils/logger/rotation.js +1 -1
  508. package/dist/src/utils/logger/stats.d.ts +1 -1
  509. package/dist/src/utils/logger/streams.js +1 -1
  510. package/dist/src/voice/tts/audio.js +1 -1
  511. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  512. package/dist/src/workflows/domain/run.d.ts +1 -0
  513. package/dist/src/workflows/domain/run.js.map +1 -1
  514. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  515. package/dist/src/workflows/engine/projector.js +23 -14
  516. package/dist/src/workflows/engine/projector.js.map +1 -1
  517. package/dist/src/workflows/engine/workflow-engine.d.ts +1 -0
  518. package/dist/src/workflows/engine/workflow-engine.js +36 -0
  519. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  520. package/dist/src/workflows/index.js +1 -1
  521. package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
  522. package/dist/src/workflows/service/workflow-run-service.js +7 -3
  523. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  524. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -0
  525. package/dist/src/workflows/service/workflow-session-bridge.js +8 -1
  526. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  527. package/dist/src/workflows/store/event-store.js +1 -1
  528. package/dist/src/workflows/store/run-index-store.d.ts +8 -0
  529. package/dist/src/workflows/store/run-index-store.js +58 -0
  530. package/dist/src/workflows/store/run-index-store.js.map +1 -0
  531. package/dist/src/workflows/store/run-store.d.ts +2 -0
  532. package/dist/src/workflows/store/run-store.js +15 -22
  533. package/dist/src/workflows/store/run-store.js.map +1 -1
  534. package/package.json +10 -5
  535. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  536. package/dist/gateway/static/root/assets/agents-CFFioJCI.js +0 -78
  537. package/dist/gateway/static/root/assets/apps-page-BYDmkbzG.js +0 -1
  538. package/dist/gateway/static/root/assets/channels-settings-CsbDaMvd.js +0 -1
  539. package/dist/gateway/static/root/assets/circle-check-C23XjkUj.js +0 -1
  540. package/dist/gateway/static/root/assets/copy-Dv6d4Dvw.js +0 -1
  541. package/dist/gateway/static/root/assets/cron-page-Apk-7p4p.js +0 -1
  542. package/dist/gateway/static/root/assets/dist-DmGDgpy2.js +0 -1
  543. package/dist/gateway/static/root/assets/extension-debug-page-pxFC-tUa.js +0 -1
  544. package/dist/gateway/static/root/assets/extension-settings-page-COXSv6xP.js +0 -1
  545. package/dist/gateway/static/root/assets/fetch-CFdKBnE6.js +0 -1
  546. package/dist/gateway/static/root/assets/gateway-startup-retry-DdngdObI.js +0 -1
  547. package/dist/gateway/static/root/assets/heartbeat-config-api-DcmAMYmN.js +0 -1
  548. package/dist/gateway/static/root/assets/index-C_2yKRJX.js +0 -4845
  549. package/dist/gateway/static/root/assets/index-DI5_GsZt.css +0 -1
  550. package/dist/gateway/static/root/assets/logs-page-DvTWUOzd.js +0 -2
  551. package/dist/gateway/static/root/assets/note-detail-page-CZbdugWZ.js +0 -180
  552. package/dist/gateway/static/root/assets/note-time-RdyBZxj3.js +0 -1
  553. package/dist/gateway/static/root/assets/notes-page-mEAwy3e1.js +0 -1
  554. package/dist/gateway/static/root/assets/schema-form-DEvdni_r.js +0 -1
  555. package/dist/gateway/static/root/assets/sessions-page-BsgffzV4.js +0 -1
  556. package/dist/gateway/static/root/assets/settings-advanced-gate-t6v8Dwb8.js +0 -2
  557. package/dist/gateway/static/root/assets/settings-form-section-BoYYZmJG.js +0 -1
  558. package/dist/gateway/static/root/assets/settings-page-ClIthYF8.js +0 -3
  559. package/dist/gateway/static/root/assets/share-preview-page-Dd9et7KD.js +0 -2
  560. package/dist/gateway/static/root/assets/skills-page-DEXtxyfQ.js +0 -2
  561. package/dist/gateway/static/root/assets/theme-store-BZozwAeK.js +0 -1
  562. package/dist/gateway/static/root/assets/url-DQRqHuL-.js +0 -3
  563. package/dist/gateway/static/root/assets/vendor-codemirror-DYoKfS8f.js +0 -45
  564. package/dist/gateway/static/root/assets/voice-api-key-field-CNrKzQrf.js +0 -1
  565. package/dist/gateway/static/root/assets/workflows-page-EMZkzJNN.js +0 -18
  566. package/dist/gateway/static/root/favicon-16.png +0 -0
  567. package/dist/gateway/static/root/favicon-32.png +0 -0
  568. package/dist/src/agent/goals/checklist-user.d.ts +0 -24
  569. package/dist/src/agent/goals/checklist-user.js +0 -92
  570. package/dist/src/agent/goals/checklist-user.js.map +0 -1
  571. package/dist/src/agent/goals/goal-run-store.d.ts +0 -19
  572. package/dist/src/agent/goals/goal-run-store.js +0 -138
  573. package/dist/src/agent/goals/goal-run-store.js.map +0 -1
  574. package/dist/src/agent/goals/goal-run-types.d.ts +0 -28
  575. package/dist/src/agent/goals/goal-run-types.js +0 -6
  576. package/dist/src/agent/goals/goal-run-types.js.map +0 -1
  577. package/dist/src/agent/goals/patch-from-user-action.d.ts +0 -20
  578. package/dist/src/agent/goals/patch-from-user-action.js +0 -103
  579. package/dist/src/agent/goals/patch-from-user-action.js.map +0 -1
  580. package/dist/src/cron/persistence.d.ts +0 -62
  581. package/dist/src/cron/persistence.js +0 -188
  582. package/dist/src/cron/persistence.js.map +0 -1
  583. /package/dist/gateway/static/root/assets/{note-detail-page-D4ZIVQbk.css → block-editor-D4ZIVQbk.css} +0 -0
@@ -1,356 +1,419 @@
1
+ import { init_agent_scope, normalizeAgentId } from "../agent/agent-scope.js";
1
2
  import { createLogger } from "../utils/logger/index.js";
2
3
  import { init_logger } from "../utils/logger.js";
3
- import { init_paths, resolveCronJobsPath } from "../config/paths.js";
4
+ import { buildSessionKey, init_session_key } from "../routing/session-key.js";
5
+ import { AddJobRequestSchema, JobDataSchema, UpdateJobRequestSchema } from "./validation.js";
6
+ import { deleteCronJob, getCronJob, listCronJobs, saveCronJob, saveCronJobs } from "../storage/sqlite/cron-job-repository.js";
7
+ import "../storage/sqlite/index.js";
8
+ import { computeNextRunAtMs, describeSchedule, timerDelayUntil } from "./schedule.js";
4
9
  import { DefaultJobExecutor } from "./executor.js";
5
- import { AddJobRequestSchema, UpdateJobRequestSchema } from "./validation.js";
6
- import { CronPersistence } from "./persistence.js";
7
10
  import { CronRunLogStore } from "./run-log-store.js";
8
- import nodeCron from "node-cron";
9
- import { CronExpressionParser } from "cron-parser";
10
- import { v4 } from "uuid";
11
+ import { randomUUID } from "node:crypto";
11
12
  //#region src/cron/service.ts
12
- init_paths();
13
13
  init_logger();
14
+ init_agent_scope();
15
+ init_session_key();
14
16
  const log = createLogger("CronService");
17
+ const DEFAULT_MAX_CONCURRENT_JOBS = 5;
18
+ const DEFAULT_MISSED_JOB_STAGGER_MS = 5e3;
19
+ var CronJobAlreadyRunningError = class extends Error {
20
+ jobId;
21
+ runningSessionKey;
22
+ constructor(jobId, runningSessionKey) {
23
+ super(`Job is already running: ${jobId}`);
24
+ this.name = "CronJobAlreadyRunningError";
25
+ this.jobId = jobId;
26
+ this.runningSessionKey = runningSessionKey;
27
+ }
28
+ };
29
+ function nowMs() {
30
+ return Date.now();
31
+ }
32
+ function runStatusFromExecution(status) {
33
+ if (status === "success") return "ok";
34
+ if (status === "cancelled" || status === "skipped") return "skipped";
35
+ return "error";
36
+ }
37
+ async function postFailureWebhook(url, payload) {
38
+ const res = await fetch(url, {
39
+ method: "POST",
40
+ headers: { "content-type": "application/json" },
41
+ body: JSON.stringify(payload)
42
+ });
43
+ if (!res.ok) {
44
+ const text = await res.text().catch(() => "");
45
+ throw new Error(`Cron failure webhook failed: HTTP ${res.status}${text ? ` ${text.slice(0, 200)}` : ""}`);
46
+ }
47
+ }
48
+ function inferJobName(input) {
49
+ if (input.name?.trim()) return input.name.trim();
50
+ if (input.payload.kind === "agentTurn") return input.payload.message.slice(0, 60) || "Agent task";
51
+ if (input.payload.kind === "systemEvent") return input.payload.text.slice(0, 60) || "System event";
52
+ if (input.payload.kind === "workflowRun") return `Workflow ${input.payload.definitionId}`;
53
+ if (input.payload.kind === "goalContinue") return `Goal ${input.payload.goalId}`;
54
+ return describeSchedule(input.schedule);
55
+ }
56
+ function resolveRunningSessionKey(job, deps) {
57
+ if (job.payload.kind !== "agentTurn") return void 0;
58
+ if (job.sessionTarget.startsWith("session:")) return job.sessionTarget.slice(8).trim() || void 0;
59
+ if (job.sessionTarget === "current") return job.sessionKey?.trim() || void 0;
60
+ if (job.sessionTarget !== "isolated") return;
61
+ const aid = job.agentId?.trim();
62
+ const fallbackAgentId = deps.getDefaultCronAgentId?.() ?? "main";
63
+ return buildSessionKey({
64
+ agentId: normalizeAgentId(aid || fallbackAgentId),
65
+ source: "cron",
66
+ accountId: "default",
67
+ peerKind: "dm",
68
+ peerId: `${job.id}-${randomUUID().slice(0, 8)}`
69
+ });
70
+ }
15
71
  var CronService = class {
16
- persistence;
17
- executor;
72
+ executor = new DefaultJobExecutor();
18
73
  runLogStore;
19
- tasks = /* @__PURE__ */ new Map();
20
74
  initialized = false;
21
- agentService = null;
22
- messageBus = null;
75
+ stopped = false;
76
+ running = false;
77
+ timer = null;
78
+ deps = {};
79
+ maxConcurrentJobs;
80
+ missedJobStaggerMs;
23
81
  constructor(config) {
24
- const filePath = config?.filePath || resolveCronJobsPath();
25
- this.persistence = new CronPersistence(filePath);
26
- this.executor = new DefaultJobExecutor();
27
82
  this.runLogStore = new CronRunLogStore(config?.dbPath);
28
83
  this.executor.setRunLogStore(this.runLogStore);
84
+ this.maxConcurrentJobs = Math.max(1, Math.floor(config?.maxConcurrentJobs ?? DEFAULT_MAX_CONCURRENT_JOBS));
85
+ this.missedJobStaggerMs = Math.max(0, Math.floor(config?.missedJobStaggerMs ?? DEFAULT_MISSED_JOB_STAGGER_MS));
29
86
  if (config?.agentService || config?.messageBus) this.setDeps({
30
87
  agentService: config.agentService,
31
88
  messageBus: config.messageBus
32
89
  });
33
90
  }
34
- /**
35
- * Set dependencies for the executor
36
- */
37
91
  setDeps(deps) {
38
- this.agentService = deps.agentService;
39
- this.messageBus = deps.messageBus;
40
- this.executor.setDeps(deps);
92
+ this.deps = {
93
+ ...this.deps,
94
+ ...deps
95
+ };
96
+ this.executor.setDeps(this.deps);
41
97
  log.debug("CronService dependencies set");
42
98
  }
43
- /**
44
- * Initialize the service and load all jobs
45
- */
46
99
  async initialize() {
47
100
  if (this.initialized) return;
48
- await this.persistence.initialize();
49
- await this.loadAllJobs();
101
+ this.stopped = false;
102
+ await this.recomputeAllNextRuns({ catchUp: true });
50
103
  this.initialized = true;
51
- log.debug("CronService initialized");
104
+ this.armTimer();
105
+ log.info("CronService initialized");
52
106
  }
53
- /**
54
- * Add a new job
55
- */
56
- async addJob(schedule, options) {
57
- const validationResult = AddJobRequestSchema.safeParse({
58
- schedule,
59
- ...options
60
- });
61
- if (!validationResult.success) {
62
- const errorMsg = validationResult.error?.errors.map((e) => e.message).join(", ") || "Unknown validation error";
63
- throw new Error(`Validation failed: ${errorMsg}`);
64
- }
65
- const data = validationResult.data;
66
- const id = v4().slice(0, 8);
67
- const now = (/* @__PURE__ */ new Date()).toISOString();
68
- const sessionTarget = data.sessionTarget ?? "main";
69
- const job = {
107
+ async addJob(scheduleOrInput, options) {
108
+ const raw = options ? {
109
+ ...options,
110
+ schedule: scheduleOrInput
111
+ } : scheduleOrInput;
112
+ const parsed = AddJobRequestSchema.parse(raw);
113
+ const ts = nowMs();
114
+ const id = parsed.id?.trim() || randomUUID().slice(0, 12);
115
+ const job = JobDataSchema.parse({
116
+ ...parsed,
70
117
  id,
71
- name: data.name,
72
- schedule: data.schedule,
73
- enabled: true,
74
- timezone: data.timezone,
75
- maxRetries: data.maxRetries ?? 3,
76
- timeout: data.timeout ?? 6e4,
77
- created_at: now,
78
- updated_at: now,
79
- sessionTarget,
80
- ...data.agentId ? { agentId: data.agentId } : {},
81
- ...data.workingDirectory ? { workingDirectory: data.workingDirectory } : {},
82
- payload: data.payload,
83
- delivery: data.delivery,
84
- model: data.model
85
- };
86
- await this.persistence.addJob(job);
87
- this.scheduleJob(job);
118
+ name: inferJobName(parsed),
119
+ enabled: parsed.enabled ?? true,
120
+ deleteAfterRun: parsed.deleteAfterRun ?? parsed.schedule.kind === "at",
121
+ createdAtMs: ts,
122
+ updatedAtMs: ts,
123
+ sessionTarget: parsed.sessionTarget ?? (parsed.payload.kind === "systemEvent" ? "main" : "isolated"),
124
+ wakeMode: parsed.wakeMode ?? "now",
125
+ state: { ...parsed.state ?? {} }
126
+ });
127
+ job.state.nextRunAtMs = computeNextRunAtMs(job, ts);
128
+ saveCronJob(job);
129
+ this.armTimer();
88
130
  log.info({
89
- jobId: id,
90
- name: data.name,
91
- sessionTarget
92
- }, "Job added");
131
+ jobId: job.id,
132
+ name: job.name,
133
+ schedule: job.schedule
134
+ }, "Cron job added");
93
135
  return {
94
- id,
95
- schedule: data.schedule
136
+ id: job.id,
137
+ schedule: job.schedule
96
138
  };
97
139
  }
98
- /**
99
- * List all jobs with next run time
100
- */
101
140
  async listJobs() {
102
- return (await this.persistence.getJobs()).map((job) => {
103
- let nextRun;
104
- if (job.enabled) try {
105
- const options = job.timezone ? { tz: job.timezone } : void 0;
106
- nextRun = CronExpressionParser.parse(job.schedule, options).next().toISOString();
107
- } catch (err) {
108
- log.debug({
109
- jobId: job.id,
110
- err
111
- }, "Failed to parse cron for next run");
112
- }
113
- return {
114
- id: job.id,
115
- name: job.name,
116
- schedule: job.schedule,
117
- enabled: job.enabled,
118
- timezone: job.timezone,
119
- maxRetries: job.maxRetries,
120
- timeout: job.timeout,
121
- sessionTarget: job.sessionTarget,
122
- ...job.agentId ? { agentId: job.agentId } : {},
123
- ...job.workingDirectory ? { workingDirectory: job.workingDirectory } : {},
124
- payload: job.payload,
125
- delivery: job.delivery,
126
- model: job.model,
127
- next_run: nextRun
128
- };
129
- });
141
+ return listCronJobs();
130
142
  }
131
- /**
132
- * Get a single job
133
- */
134
143
  async getJob(id) {
135
- return this.persistence.getJob(id);
144
+ return getCronJob(id);
136
145
  }
137
- /**
138
- * Update a job
139
- */
140
146
  async updateJob(id, updates) {
141
- const validationResult = UpdateJobRequestSchema.safeParse(updates);
142
- if (!validationResult.success) {
143
- const errorMsg = validationResult.error?.errors.map((e) => e.message).join(", ") || "Unknown validation error";
144
- throw new Error(`Validation failed: ${errorMsg}`);
145
- }
146
- const job = await this.persistence.getJob(id);
147
- if (!job) return false;
148
- const { agentId: agentIdPatch, workingDirectory: workingDirectoryPatch, ...rest } = validationResult.data;
149
- const patch = { ...rest };
150
- let clearAgentId = false;
151
- if (agentIdPatch === null) clearAgentId = true;
152
- else if (agentIdPatch !== void 0) patch.agentId = agentIdPatch;
153
- let clearWorkingDirectory = false;
154
- if (workingDirectoryPatch === null) clearWorkingDirectory = true;
155
- else if (workingDirectoryPatch !== void 0) patch.workingDirectory = workingDirectoryPatch;
156
- if (patch.schedule && patch.schedule !== job.schedule) this.cancelTask(id);
157
- await this.persistence.updateJob(id, patch, {
158
- clearAgentId,
159
- clearWorkingDirectory
147
+ const parsed = UpdateJobRequestSchema.parse(updates);
148
+ const current = getCronJob(id);
149
+ if (!current) return false;
150
+ const ts = nowMs();
151
+ const next = JobDataSchema.parse({
152
+ ...current,
153
+ ...parsed,
154
+ id: current.id,
155
+ createdAtMs: current.createdAtMs,
156
+ updatedAtMs: ts,
157
+ state: {
158
+ ...current.state,
159
+ ...parsed.state ?? {}
160
+ }
160
161
  });
161
- const updated = await this.persistence.getJob(id);
162
- if (updated && updated.enabled) this.scheduleJob(updated);
163
- log.info({ jobId: id }, "Job updated");
162
+ if ("schedule" in parsed || "enabled" in parsed) {
163
+ next.state.nextRunAtMs = computeNextRunAtMs(next, ts);
164
+ delete next.state.runningAtMs;
165
+ }
166
+ if ("agentId" in updates && updates.agentId?.trim() === "") delete next.agentId;
167
+ if ("workingDirectory" in updates && updates.workingDirectory?.trim() === "") delete next.workingDirectory;
168
+ saveCronJob(next);
169
+ this.armTimer();
170
+ log.info({ jobId: id }, "Cron job updated");
164
171
  return true;
165
172
  }
166
- /**
167
- * Remove a job
168
- */
169
173
  async removeJob(id) {
170
- this.cancelTask(id);
171
- const removed = await this.persistence.removeJob(id);
174
+ const removed = deleteCronJob(id);
172
175
  if (removed) {
176
+ this.executor.cancelJob(id);
173
177
  await this.runLogStore.deleteJobRuns(id);
174
- log.info({ jobId: id }, "Job removed");
178
+ this.armTimer();
179
+ log.info({ jobId: id }, "Cron job removed");
175
180
  }
176
181
  return removed;
177
182
  }
178
- /**
179
- * Toggle job enabled state
180
- */
181
183
  async toggleJob(id, enabled) {
182
- if (!await this.persistence.getJob(id)) return false;
183
- await this.persistence.updateJob(id, { enabled });
184
- if (enabled) {
185
- const updated = await this.persistence.getJob(id);
186
- if (updated) this.scheduleJob(updated);
187
- } else this.cancelTask(id);
188
- log.info({
189
- jobId: id,
190
- enabled
191
- }, "Job toggled");
192
- return true;
184
+ return this.updateJob(id, { enabled });
193
185
  }
194
- /**
195
- * Execution history for one job: merged in-memory (incl. running) + persisted SQLite rows.
196
- */
197
186
  async getJobHistory(jobId, limit) {
198
- const cap = Math.min(Math.max(limit ?? 10, 1), 500);
199
- const [disk, memory] = await Promise.all([this.runLogStore.readJobHistory(jobId, cap * 2), Promise.resolve(this.executor.getHistory(jobId, cap * 2))]);
200
- const byId = /* @__PURE__ */ new Map();
201
- for (const e of memory) byId.set(e.id, e);
202
- for (const e of disk) if (!byId.has(e.id)) byId.set(e.id, e);
203
- return [...byId.values()].sort((a, b) => new Date(b.startedAt).getTime() - new Date(a.startedAt).getTime()).slice(0, cap);
187
+ return this.runLogStore.readJobHistory(jobId, Math.min(Math.max(limit ?? 10, 1), 500));
204
188
  }
205
- /**
206
- * Latest runs across all jobs (persisted rows + optional job name).
207
- */
208
189
  async getAllRunsHistory(limit) {
209
190
  const cap = Math.min(Math.max(limit ?? 50, 1), 500);
210
- const jobs = await this.persistence.getJobs();
211
- const jobNames = new Map(jobs.map((j) => [j.id, j.name]));
212
- return this.runLogStore.readAllRuns(cap, jobNames);
191
+ const jobs = listCronJobs();
192
+ const names = new Map(jobs.map((job) => [job.id, job.name]));
193
+ return this.runLogStore.readAllRuns(cap, names);
213
194
  }
214
- /**
215
- * Get service metrics
216
- */
217
195
  async getMetrics() {
218
- const jobs = await this.persistence.getJobs();
219
- const enabled = jobs.filter((j) => j.enabled);
220
- let nextScheduledJob;
221
- for (const job of enabled) try {
222
- const options = job.timezone ? { tz: job.timezone } : void 0;
223
- const next = CronExpressionParser.parse(job.schedule, options).next();
224
- if (!nextScheduledJob || next.getTime() < nextScheduledJob.runAt.getTime()) nextScheduledJob = {
225
- id: job.id,
226
- name: job.name,
227
- runAt: next.toDate()
228
- };
229
- } catch {}
196
+ const jobs = listCronJobs();
197
+ const enabled = jobs.filter((job) => job.enabled);
198
+ const next = enabled.filter((job) => job.state.nextRunAtMs != null).toSorted((a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0))[0];
230
199
  return {
231
200
  totalJobs: jobs.length,
232
- runningJobs: this.tasks.size,
201
+ runningJobs: jobs.filter((job) => job.state.runningAtMs != null).length,
233
202
  enabledJobs: enabled.length,
234
- failedLastHour: 0,
203
+ failedLastHour: jobs.filter((job) => job.state.lastRunStatus === "error" && (job.state.lastRunAtMs ?? 0) >= nowMs() - 60 * 6e4).length,
235
204
  avgExecutionTime: 0,
236
- nextScheduledJob
205
+ nextScheduledJob: next?.state.nextRunAtMs ? {
206
+ id: next.id,
207
+ name: next.name,
208
+ runAt: new Date(next.state.nextRunAtMs)
209
+ } : void 0
237
210
  };
238
211
  }
239
- /**
240
- * Update config (hot reload)
241
- */
242
- updateConfig(_config) {
243
- log.debug("Cron config updated (jobs managed separately via addJob/removeJob)");
212
+ updateConfig(config) {
213
+ this.maxConcurrentJobs = Math.max(1, Math.floor(config.cron?.maxConcurrentJobs ?? DEFAULT_MAX_CONCURRENT_JOBS));
214
+ this.armTimer();
244
215
  }
245
- /**
246
- * Health check
247
- */
248
216
  async healthCheck() {
249
217
  const issues = [];
250
218
  if (!this.initialized) issues.push("Service not initialized");
251
- const jobs = await this.persistence.getJobs();
252
- for (const job of jobs) if (!nodeCron.validate(job.schedule)) issues.push(`Job ${job.id} has invalid schedule`);
253
- for (const job of jobs) if (job.enabled && job.sessionTarget === "isolated" && !this.agentService) {
254
- issues.push(`Job ${job.id} requires agent service but none configured`);
255
- break;
219
+ for (const job of listCronJobs()) {
220
+ if (!JobDataSchema.safeParse(job).success) issues.push(`Job ${job.id} is invalid`);
221
+ if (job.enabled && job.state.nextRunAtMs == null && job.schedule.kind !== "at") issues.push(`Job ${job.id} has no next run`);
256
222
  }
257
- let status = "healthy";
258
- if (issues.length > 0) status = issues.length > 5 ? "unhealthy" : "degraded";
259
223
  return {
260
- status,
224
+ status: issues.length === 0 ? "healthy" : issues.length > 5 ? "unhealthy" : "degraded",
261
225
  issues
262
226
  };
263
227
  }
264
- /**
265
- * Run a job immediately (manual trigger)
266
- */
267
228
  async runJobNow(id) {
268
- const job = await this.persistence.getJob(id);
229
+ const job = getCronJob(id);
269
230
  if (!job) throw new Error(`Job not found: ${id}`);
270
- if (!job.enabled) throw new Error(`Job is disabled: ${id}`);
271
- await this.executeJob(job);
231
+ if (job.state.runningAtMs != null) throw new CronJobAlreadyRunningError(id, job.state.runningSessionKey);
232
+ return {
233
+ job: this.startSingleJob(job, { manual: true }),
234
+ history: await this.getJobHistory(id, 20)
235
+ };
272
236
  }
273
- /**
274
- * Stop all jobs and cleanup
275
- */
276
237
  async stop(options) {
277
- const timeout = options?.timeout ?? 3e4;
278
- for (const [id, task] of this.tasks) {
279
- task.stop();
280
- this.executor.cancelJob(id);
238
+ this.stopped = true;
239
+ if (this.timer) {
240
+ clearTimeout(this.timer);
241
+ this.timer = null;
281
242
  }
282
- this.tasks.clear();
243
+ for (const job of listCronJobs()) this.executor.cancelJob(job.id);
283
244
  if (options?.waitForRunning) {
284
- const start = Date.now();
285
- while (Date.now() - start < timeout) {
286
- if (this.executor.getRunningExecutions().length === 0) break;
287
- await new Promise((r) => setTimeout(r, 100));
245
+ const started = nowMs();
246
+ const timeout = options.timeout ?? 3e4;
247
+ while (nowMs() - started < timeout) {
248
+ if (listCronJobs().every((job) => job.state.runningAtMs == null)) break;
249
+ await new Promise((resolve) => setTimeout(resolve, 100));
288
250
  }
289
251
  }
290
- await this.persistence.flush();
291
252
  log.info("CronService stopped");
292
253
  }
293
- /**
294
- * Load and schedule all enabled jobs
295
- */
296
- async loadAllJobs() {
297
- const jobs = await this.persistence.getJobs();
298
- for (const job of jobs) if (job.enabled) this.scheduleJob(job);
299
- log.debug({ count: this.tasks.size }, "Jobs loaded");
254
+ async recomputeAllNextRuns(opts) {
255
+ const ts = nowMs();
256
+ saveCronJobs(listCronJobs().map((job, index) => {
257
+ const next = {
258
+ ...job,
259
+ state: { ...job.state }
260
+ };
261
+ if (next.state.runningAtMs != null) {
262
+ next.state.lastRunStatus = "error";
263
+ next.state.lastError = "Interrupted by gateway restart";
264
+ next.state.consecutiveErrors = (next.state.consecutiveErrors ?? 0) + 1;
265
+ delete next.state.runningAtMs;
266
+ }
267
+ if (next.enabled) {
268
+ const existingNext = next.state.nextRunAtMs;
269
+ if (opts?.catchUp && existingNext != null && existingNext <= ts) next.state.nextRunAtMs = ts + index * this.missedJobStaggerMs;
270
+ else next.state.nextRunAtMs = computeNextRunAtMs(next, ts);
271
+ } else next.state.nextRunAtMs = void 0;
272
+ return next;
273
+ }));
300
274
  }
301
- /**
302
- * Schedule a job with node-cron
303
- */
304
- scheduleJob(job) {
305
- this.cancelTask(job.id);
306
- if (!nodeCron.validate(job.schedule)) {
307
- log.error({
308
- jobId: job.id,
309
- schedule: job.schedule
310
- }, "Invalid cron expression");
311
- return;
275
+ armTimer() {
276
+ if (this.stopped) return;
277
+ if (this.timer) {
278
+ clearTimeout(this.timer);
279
+ this.timer = null;
312
280
  }
313
- const options = job.timezone ? { timezone: job.timezone } : void 0;
314
- const task = nodeCron.schedule(job.schedule, async () => {
315
- await this.executeJob(job);
316
- }, options);
317
- this.tasks.set(job.id, task);
318
- log.debug({
319
- jobId: job.id,
320
- schedule: job.schedule
321
- }, "Job scheduled");
281
+ const next = listCronJobs().filter((job) => job.enabled && job.state.nextRunAtMs != null).toSorted((a, b) => (a.state.nextRunAtMs ?? 0) - (b.state.nextRunAtMs ?? 0))[0];
282
+ if (!next?.state.nextRunAtMs) return;
283
+ this.timer = setTimeout(() => {
284
+ this.onTimer();
285
+ }, timerDelayUntil(next.state.nextRunAtMs));
286
+ this.timer.unref?.();
322
287
  }
323
- /**
324
- * Execute a job with retry logic
325
- */
326
- async executeJob(job) {
327
- if (this.executor.isRunning(job.id)) {
328
- log.warn({ jobId: job.id }, "Job already running, skipping");
288
+ async onTimer() {
289
+ if (this.stopped) return;
290
+ if (this.running) {
291
+ this.armTimer();
329
292
  return;
330
293
  }
331
- const controller = new AbortController();
294
+ this.running = true;
332
295
  try {
333
- await this.executor.execute(job, controller.signal);
334
- } catch (error) {
296
+ const ts = nowMs();
297
+ const due = listCronJobs().filter((job) => job.enabled && job.state.nextRunAtMs != null && job.state.nextRunAtMs <= ts && job.state.runningAtMs == null).slice(0, this.maxConcurrentJobs);
298
+ if (due.length === 0) return;
299
+ const reserved = due.map((job) => ({
300
+ ...job,
301
+ state: {
302
+ ...job.state,
303
+ runningAtMs: ts
304
+ }
305
+ }));
306
+ saveCronJobs(reserved);
307
+ await Promise.all(reserved.map((job) => this.runSingleJob(job)));
308
+ } finally {
309
+ this.running = false;
310
+ this.armTimer();
311
+ }
312
+ }
313
+ startSingleJob(job, opts) {
314
+ const started = nowMs();
315
+ const runningSessionKey = resolveRunningSessionKey(job, this.deps);
316
+ const reserved = {
317
+ ...job,
318
+ state: {
319
+ ...job.state,
320
+ runningAtMs: started,
321
+ ...runningSessionKey ? { runningSessionKey } : {}
322
+ }
323
+ };
324
+ saveCronJob(reserved);
325
+ this.runReservedJob(reserved, started, runningSessionKey, opts).catch((err) => {
335
326
  log.error({
336
- jobId: job.id,
337
- err: error
338
- }, "Job execution failed");
327
+ err,
328
+ jobId: job.id
329
+ }, `Background cron job failed: ${err instanceof Error ? err.message : String(err)}`);
330
+ });
331
+ return reserved;
332
+ }
333
+ async runSingleJob(job, opts) {
334
+ const started = nowMs();
335
+ const runningSessionKey = resolveRunningSessionKey(job, this.deps);
336
+ const reserved = {
337
+ ...job,
338
+ state: {
339
+ ...job.state,
340
+ runningAtMs: started,
341
+ ...runningSessionKey ? { runningSessionKey } : {}
342
+ }
343
+ };
344
+ saveCronJob(reserved);
345
+ await this.runReservedJob(reserved, started, runningSessionKey, opts);
346
+ }
347
+ async runReservedJob(reserved, started, runningSessionKey, opts) {
348
+ const controller = new AbortController();
349
+ await this.executor.execute(runningSessionKey ? {
350
+ ...reserved,
351
+ sessionKey: runningSessionKey
352
+ } : reserved, controller.signal, this.deps);
353
+ const latestRun = (await this.getJobHistory(reserved.id, 1))[0];
354
+ const finished = nowMs();
355
+ const status = latestRun ? runStatusFromExecution(latestRun.status) : "error";
356
+ const latest = getCronJob(reserved.id);
357
+ if (!latest) return;
358
+ const next = {
359
+ ...latest,
360
+ state: {
361
+ ...latest.state,
362
+ lastRunAtMs: finished,
363
+ lastRunStatus: status,
364
+ lastError: latestRun?.error,
365
+ lastDurationMs: finished - started,
366
+ consecutiveErrors: status === "error" ? (latest.state.consecutiveErrors ?? 0) + 1 : 0,
367
+ consecutiveSkipped: status === "skipped" ? (latest.state.consecutiveSkipped ?? 0) + 1 : 0,
368
+ lastDeliveryStatus: latest.delivery?.mode && latest.delivery.mode !== "none" ? "unknown" : "not-requested"
369
+ }
370
+ };
371
+ delete next.state.runningAtMs;
372
+ delete next.state.runningSessionKey;
373
+ if (!opts?.manual && next.deleteAfterRun && status === "ok") {
374
+ await this.removeJob(next.id);
375
+ return;
339
376
  }
377
+ next.state.nextRunAtMs = computeNextRunAtMs(next, finished);
378
+ saveCronJob(next);
379
+ await this.maybeEmitFailureAlert(next);
340
380
  }
341
- /**
342
- * Cancel a scheduled task
343
- */
344
- cancelTask(id) {
345
- const task = this.tasks.get(id);
346
- if (task) {
347
- task.stop();
348
- this.tasks.delete(id);
349
- log.debug({ jobId: id }, "Task cancelled");
381
+ async maybeEmitFailureAlert(job) {
382
+ if (!job.failureAlert) return;
383
+ if (job.state.lastRunStatus !== "error") return;
384
+ const threshold = job.failureAlert.after ?? 1;
385
+ if ((job.state.consecutiveErrors ?? 0) < threshold) return;
386
+ const ts = nowMs();
387
+ const cooldownMs = job.failureAlert.cooldownMs ?? 60 * 6e4;
388
+ if (job.state.lastFailureAlertAtMs && ts - job.state.lastFailureAlertAtMs < cooldownMs) return;
389
+ const channel = job.failureAlert.channel || job.delivery?.channel;
390
+ const to = job.failureAlert.to || job.delivery?.to;
391
+ if (!to) return;
392
+ if (job.failureAlert.mode === "webhook") {
393
+ await postFailureWebhook(to, {
394
+ jobId: job.id,
395
+ jobName: job.name,
396
+ status: job.state.lastRunStatus,
397
+ error: job.state.lastError ?? "Unknown error",
398
+ consecutiveErrors: job.state.consecutiveErrors ?? 0,
399
+ lastRunAtMs: job.state.lastRunAtMs
400
+ });
401
+ job.state.lastFailureAlertAtMs = ts;
402
+ saveCronJob(job);
403
+ return;
350
404
  }
405
+ if (!this.deps.messageBus || !channel) return;
406
+ await this.deps.messageBus.publishOutbound({
407
+ channel,
408
+ chat_id: to,
409
+ type: "message",
410
+ content: `Cron job failed: ${job.name}\n${job.state.lastError ?? "Unknown error"}`
411
+ });
412
+ job.state.lastFailureAlertAtMs = ts;
413
+ saveCronJob(job);
351
414
  }
352
415
  };
353
416
  //#endregion
354
- export { CronService };
417
+ export { CronJobAlreadyRunningError, CronService };
355
418
 
356
419
  //# sourceMappingURL=service.js.map