@xopcai/xopc 0.0.110 → 0.0.111

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 (301) 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/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +41 -0
  6. package/dist/gateway/static/root/assets/agent-avatar-dicebear-zlx9l5Yp.js +1 -0
  7. package/dist/gateway/static/root/assets/agent-browser-settings-page-B-0zGjt8.js +6 -0
  8. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-Bz7JWjRM.js +1 -0
  9. package/dist/gateway/static/root/assets/agents-DwDnJlXT.js +71 -0
  10. package/dist/gateway/static/root/assets/app-management-settings-panel-DaQwdeCq.js +1 -0
  11. package/dist/gateway/static/root/assets/appearance-settings-D2zv6r3P.js +1 -0
  12. package/dist/gateway/static/root/assets/apps-page-BIppe_jj.js +1 -0
  13. package/dist/gateway/static/root/assets/archive-plugin-DEmu8eH7.js +1 -0
  14. package/dist/gateway/static/root/assets/attachment-load-B98lJoN5.js +2 -0
  15. package/dist/gateway/static/root/assets/{attachment-preview-renderer-CybMSIoS.js → attachment-preview-renderer-DonnL2dL.js} +1 -1
  16. package/dist/gateway/static/root/assets/binary-plugins-CL9QKmyo.js +2 -0
  17. package/dist/gateway/static/root/assets/block-editor-BOAhMAhT.js +180 -0
  18. package/dist/gateway/static/root/assets/channels-settings-Br8iRnXp.js +1 -0
  19. package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +1 -0
  20. package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +1 -0
  21. package/dist/gateway/static/root/assets/config-api-0o1WYdz2.js +3 -0
  22. package/dist/gateway/static/root/assets/connectors-settings-DDvHo9in.js +2 -0
  23. package/dist/gateway/static/root/assets/cron-api-Dj_UZKST.js +1 -0
  24. package/dist/gateway/static/root/assets/cron-dreaming-jobs-nCMWCf0p.js +1 -0
  25. package/dist/gateway/static/root/assets/cron-page-Dv7GII9G.js +1 -0
  26. package/dist/gateway/static/root/assets/cron-schedule-picker-DH10KgD6.js +1 -0
  27. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
  28. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
  29. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
  30. package/dist/gateway/static/root/assets/dreaming-scene-BHMRVEUS.js +4585 -0
  31. package/dist/gateway/static/root/assets/dreaming-settings-L2rgZDQl.js +1 -0
  32. package/dist/gateway/static/root/assets/extension-debug-page-Cjx6pZVz.js +1 -0
  33. package/dist/gateway/static/root/assets/{extension-page-W1wiG38F.js → extension-page-BSPNL90V.js} +1 -1
  34. package/dist/gateway/static/root/assets/extension-settings-page-m_UQYkVc.js +1 -0
  35. package/dist/gateway/static/root/assets/fetch-Bs7in_4F.js +1 -0
  36. package/dist/gateway/static/root/assets/format-interval-label-CftJ5uXu.js +1 -0
  37. package/dist/gateway/static/root/assets/gateway-config-api-Clfck-hW.js +1 -0
  38. package/dist/gateway/static/root/assets/gateway-settings-CS177xni.js +1 -0
  39. package/dist/gateway/static/root/assets/gateway-startup-retry-BkjVJc38.js +1 -0
  40. package/dist/gateway/static/root/assets/goal-detail-page-kqJue0sE.js +1 -0
  41. package/dist/gateway/static/root/assets/goals-page-C0FujUB5.js +2 -0
  42. package/dist/gateway/static/root/assets/goals-settings-CJnzNSDo.js +1 -0
  43. package/dist/gateway/static/root/assets/heartbeat-config-api-Cp7CPuIn.js +1 -0
  44. package/dist/gateway/static/root/assets/heartbeat-settings-ifSI1Wbh.js +1 -0
  45. package/dist/gateway/static/root/assets/html-workspace-editor-CQLWDiwE.js +1 -0
  46. package/dist/gateway/static/root/assets/index-COkF54xv.js +121 -0
  47. package/dist/gateway/static/root/assets/index-DIaSNGEO.css +1 -0
  48. package/dist/gateway/static/root/assets/interval-presets-B29Ss_2y.js +2 -0
  49. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings--MI1rYl7.js +1 -0
  50. package/dist/gateway/static/root/assets/locale-store-DjbfSsfA.js +1 -0
  51. package/dist/gateway/static/root/assets/logs-page-BwrVNlyW.js +2 -0
  52. package/dist/gateway/static/root/assets/markdown-editor-AssmZFx4.js +2 -0
  53. package/dist/gateway/static/root/assets/markdown-split-B_oc9lJe.js +1 -0
  54. package/dist/gateway/static/root/assets/media-plugins-DLPvB5H3.js +1 -0
  55. package/dist/gateway/static/root/assets/mermaid-render-BbqDc_LQ.js +134 -0
  56. package/dist/gateway/static/root/assets/messages-Csef1aW7.js +3 -0
  57. package/dist/gateway/static/root/assets/middleware-Pd0e8Igk.js +1 -0
  58. package/dist/gateway/static/root/assets/models-hub-panel-DHGiTIvf.js +2 -0
  59. package/dist/gateway/static/root/assets/note-detail-page-BM7zlDiT.js +2 -0
  60. package/dist/gateway/static/root/assets/note-image-lightbox-rSqAgOi9.js +1 -0
  61. package/dist/gateway/static/root/assets/note-time-hm6JO_Wi.js +1 -0
  62. package/dist/gateway/static/root/assets/notes-page-C9ACGEty.js +1 -0
  63. package/dist/gateway/static/root/assets/preview-open-alternatives-Bw_N2oZi.js +1 -0
  64. package/dist/gateway/static/root/assets/remote-access-hub-BhcWIKuM.js +1 -0
  65. package/dist/gateway/static/root/assets/save-bar-controls-CNP2jmw0.js +1 -0
  66. package/dist/gateway/static/root/assets/schedule-field-BPAWui3P.js +1 -0
  67. package/dist/gateway/static/root/assets/schedule-summary-B-hdSRdR.js +1 -0
  68. package/dist/gateway/static/root/assets/schema-form-CDPzua9q.js +1 -0
  69. package/dist/gateway/static/root/assets/sessions-page-DzkpSDZr.js +1 -0
  70. package/dist/gateway/static/root/assets/settings-advanced-gate-BYS-rpzn.js +1 -0
  71. package/dist/gateway/static/root/assets/settings-collapsible-section-C9bff85B.js +1 -0
  72. package/dist/gateway/static/root/assets/settings-form-section-BsrK7TBF.js +1 -0
  73. package/dist/gateway/static/root/assets/settings-page-DWK4Zo7s.js +1 -0
  74. package/dist/gateway/static/root/assets/setup-status-panel-DJiksNu4.js +1 -0
  75. package/dist/gateway/static/root/assets/share-preview-page-DnutoY_S.js +2 -0
  76. package/dist/gateway/static/root/assets/shares-settings-6oRgJMpn.js +1 -0
  77. package/dist/gateway/static/root/assets/skill-reload-api-CU9i0nJV.js +1 -0
  78. package/dist/gateway/static/root/assets/skills-page-ERbdWENm.js +2 -0
  79. package/dist/gateway/static/root/assets/system-settings-panel-qP1JDtDd.js +1 -0
  80. package/dist/gateway/static/root/assets/theme-store-CD2wtgZV.js +1 -0
  81. package/dist/gateway/static/root/assets/use-agent-defaults-form-D3FGVLZb.js +1 -0
  82. package/dist/gateway/static/root/assets/use-blob-object-url-D4BFuzZB.js +1 -0
  83. package/dist/gateway/static/root/assets/use-channel-catalog-C4mg1hjD.js +1 -0
  84. package/dist/gateway/static/root/assets/use-settings-tab-guard-F6C0mpJt.js +1 -0
  85. package/dist/gateway/static/root/assets/vendor-codemirror-CNP1wPe7.js +45 -0
  86. package/dist/gateway/static/root/assets/voice-api-key-field-BnDDb6qO.js +1 -0
  87. package/dist/gateway/static/root/assets/voice-player-store-B2EwIhtY.js +1 -0
  88. package/dist/gateway/static/root/assets/{workflow-page.utils-EYg_xBQS.js → workflow-page.utils-CRB7WX9l.js} +1 -1
  89. package/dist/gateway/static/root/assets/workflows-page-2Fptr0je.js +18 -0
  90. package/dist/gateway/static/root/index.html +12 -10
  91. package/dist/package.js +1 -1
  92. package/dist/src/agent/goals/checklist-judge.d.ts +5 -0
  93. package/dist/src/agent/goals/checklist-judge.js +26 -2
  94. package/dist/src/agent/goals/checklist-judge.js.map +1 -1
  95. package/dist/src/agent/goals/evaluate-turn.d.ts +5 -1
  96. package/dist/src/agent/goals/evaluate-turn.js +29 -3
  97. package/dist/src/agent/goals/evaluate-turn.js.map +1 -1
  98. package/dist/src/agent/goals/goal-locale.d.ts +0 -2
  99. package/dist/src/agent/goals/goal-locale.js +2 -15
  100. package/dist/src/agent/goals/goal-locale.js.map +1 -1
  101. package/dist/src/agent/goals/persistent-goal-service.d.ts +9 -0
  102. package/dist/src/agent/goals/persistent-goal-service.js +2 -1
  103. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
  104. package/dist/src/agent/goals/post-turn.d.ts +7 -0
  105. package/dist/src/agent/goals/post-turn.js +68 -23
  106. package/dist/src/agent/goals/post-turn.js.map +1 -1
  107. package/dist/src/agent/goals/state.d.ts +0 -5
  108. package/dist/src/agent/goals/state.js +1 -96
  109. package/dist/src/agent/goals/state.js.map +1 -1
  110. package/dist/src/agent/messaging/command-handler.d.ts +4 -0
  111. package/dist/src/agent/messaging/command-handler.js +6 -2
  112. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  113. package/dist/src/agent/service/direct-turn-helpers.d.ts +2 -0
  114. package/dist/src/agent/service/direct-turn-helpers.js +3 -2
  115. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  116. package/dist/src/agent/service/process-direct-streaming.js +10 -1
  117. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  118. package/dist/src/agent/service.js +20 -1
  119. package/dist/src/agent/service.js.map +1 -1
  120. package/dist/src/agent/service.types.d.ts +8 -0
  121. package/dist/src/agent/tools/cronjob-tool.d.ts +2 -0
  122. package/dist/src/agent/tools/cronjob-tool.js +27 -4
  123. package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
  124. package/dist/src/agent/tools/edit.d.ts +2 -0
  125. package/dist/src/agent/tools/edit.js +10 -0
  126. package/dist/src/agent/tools/edit.js.map +1 -1
  127. package/dist/src/agent/tools/factory.js +16 -3
  128. package/dist/src/agent/tools/factory.js.map +1 -1
  129. package/dist/src/agent/tools/goal-evidence-recorder.d.ts +6 -0
  130. package/dist/src/agent/tools/goal-evidence-recorder.js +34 -0
  131. package/dist/src/agent/tools/goal-evidence-recorder.js.map +1 -0
  132. package/dist/src/agent/tools/goal-tool.d.ts +19 -0
  133. package/dist/src/agent/tools/goal-tool.js +101 -0
  134. package/dist/src/agent/tools/goal-tool.js.map +1 -0
  135. package/dist/src/agent/tools/index.d.ts +1 -0
  136. package/dist/src/agent/tools/index.js +2 -1
  137. package/dist/src/agent/tools/shell.d.ts +2 -0
  138. package/dist/src/agent/tools/shell.js +17 -2
  139. package/dist/src/agent/tools/shell.js.map +1 -1
  140. package/dist/src/agent/tools/workflow-tool.d.ts +1 -0
  141. package/dist/src/agent/tools/workflow-tool.js +10 -2
  142. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  143. package/dist/src/agent/tools/write.d.ts +2 -0
  144. package/dist/src/agent/tools/write.js +11 -0
  145. package/dist/src/agent/tools/write.js.map +1 -1
  146. package/dist/src/channels/attachments/inbound-persist.d.ts +7 -0
  147. package/dist/src/channels/attachments/inbound-persist.js +20 -2
  148. package/dist/src/channels/attachments/inbound-persist.js.map +1 -1
  149. package/dist/src/chat-commands/builtins/goal.d.ts +1 -1
  150. package/dist/src/chat-commands/builtins/goal.js +55 -97
  151. package/dist/src/chat-commands/builtins/goal.js.map +1 -1
  152. package/dist/src/chat-commands/builtins/subgoal.d.ts +1 -1
  153. package/dist/src/chat-commands/builtins/subgoal.js +49 -108
  154. package/dist/src/chat-commands/builtins/subgoal.js.map +1 -1
  155. package/dist/src/chat-commands/builtins/workflow.js +132 -8
  156. package/dist/src/chat-commands/builtins/workflow.js.map +1 -1
  157. package/dist/src/chat-commands/context.d.ts +3 -0
  158. package/dist/src/chat-commands/context.js +5 -0
  159. package/dist/src/chat-commands/context.js.map +1 -1
  160. package/dist/src/chat-commands/types.d.ts +5 -0
  161. package/dist/src/cli/command-catalog.js +43 -0
  162. package/dist/src/cli/command-catalog.js.map +1 -1
  163. package/dist/src/cli/command-loaders.js +1 -0
  164. package/dist/src/cli/command-loaders.js.map +1 -1
  165. package/dist/src/cli/command-manifest.js +4 -0
  166. package/dist/src/cli/command-manifest.js.map +1 -1
  167. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  168. package/dist/src/cli/commands/goal.d.ts +4 -0
  169. package/dist/src/cli/commands/goal.js +213 -0
  170. package/dist/src/cli/commands/goal.js.map +1 -0
  171. package/dist/src/cli/commands/onboard.js +11 -5
  172. package/dist/src/cli/commands/onboard.js.map +1 -1
  173. package/dist/src/config/index.js +2 -2
  174. package/dist/src/config/schema.d.ts +115 -0
  175. package/dist/src/config/schema.js +63 -4
  176. package/dist/src/config/schema.js.map +1 -1
  177. package/dist/src/config/web-patch.d.ts +14 -0
  178. package/dist/src/config/web-patch.js +45 -6
  179. package/dist/src/config/web-patch.js.map +1 -1
  180. package/dist/src/cron/executor.d.ts +2 -0
  181. package/dist/src/cron/executor.js +25 -0
  182. package/dist/src/cron/executor.js.map +1 -1
  183. package/dist/src/cron/job-content.js +1 -0
  184. package/dist/src/cron/job-content.js.map +1 -1
  185. package/dist/src/cron/types.d.ts +19 -1
  186. package/dist/src/cron/validation.d.ts +20 -0
  187. package/dist/src/cron/validation.js +7 -0
  188. package/dist/src/cron/validation.js.map +1 -1
  189. package/dist/src/gateway/hono/lib/config-payload.d.ts +14 -0
  190. package/dist/src/gateway/hono/routes/goals.d.ts +1 -1
  191. package/dist/src/gateway/hono/routes/goals.js +670 -173
  192. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  193. package/dist/src/gateway/hono/routes/home.d.ts +5 -0
  194. package/dist/src/gateway/hono/routes/home.js +88 -3
  195. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  196. package/dist/src/gateway/hono/routes/notes.js +20 -14
  197. package/dist/src/gateway/hono/routes/notes.js.map +1 -1
  198. package/dist/src/gateway/hono/routes/workflows.js +6 -2
  199. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  200. package/dist/src/gateway/hono/sse.js.map +1 -1
  201. package/dist/src/gateway/service/agent-runner.d.ts +2 -0
  202. package/dist/src/gateway/service/agent-runner.js +6 -2
  203. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  204. package/dist/src/gateway/service/run-gateway-agent.d.ts +3 -0
  205. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  206. package/dist/src/gateway/service.d.ts +8 -0
  207. package/dist/src/gateway/service.js +69 -2
  208. package/dist/src/gateway/service.js.map +1 -1
  209. package/dist/src/goals/goal-notifications.d.ts +29 -0
  210. package/dist/src/goals/goal-notifications.js +154 -0
  211. package/dist/src/goals/goal-notifications.js.map +1 -0
  212. package/dist/src/goals/goal-queue-store.d.ts +16 -0
  213. package/dist/src/goals/goal-queue-store.js +131 -0
  214. package/dist/src/goals/goal-queue-store.js.map +1 -0
  215. package/dist/src/goals/goal-queue-types.d.ts +31 -0
  216. package/dist/src/goals/goal-queue-types.js +1 -0
  217. package/dist/src/goals/goal-runner.d.ts +17 -0
  218. package/dist/src/goals/goal-runner.js +127 -0
  219. package/dist/src/goals/goal-runner.js.map +1 -0
  220. package/dist/src/goals/goal-service.d.ts +77 -0
  221. package/dist/src/goals/goal-service.js +261 -0
  222. package/dist/src/goals/goal-service.js.map +1 -0
  223. package/dist/src/goals/goal-store.d.ts +38 -0
  224. package/dist/src/goals/goal-store.js +404 -0
  225. package/dist/src/goals/goal-store.js.map +1 -0
  226. package/dist/src/goals/goal-workflow-judge.d.ts +13 -0
  227. package/dist/src/goals/goal-workflow-judge.js +147 -0
  228. package/dist/src/goals/goal-workflow-judge.js.map +1 -0
  229. package/dist/src/goals/index.d.ts +10 -0
  230. package/dist/src/goals/index.js +7 -0
  231. package/dist/src/goals/types.d.ts +119 -0
  232. package/dist/src/goals/types.js +1 -0
  233. package/dist/src/storage/sqlite/migrations/006_add_goals.sql +108 -0
  234. package/dist/src/storage/sqlite/migrations/007_goal_run_judge_schema.sql +4 -0
  235. package/dist/src/storage/sqlite/migrations/008_goal_queue_workflow_runs.sql +53 -0
  236. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  237. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  238. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  239. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  240. package/dist/src/storage/sqlite/schema.js +1 -1
  241. package/dist/src/storage/sqlite/schema.sql +163 -0
  242. package/dist/src/utils/logger/stats.d.ts +1 -1
  243. package/dist/src/workflows/domain/run.d.ts +1 -0
  244. package/dist/src/workflows/domain/run.js.map +1 -1
  245. package/dist/src/workflows/service/workflow-run-service.d.ts +1 -0
  246. package/dist/src/workflows/service/workflow-run-service.js +5 -1
  247. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  248. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -0
  249. package/dist/src/workflows/service/workflow-session-bridge.js +7 -0
  250. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  251. package/dist/src/workflows/store/run-index-store.d.ts +8 -0
  252. package/dist/src/workflows/store/run-index-store.js +58 -0
  253. package/dist/src/workflows/store/run-index-store.js.map +1 -0
  254. package/dist/src/workflows/store/run-store.d.ts +2 -0
  255. package/dist/src/workflows/store/run-store.js +14 -21
  256. package/dist/src/workflows/store/run-store.js.map +1 -1
  257. package/package.json +9 -3
  258. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  259. package/dist/gateway/static/root/assets/agents-CFFioJCI.js +0 -78
  260. package/dist/gateway/static/root/assets/apps-page-BYDmkbzG.js +0 -1
  261. package/dist/gateway/static/root/assets/channels-settings-CsbDaMvd.js +0 -1
  262. package/dist/gateway/static/root/assets/circle-check-C23XjkUj.js +0 -1
  263. package/dist/gateway/static/root/assets/copy-Dv6d4Dvw.js +0 -1
  264. package/dist/gateway/static/root/assets/cron-page-Apk-7p4p.js +0 -1
  265. package/dist/gateway/static/root/assets/dist-DmGDgpy2.js +0 -1
  266. package/dist/gateway/static/root/assets/extension-debug-page-pxFC-tUa.js +0 -1
  267. package/dist/gateway/static/root/assets/extension-settings-page-COXSv6xP.js +0 -1
  268. package/dist/gateway/static/root/assets/fetch-CFdKBnE6.js +0 -1
  269. package/dist/gateway/static/root/assets/gateway-startup-retry-DdngdObI.js +0 -1
  270. package/dist/gateway/static/root/assets/heartbeat-config-api-DcmAMYmN.js +0 -1
  271. package/dist/gateway/static/root/assets/index-C_2yKRJX.js +0 -4845
  272. package/dist/gateway/static/root/assets/index-DI5_GsZt.css +0 -1
  273. package/dist/gateway/static/root/assets/logs-page-DvTWUOzd.js +0 -2
  274. package/dist/gateway/static/root/assets/note-detail-page-CZbdugWZ.js +0 -180
  275. package/dist/gateway/static/root/assets/note-time-RdyBZxj3.js +0 -1
  276. package/dist/gateway/static/root/assets/notes-page-mEAwy3e1.js +0 -1
  277. package/dist/gateway/static/root/assets/schema-form-DEvdni_r.js +0 -1
  278. package/dist/gateway/static/root/assets/sessions-page-BsgffzV4.js +0 -1
  279. package/dist/gateway/static/root/assets/settings-advanced-gate-t6v8Dwb8.js +0 -2
  280. package/dist/gateway/static/root/assets/settings-form-section-BoYYZmJG.js +0 -1
  281. package/dist/gateway/static/root/assets/settings-page-ClIthYF8.js +0 -3
  282. package/dist/gateway/static/root/assets/share-preview-page-Dd9et7KD.js +0 -2
  283. package/dist/gateway/static/root/assets/skills-page-DEXtxyfQ.js +0 -2
  284. package/dist/gateway/static/root/assets/theme-store-BZozwAeK.js +0 -1
  285. package/dist/gateway/static/root/assets/url-DQRqHuL-.js +0 -3
  286. package/dist/gateway/static/root/assets/vendor-codemirror-DYoKfS8f.js +0 -45
  287. package/dist/gateway/static/root/assets/voice-api-key-field-CNrKzQrf.js +0 -1
  288. package/dist/gateway/static/root/assets/workflows-page-EMZkzJNN.js +0 -18
  289. package/dist/src/agent/goals/checklist-user.d.ts +0 -24
  290. package/dist/src/agent/goals/checklist-user.js +0 -92
  291. package/dist/src/agent/goals/checklist-user.js.map +0 -1
  292. package/dist/src/agent/goals/goal-run-store.d.ts +0 -19
  293. package/dist/src/agent/goals/goal-run-store.js +0 -138
  294. package/dist/src/agent/goals/goal-run-store.js.map +0 -1
  295. package/dist/src/agent/goals/goal-run-types.d.ts +0 -28
  296. package/dist/src/agent/goals/goal-run-types.js +0 -6
  297. package/dist/src/agent/goals/goal-run-types.js.map +0 -1
  298. package/dist/src/agent/goals/patch-from-user-action.d.ts +0 -20
  299. package/dist/src/agent/goals/patch-from-user-action.js +0 -103
  300. package/dist/src/agent/goals/patch-from-user-action.js.map +0 -1
  301. /package/dist/gateway/static/root/assets/{note-detail-page-D4ZIVQbk.css → block-editor-D4ZIVQbk.css} +0 -0
@@ -15,7 +15,37 @@ const GoalsConfigPatchSchema = z.object({
15
15
  checklistMode: z.boolean().optional(),
16
16
  maxConsecutiveParseFailures: z.number().int().min(1).max(20).optional(),
17
17
  judgeTimeoutMs: z.number().int().min(5e3).max(12e4).optional(),
18
- checklistHistoryChars: z.number().int().min(0).max(1e5).optional()
18
+ checklistHistoryChars: z.number().int().min(0).max(1e5).optional(),
19
+ notifications: z.object({
20
+ enabled: z.boolean().optional(),
21
+ includeLinkedSessions: z.boolean().optional(),
22
+ channels: z.array(z.string().min(1)).optional(),
23
+ events: z.array(z.enum([
24
+ "done",
25
+ "blocked",
26
+ "needs_input",
27
+ "queue_failed",
28
+ "queue_retry",
29
+ "queue_succeeded",
30
+ "queue_skipped"
31
+ ])).optional(),
32
+ targets: z.array(z.object({
33
+ channel: z.string().min(1),
34
+ chatId: z.string().min(1),
35
+ accountId: z.string().optional(),
36
+ threadId: z.union([z.string(), z.number()]).optional(),
37
+ silent: z.boolean().optional(),
38
+ events: z.array(z.enum([
39
+ "done",
40
+ "blocked",
41
+ "needs_input",
42
+ "queue_failed",
43
+ "queue_retry",
44
+ "queue_succeeded",
45
+ "queue_skipped"
46
+ ])).optional()
47
+ })).optional()
48
+ }).optional()
19
49
  });
20
50
  const SessionStoragePatchSchema = z.object({
21
51
  pruneAfterMs: z.union([z.number().int().min(0), z.null()]).optional(),
@@ -62,14 +92,23 @@ function mergeGoalsConfigPatch(config, patch) {
62
92
  ok: false,
63
93
  message: parsed.error.issues.map((i) => i.message).join("; ")
64
94
  };
65
- config.goals = {
66
- ...config.goals ?? GoalsConfigSchema.parse({}),
67
- ...parsed.data
68
- };
95
+ const currentGoals = GoalsConfigSchema.parse(config.goals ?? {});
96
+ const goalPatch = { ...parsed.data };
69
97
  if ("judgeModelRef" in patch) {
70
98
  const ref = patch.judgeModelRef;
71
- if (ref === null || typeof ref === "string" && !ref.trim()) delete config.goals?.judgeModelRef;
99
+ if (ref === null || typeof ref === "string" && !ref.trim()) {
100
+ delete goalPatch.judgeModelRef;
101
+ delete currentGoals.judgeModelRef;
102
+ }
72
103
  }
104
+ config.goals = GoalsConfigSchema.parse({
105
+ ...currentGoals,
106
+ ...goalPatch,
107
+ notifications: goalPatch.notifications ? {
108
+ ...currentGoals.notifications,
109
+ ...goalPatch.notifications
110
+ } : currentGoals.notifications
111
+ });
73
112
  return { ok: true };
74
113
  }
75
114
  function mergeSessionConfigPatch(config, patch) {
@@ -1 +1 @@
1
- {"version":3,"file":"web-patch.js","names":[],"sources":["../../../src/config/web-patch.ts"],"sourcesContent":["import { z } from 'zod';\n\nimport type { Config } from './schema.js';\nimport {\n CronConfigSchema,\n GoalsConfigSchema,\n SessionConfigSchema,\n SessionDmScopeSchema,\n UpdateAutoConfigSchema,\n UpdateConfigSchema,\n} from './schema.js';\n\nconst CronConfigPatchSchema = z.object({\n enabled: z.boolean().optional(),\n maxConcurrentJobs: z.number().int().min(1).max(100).optional(),\n defaultTimezone: z.string().min(1).optional(),\n historyRetentionDays: z.number().int().min(1).max(365).optional(),\n enableMetrics: z.boolean().optional(),\n});\n\nconst GoalsConfigPatchSchema = z.object({\n maxTurns: z.number().int().min(1).max(500).optional(),\n judgeModelRef: z.union([z.string(), z.null()]).optional(),\n checklistMode: z.boolean().optional(),\n maxConsecutiveParseFailures: z.number().int().min(1).max(20).optional(),\n judgeTimeoutMs: z.number().int().min(5_000).max(120_000).optional(),\n checklistHistoryChars: z.number().int().min(0).max(100_000).optional(),\n});\n\nconst SessionStoragePatchSchema = z.object({\n pruneAfterMs: z.union([z.number().int().min(0), z.null()]).optional(),\n maxEntries: z.union([z.number().int().min(1), z.null()]).optional(),\n});\n\nconst SessionConfigPatchSchema = z.object({\n dmScope: SessionDmScopeSchema.optional(),\n storage: SessionStoragePatchSchema.optional(),\n});\n\nconst UpdateAutoPatchSchema = z.object({\n enabled: z.boolean().optional(),\n stableDelayHours: z.number().min(0).optional(),\n stableJitterHours: z.number().min(0).optional(),\n betaCheckIntervalHours: z.number().min(0.25).optional(),\n});\n\nconst UpdateConfigPatchSchema = z.object({\n checkOnStart: z.boolean().optional(),\n channel: z.enum(['stable', 'beta', 'dev']).optional(),\n auto: UpdateAutoPatchSchema.optional(),\n});\n\nconst GatewaySkillsPatchSchema = z.object({\n skillsMarketplaceProvider: z.string().min(1).optional(),\n skillsStoreBaseUrl: z.string().url().optional(),\n});\n\nexport function mergeCronConfigPatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = CronConfigPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n config.cron = {\n ...(config.cron ?? CronConfigSchema.parse({})),\n ...parsed.data,\n };\n return { ok: true };\n}\n\nexport function mergeGoalsConfigPatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = GoalsConfigPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n config.goals = {\n ...(config.goals ?? GoalsConfigSchema.parse({})),\n ...parsed.data,\n };\n if ('judgeModelRef' in patch) {\n const ref = patch.judgeModelRef;\n if (ref === null || (typeof ref === 'string' && !ref.trim())) {\n delete config.goals?.judgeModelRef;\n }\n }\n return { ok: true };\n}\n\nexport function mergeSessionConfigPatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = SessionConfigPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n const current = config.session ?? SessionConfigSchema.parse({});\n const next = { ...current, ...parsed.data };\n if (parsed.data.storage !== undefined) {\n const storagePatch = parsed.data.storage;\n const nextStorage = { ...(current.storage ?? {}) };\n if ('pruneAfterMs' in storagePatch) {\n if (storagePatch.pruneAfterMs === null) delete nextStorage.pruneAfterMs;\n else if (storagePatch.pruneAfterMs !== undefined) nextStorage.pruneAfterMs = storagePatch.pruneAfterMs;\n }\n if ('maxEntries' in storagePatch) {\n if (storagePatch.maxEntries === null) delete nextStorage.maxEntries;\n else if (storagePatch.maxEntries !== undefined) nextStorage.maxEntries = storagePatch.maxEntries;\n }\n if (Object.keys(nextStorage).length === 0) delete next.storage;\n else next.storage = nextStorage;\n }\n config.session = next;\n return { ok: true };\n}\n\nexport function mergeUpdateConfigPatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = UpdateConfigPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n const current = config.update ?? { checkOnStart: true, channel: 'stable' as const };\n const merged = {\n ...current,\n ...parsed.data,\n ...(parsed.data.auto !== undefined\n ? { auto: { ...(current.auto ?? {}), ...parsed.data.auto } }\n : {}),\n };\n config.update = UpdateConfigSchema.parse(merged);\n return { ok: true };\n}\n\nexport function mergeGatewaySkillsMarketplacePatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = GatewaySkillsPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: 18790,\n auth: { mode: 'token' },\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n }\n if (parsed.data.skillsMarketplaceProvider !== undefined) {\n config.gateway.skillsMarketplaceProvider = parsed.data.skillsMarketplaceProvider.trim();\n }\n if (parsed.data.skillsStoreBaseUrl !== undefined) {\n config.gateway.skillsStoreBaseUrl = parsed.data.skillsStoreBaseUrl.trim().replace(/\\/+$/, '');\n }\n return { ok: true };\n}\n\nexport function resolveGoalsConfigForWeb(config: Config) {\n return GoalsConfigSchema.parse(config.goals ?? {});\n}\n\nexport function resolveSessionConfigForWeb(config: Config) {\n const session = SessionConfigSchema.parse(config.session ?? {});\n return {\n dmScope: session.dmScope,\n storage: {\n pruneAfterDays:\n typeof session.storage?.pruneAfterMs === 'number'\n ? Math.max(0, Math.round(session.storage.pruneAfterMs / 86_400_000))\n : null,\n maxEntries: session.storage?.maxEntries ?? null,\n },\n };\n}\n\nexport function resolveUpdateConfigForWeb(config: Config) {\n const update = config.update ?? { checkOnStart: true, channel: 'stable' as const };\n const auto = UpdateAutoConfigSchema.parse(update.auto ?? {});\n return {\n checkOnStart: update.checkOnStart !== false,\n channel: update.channel ?? 'stable',\n auto: {\n enabled: auto?.enabled === true,\n stableDelayHours: auto?.stableDelayHours ?? 6,\n stableJitterHours: auto?.stableJitterHours ?? 12,\n betaCheckIntervalHours: auto?.betaCheckIntervalHours ?? 1,\n },\n };\n}\n\nexport function resolveCronConfigForWeb(config: Config) {\n const cron = CronConfigSchema.parse(config.cron ?? {});\n return {\n enabled: cron.enabled !== false,\n maxConcurrentJobs: cron.maxConcurrentJobs ?? 5,\n defaultTimezone: cron.defaultTimezone ?? 'UTC',\n historyRetentionDays: cron.historyRetentionDays ?? 7,\n enableMetrics: cron.enableMetrics !== false,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"web-patch.js","names":[],"sources":["../../../src/config/web-patch.ts"],"sourcesContent":["import { z } from 'zod';\n\nimport type { Config } from './schema.js';\nimport {\n CronConfigSchema,\n GoalsConfigSchema,\n SessionConfigSchema,\n SessionDmScopeSchema,\n UpdateAutoConfigSchema,\n UpdateConfigSchema,\n} from './schema.js';\n\nconst CronConfigPatchSchema = z.object({\n enabled: z.boolean().optional(),\n maxConcurrentJobs: z.number().int().min(1).max(100).optional(),\n defaultTimezone: z.string().min(1).optional(),\n historyRetentionDays: z.number().int().min(1).max(365).optional(),\n enableMetrics: z.boolean().optional(),\n});\n\nconst GoalsConfigPatchSchema = z.object({\n maxTurns: z.number().int().min(1).max(500).optional(),\n judgeModelRef: z.union([z.string(), z.null()]).optional(),\n checklistMode: z.boolean().optional(),\n maxConsecutiveParseFailures: z.number().int().min(1).max(20).optional(),\n judgeTimeoutMs: z.number().int().min(5_000).max(120_000).optional(),\n checklistHistoryChars: z.number().int().min(0).max(100_000).optional(),\n notifications: z\n .object({\n enabled: z.boolean().optional(),\n includeLinkedSessions: z.boolean().optional(),\n channels: z.array(z.string().min(1)).optional(),\n events: z\n .array(z.enum([\n 'done',\n 'blocked',\n 'needs_input',\n 'queue_failed',\n 'queue_retry',\n 'queue_succeeded',\n 'queue_skipped',\n ]))\n .optional(),\n targets: z\n .array(z.object({\n channel: z.string().min(1),\n chatId: z.string().min(1),\n accountId: z.string().optional(),\n threadId: z.union([z.string(), z.number()]).optional(),\n silent: z.boolean().optional(),\n events: z\n .array(z.enum([\n 'done',\n 'blocked',\n 'needs_input',\n 'queue_failed',\n 'queue_retry',\n 'queue_succeeded',\n 'queue_skipped',\n ]))\n .optional(),\n }))\n .optional(),\n })\n .optional(),\n});\n\nconst SessionStoragePatchSchema = z.object({\n pruneAfterMs: z.union([z.number().int().min(0), z.null()]).optional(),\n maxEntries: z.union([z.number().int().min(1), z.null()]).optional(),\n});\n\nconst SessionConfigPatchSchema = z.object({\n dmScope: SessionDmScopeSchema.optional(),\n storage: SessionStoragePatchSchema.optional(),\n});\n\nconst UpdateAutoPatchSchema = z.object({\n enabled: z.boolean().optional(),\n stableDelayHours: z.number().min(0).optional(),\n stableJitterHours: z.number().min(0).optional(),\n betaCheckIntervalHours: z.number().min(0.25).optional(),\n});\n\nconst UpdateConfigPatchSchema = z.object({\n checkOnStart: z.boolean().optional(),\n channel: z.enum(['stable', 'beta', 'dev']).optional(),\n auto: UpdateAutoPatchSchema.optional(),\n});\n\nconst GatewaySkillsPatchSchema = z.object({\n skillsMarketplaceProvider: z.string().min(1).optional(),\n skillsStoreBaseUrl: z.string().url().optional(),\n});\n\nexport function mergeCronConfigPatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = CronConfigPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n config.cron = {\n ...(config.cron ?? CronConfigSchema.parse({})),\n ...parsed.data,\n };\n return { ok: true };\n}\n\nexport function mergeGoalsConfigPatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = GoalsConfigPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n const currentGoals = GoalsConfigSchema.parse(config.goals ?? {});\n const goalPatch = { ...parsed.data };\n if ('judgeModelRef' in patch) {\n const ref = patch.judgeModelRef;\n if (ref === null || (typeof ref === 'string' && !ref.trim())) {\n delete goalPatch.judgeModelRef;\n delete currentGoals.judgeModelRef;\n }\n }\n config.goals = GoalsConfigSchema.parse({\n ...currentGoals,\n ...goalPatch,\n notifications: goalPatch.notifications\n ? {\n ...currentGoals.notifications,\n ...goalPatch.notifications,\n }\n : currentGoals.notifications,\n });\n return { ok: true };\n}\n\nexport function mergeSessionConfigPatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = SessionConfigPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n const current = config.session ?? SessionConfigSchema.parse({});\n const next = { ...current, ...parsed.data };\n if (parsed.data.storage !== undefined) {\n const storagePatch = parsed.data.storage;\n const nextStorage = { ...(current.storage ?? {}) };\n if ('pruneAfterMs' in storagePatch) {\n if (storagePatch.pruneAfterMs === null) delete nextStorage.pruneAfterMs;\n else if (storagePatch.pruneAfterMs !== undefined) nextStorage.pruneAfterMs = storagePatch.pruneAfterMs;\n }\n if ('maxEntries' in storagePatch) {\n if (storagePatch.maxEntries === null) delete nextStorage.maxEntries;\n else if (storagePatch.maxEntries !== undefined) nextStorage.maxEntries = storagePatch.maxEntries;\n }\n if (Object.keys(nextStorage).length === 0) delete next.storage;\n else next.storage = nextStorage;\n }\n config.session = next;\n return { ok: true };\n}\n\nexport function mergeUpdateConfigPatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = UpdateConfigPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n const current = config.update ?? { checkOnStart: true, channel: 'stable' as const };\n const merged = {\n ...current,\n ...parsed.data,\n ...(parsed.data.auto !== undefined\n ? { auto: { ...(current.auto ?? {}), ...parsed.data.auto } }\n : {}),\n };\n config.update = UpdateConfigSchema.parse(merged);\n return { ok: true };\n}\n\nexport function mergeGatewaySkillsMarketplacePatch(\n config: Config,\n patch: Record<string, unknown>,\n): { ok: true } | { ok: false; message: string } {\n const parsed = GatewaySkillsPatchSchema.safeParse(patch);\n if (!parsed.success) {\n return { ok: false, message: parsed.error.issues.map((i) => i.message).join('; ') };\n }\n if (!config.gateway) {\n config.gateway = {\n bind: 'loopback',\n port: 18790,\n auth: { mode: 'token' },\n heartbeat: { enabled: true, intervalMs: 1_800_000, includeSystemPromptSection: false },\n maxSseConnections: 100,\n corsOrigins: [],\n };\n }\n if (parsed.data.skillsMarketplaceProvider !== undefined) {\n config.gateway.skillsMarketplaceProvider = parsed.data.skillsMarketplaceProvider.trim();\n }\n if (parsed.data.skillsStoreBaseUrl !== undefined) {\n config.gateway.skillsStoreBaseUrl = parsed.data.skillsStoreBaseUrl.trim().replace(/\\/+$/, '');\n }\n return { ok: true };\n}\n\nexport function resolveGoalsConfigForWeb(config: Config) {\n return GoalsConfigSchema.parse(config.goals ?? {});\n}\n\nexport function resolveSessionConfigForWeb(config: Config) {\n const session = SessionConfigSchema.parse(config.session ?? {});\n return {\n dmScope: session.dmScope,\n storage: {\n pruneAfterDays:\n typeof session.storage?.pruneAfterMs === 'number'\n ? Math.max(0, Math.round(session.storage.pruneAfterMs / 86_400_000))\n : null,\n maxEntries: session.storage?.maxEntries ?? null,\n },\n };\n}\n\nexport function resolveUpdateConfigForWeb(config: Config) {\n const update = config.update ?? { checkOnStart: true, channel: 'stable' as const };\n const auto = UpdateAutoConfigSchema.parse(update.auto ?? {});\n return {\n checkOnStart: update.checkOnStart !== false,\n channel: update.channel ?? 'stable',\n auto: {\n enabled: auto?.enabled === true,\n stableDelayHours: auto?.stableDelayHours ?? 6,\n stableJitterHours: auto?.stableJitterHours ?? 12,\n betaCheckIntervalHours: auto?.betaCheckIntervalHours ?? 1,\n },\n };\n}\n\nexport function resolveCronConfigForWeb(config: Config) {\n const cron = CronConfigSchema.parse(config.cron ?? {});\n return {\n enabled: cron.enabled !== false,\n maxConcurrentJobs: cron.maxConcurrentJobs ?? 5,\n defaultTimezone: cron.defaultTimezone ?? 'UTC',\n historyRetentionDays: cron.historyRetentionDays ?? 7,\n enableMetrics: cron.enableMetrics !== false,\n };\n}\n"],"mappings":"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"}
@@ -10,6 +10,7 @@ export declare class DefaultJobExecutor implements JobExecutor {
10
10
  private runLogStore;
11
11
  private getDefaultCronAgentId;
12
12
  private workflowRunService;
13
+ private goalRunner;
13
14
  setRunLogStore(store: CronRunLogStore | null): void;
14
15
  setDeps(deps: JobExecutorDeps): void;
15
16
  private buildCronOutboundMessage;
@@ -18,6 +19,7 @@ export declare class DefaultJobExecutor implements JobExecutor {
18
19
  * Perform the actual job work - integrate with AgentService
19
20
  */
20
21
  protected performJob(job: JobData, signal: AbortSignal): Promise<CronRunOutcome>;
22
+ private executeGoalContinue;
21
23
  private executeWorkflowRun;
22
24
  private waitForWorkflowRunOutcome;
23
25
  private deliverWorkflowRunOutcome;
@@ -40,6 +40,7 @@ var DefaultJobExecutor = class {
40
40
  runLogStore = null;
41
41
  getDefaultCronAgentId = null;
42
42
  workflowRunService = null;
43
+ goalRunner = null;
43
44
  setRunLogStore(store) {
44
45
  this.runLogStore = store;
45
46
  }
@@ -50,6 +51,7 @@ var DefaultJobExecutor = class {
50
51
  if (deps.sessionStore !== void 0) this.sessionStore = deps.sessionStore;
51
52
  this.getDefaultCronAgentId = deps.getDefaultCronAgentId ?? null;
52
53
  this.workflowRunService = deps.workflowRunService ?? null;
54
+ this.goalRunner = deps.goalRunner ?? null;
53
55
  }
54
56
  async buildCronOutboundMessage(channel, to, content) {
55
57
  const plugin = getChannelPlugin(channel);
@@ -161,6 +163,7 @@ var DefaultJobExecutor = class {
161
163
  error: "Job was aborted before execution"
162
164
  };
163
165
  try {
166
+ if (job.payload.kind === "goalContinue") return await this.executeGoalContinue(job);
164
167
  if (job.payload.kind === "workflowRun") return await this.executeWorkflowRun(job, signal);
165
168
  if (!this.agentService || !this.messageBus) {
166
169
  log.warn({ jobId: job.id }, "No agent service configured, using basic execution");
@@ -175,6 +178,28 @@ var DefaultJobExecutor = class {
175
178
  };
176
179
  }
177
180
  }
181
+ async executeGoalContinue(job) {
182
+ if (job.payload.kind !== "goalContinue") return {
183
+ status: "error",
184
+ error: "Cron job payload is not goalContinue"
185
+ };
186
+ if (!this.goalRunner) return {
187
+ status: "error",
188
+ error: "Goal runner is not configured for cron"
189
+ };
190
+ const item = this.goalRunner.enqueue(job.payload.goalId, {
191
+ message: job.payload.message,
192
+ maxRetries: job.payload.maxRetries ?? job.maxRetries,
193
+ source: "cron"
194
+ });
195
+ return {
196
+ status: "ok",
197
+ summary: `Queued goal ${job.payload.goalId} (${item.status})`,
198
+ sessionId: item.sessionKey,
199
+ sessionKey: item.sessionKey,
200
+ sessionType: "goal"
201
+ };
202
+ }
178
203
  async executeWorkflowRun(job, signal) {
179
204
  if (signal.aborted) return {
180
205
  status: "skipped",
@@ -1 +1 @@
1
- {"version":3,"file":"executor.js","names":[],"sources":["../../../src/cron/executor.ts"],"sourcesContent":["// Cron job executor with timeout, retry logic and agent integration\nimport type { WorkflowRunView } from '../workflows/domain/index.js';\nimport type {\n CronRunOutcome,\n CronWorkflowRunStarter,\n HeartbeatWakeSink,\n JobData,\n JobExecution,\n JobExecutor,\n JobExecutorDeps,\n} from './types.js';\nimport type { OutboundMessage } from '../channels/transport-types.js';\nimport { createLogger } from '../utils/logger.js';\nimport {\n getChannelPlugin,\n listChannelPlugins,\n} from '../channels/plugins/registry.js';\nimport { getCronPayloadText } from './job-content.js';\nimport type { SessionStore } from '../session/store.js';\nimport type { CronRunLogStore } from './run-log-store.js';\nimport {\n DEFAULT_ACK_MAX_CHARS,\n NO_REPLY,\n shouldSilence,\n stripHeartbeatToken,\n} from '../heartbeat/tokens.js';\nimport { DEFAULT_AGENT_ID, normalizeAgentId } from '../agent/agent-scope.js';\nimport { buildSessionKey } from '../routing/session-key.js';\nimport {\n buildWorkflowRunCronSummary,\n buildWorkflowRunDeliveryText,\n isWorkflowRunCronSuccess,\n resolveWorkflowCronWaitMs,\n waitForWorkflowRunView,\n} from './workflow-run-completion.js';\n\nconst log = createLogger('CronExecutor');\n\n// Error backoff schedule in ms\nconst ERROR_BACKOFF_MS = [\n 30_000, // 1st error → 30s\n 60_000, // 2nd error → 1min\n 5 * 60_000, // 3rd error → 5min\n 15 * 60_000, // 4th error → 15min\n 60 * 60_000, // 5th+ error → 60min\n];\n\nfunction errorBackoffMs(consecutiveErrors: number): number {\n const idx = Math.min(consecutiveErrors - 1, ERROR_BACKOFF_MS.length - 1);\n return ERROR_BACKOFF_MS[Math.max(0, idx)];\n}\n\nfunction resolveIsolatedCronJobModel(job: JobData): string | undefined {\n const fromJob = job.model?.trim();\n if (fromJob) return fromJob;\n if (job.payload?.kind === 'agentTurn') {\n const m = job.payload.model?.trim();\n if (m) return m;\n }\n return undefined;\n}\n\nexport class DefaultJobExecutor implements JobExecutor {\n private history: Map<string, JobExecution[]> = new Map();\n private runningJobs = new Map<string, AbortController>();\n private agentService: any = null;\n private messageBus: any = null;\n private heartbeatService: HeartbeatWakeSink | null = null;\n private sessionStore: SessionStore | undefined;\n private runLogStore: CronRunLogStore | null = null;\n private getDefaultCronAgentId: (() => string) | null = null;\n private workflowRunService: CronWorkflowRunStarter | null = null;\n\n setRunLogStore(store: CronRunLogStore | null): void {\n this.runLogStore = store;\n }\n\n setDeps(deps: JobExecutorDeps): void {\n this.agentService = deps.agentService;\n this.messageBus = deps.messageBus;\n this.heartbeatService = deps.heartbeatService ?? null;\n if (deps.sessionStore !== undefined) {\n this.sessionStore = deps.sessionStore;\n }\n this.getDefaultCronAgentId = deps.getDefaultCronAgentId ?? null;\n this.workflowRunService = deps.workflowRunService ?? null;\n }\n\n private async buildCronOutboundMessage(\n channel: string,\n to: string,\n content: string,\n ): Promise<OutboundMessage> {\n const plugin = getChannelPlugin(channel);\n if (plugin?.cronDelivery) {\n const { chatId, accountId, metadata } = await plugin.cronDelivery.normalizeDeliveryTarget(\n to,\n this.sessionStore,\n );\n const meta =\n accountId || metadata\n ? { ...(metadata ?? {}), ...(accountId ? { accountId } : {}) }\n : undefined;\n return {\n channel,\n chat_id: chatId,\n content,\n type: 'message',\n ...(meta && Object.keys(meta).length > 0 ? { metadata: meta } : {}),\n };\n }\n return {\n channel,\n chat_id: to,\n content,\n type: 'message',\n };\n }\n\n async execute(job: JobData, signal: AbortSignal, deps?: JobExecutorDeps): Promise<void> {\n // Set deps if provided\n if (deps) {\n this.setDeps(deps);\n }\n\n const executionId = crypto.randomUUID();\n const execution: JobExecution = {\n id: executionId,\n jobId: job.id,\n status: 'running',\n startedAt: new Date().toISOString(),\n retryCount: 0,\n };\n\n // Record execution start\n this.addToHistory(job.id, execution);\n this.runningJobs.set(job.id, new AbortController());\n\n log.info(\n { jobId: job.id, executionId, preview: getCronPayloadText(job).slice(0, 100) },\n 'Job executing'\n );\n\n let result: CronRunOutcome;\n\n try {\n // Check for cancellation\n if (signal.aborted) {\n throw new Error('Job was cancelled before execution');\n }\n\n // Execute the job\n result = await this.performJob(job, signal);\n\n // Mark as success/failed\n execution.status = result.status === 'ok' ? 'success' : result.status === 'skipped' ? 'cancelled' : 'failed';\n execution.endedAt = new Date().toISOString();\n execution.duration = Date.now() - new Date(execution.startedAt).getTime();\n execution.summary = result.summary;\n execution.error = result.error;\n execution.sessionId = result.sessionId;\n execution.sessionKey = result.sessionKey;\n execution.sessionType = result.sessionType;\n execution.model = result.model;\n execution.workflowRunId = result.workflowRunId;\n\n if (result.status === 'ok') {\n log.info(\n { jobId: job.id, executionId, duration: execution.duration },\n 'Job completed'\n );\n } else if (result.status === 'skipped') {\n log.warn({ jobId: job.id, executionId, reason: result.error }, 'Job skipped');\n } else {\n log.error(\n { jobId: job.id, executionId, errorMessage: result.error, phase: 'cron.execute' },\n `Job failed: ${result.error ?? 'unknown'}`,\n );\n }\n\n if (result.status === 'ok' && this.heartbeatService) {\n try {\n this.heartbeatService.requestNow({ reason: `cron:${job.id}` });\n } catch (e) {\n log.warn({ jobId: job.id, err: e }, 'Heartbeat wake after cron failed');\n }\n }\n } catch (error) {\n execution.status = 'failed';\n execution.endedAt = new Date().toISOString();\n execution.duration = Date.now() - new Date(execution.startedAt).getTime();\n execution.error = error instanceof Error ? error.message : String(error);\n\n log.error(\n {\n err: error,\n errorMessage: execution.error,\n jobId: job.id,\n executionId,\n phase: 'cron.execute',\n },\n `Job execution error: ${execution.error}`,\n );\n\n result = {\n status: 'error',\n error: execution.error,\n };\n } finally {\n this.runningJobs.delete(job.id);\n }\n\n if (this.runLogStore) {\n await this.runLogStore.appendCompleted(execution);\n }\n\n return;\n }\n\n /**\n * Perform the actual job work - integrate with AgentService\n */\n protected async performJob(job: JobData, signal: AbortSignal): Promise<CronRunOutcome> {\n const timeout = job.timeout || 60000;\n const sessionTarget = job.sessionTarget || 'main';\n\n // Check for abort before starting\n if (signal.aborted) {\n return { status: 'skipped', error: 'Job was aborted before execution' };\n }\n\n try {\n if (job.payload.kind === 'workflowRun') {\n return await this.executeWorkflowRun(job, signal);\n }\n\n // If no agent service, fall back to basic execution\n if (!this.agentService || !this.messageBus) {\n log.warn({ jobId: job.id }, 'No agent service configured, using basic execution');\n return this.basicExecute(job, signal, timeout);\n }\n\n if (sessionTarget === 'main') {\n return await this.executeMainSession(job, signal, timeout);\n } else {\n return await this.executeIsolated(job, signal, timeout);\n }\n } catch (error) {\n return {\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n private async executeWorkflowRun(job: JobData, signal: AbortSignal): Promise<CronRunOutcome> {\n if (signal.aborted) {\n return { status: 'skipped', error: 'Job was aborted before workflow run start' };\n }\n\n if (job.payload.kind !== 'workflowRun') {\n return { status: 'error', error: 'Cron job payload is not workflowRun' };\n }\n\n if (!this.workflowRunService) {\n return { status: 'error', error: 'Workflow run service is not configured for cron' };\n }\n\n const fallbackAgentId = this.getDefaultCronAgentId?.() ?? DEFAULT_AGENT_ID;\n const agentId = normalizeAgentId(job.payload.agentId || job.agentId || fallbackAgentId);\n const fireId = job.payload.source?.fireId || crypto.randomUUID();\n const source = {\n kind: 'cron' as const,\n scheduleId: job.payload.source?.scheduleId || job.id,\n fireId,\n scheduledAtMs: job.payload.source?.scheduledAtMs ?? Date.now(),\n };\n const result = await this.workflowRunService.startWorkflowRun({\n agentId,\n definitionId: job.payload.definitionId,\n input: job.payload.input,\n inputEnvelope: job.payload.inputEnvelope,\n goal: job.payload.goal,\n source,\n idempotencyKey: `cron:${job.id}:${fireId}`,\n });\n\n if (result.ok === false) {\n return {\n status: 'error',\n error: result.message,\n };\n }\n\n log.info(\n {\n jobId: job.id,\n workflowRunId: result.runId,\n definitionId: job.payload.definitionId,\n sessionKey: result.sessionKey,\n },\n 'Workflow run started from cron',\n );\n\n const waitForCompletion = job.payload.waitForCompletion !== false;\n if (!waitForCompletion || !this.workflowRunService.readWorkflowRunView) {\n return {\n status: 'ok',\n summary: `Started workflow run ${result.runId}`,\n sessionId: result.sessionKey,\n sessionKey: result.sessionKey,\n sessionType: 'workflow',\n workflowRunId: result.runId,\n };\n }\n\n return this.waitForWorkflowRunOutcome({\n job,\n agentId,\n sessionKey: result.sessionKey,\n initialRunId: result.runId,\n signal,\n });\n }\n\n private async waitForWorkflowRunOutcome(params: {\n job: JobData;\n agentId: string;\n sessionKey: string;\n initialRunId: string;\n signal: AbortSignal;\n }): Promise<CronRunOutcome> {\n const waitMs = resolveWorkflowCronWaitMs(params.job.timeout);\n const maxWorkflowRetries = Math.max(0, params.job.maxRetries ?? 0);\n let runId = params.initialRunId;\n let attempt = 0;\n\n while (attempt <= maxWorkflowRetries) {\n const waitResult = await waitForWorkflowRunView({\n readView: (id) => this.workflowRunService!.readWorkflowRunView!(params.agentId, id),\n runId,\n signal: params.signal,\n timeoutMs: waitMs,\n });\n\n if (waitResult.kind === 'aborted') {\n return { status: 'skipped', error: 'Job was aborted while waiting for workflow run' };\n }\n\n if (waitResult.kind === 'timeout') {\n return {\n status: 'error',\n error: `Workflow run ${runId} did not finish within ${waitMs}ms`,\n summary: waitResult.lastView ? buildWorkflowRunCronSummary(waitResult.lastView) : undefined,\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n }\n\n const view = waitResult.view;\n const summary = buildWorkflowRunCronSummary(view);\n const succeeded = isWorkflowRunCronSuccess(view);\n\n if (succeeded) {\n const baseOutcome: CronRunOutcome = {\n status: 'ok',\n summary,\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n await this.deliverWorkflowRunOutcome(params.job, view, baseOutcome);\n return baseOutcome;\n }\n\n const canRetry =\n attempt < maxWorkflowRetries &&\n view.run.status === 'failed' &&\n Boolean(this.workflowRunService?.retryWorkflowRun);\n\n if (!canRetry) {\n return {\n status: 'error',\n summary,\n error: summary,\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n }\n\n const retryResult = await this.workflowRunService!.retryWorkflowRun!({\n agentId: params.agentId,\n runId,\n });\n if (retryResult.ok === false) {\n return {\n status: 'error',\n error: retryResult.message,\n summary,\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n }\n\n runId = retryResult.runId;\n attempt += 1;\n log.info(\n { jobId: params.job.id, attempt, workflowRunId: runId },\n 'Retrying failed workflow run from cron',\n );\n }\n\n return {\n status: 'error',\n error: 'Workflow run retries exhausted',\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n }\n\n private async deliverWorkflowRunOutcome(\n job: JobData,\n view: WorkflowRunView,\n outcome: CronRunOutcome,\n ): Promise<void> {\n if (!this.messageBus) return;\n const delivery = job.delivery;\n if (!delivery || delivery.mode === 'none' || delivery.channel === 'local' || !delivery.to?.trim()) {\n return;\n }\n\n try {\n const text = buildWorkflowRunDeliveryText(view);\n const outbound = await this.buildCronOutboundMessage(delivery.channel!, delivery.to!, text);\n await this.messageBus.publishOutbound(outbound);\n log.info(\n { jobId: job.id, channel: delivery.channel, to: outbound.chat_id, workflowRunId: view.run.id },\n 'Delivered workflow run result from cron',\n );\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ jobId: job.id, err, workflowRunId: view.run.id }, `Workflow cron delivery failed: ${em}`);\n if (outcome.status === 'ok') {\n outcome.summary = `${outcome.summary ?? ''} (delivery failed: ${em})`.trim();\n }\n }\n }\n\n /**\n * Execute in main session - sends system event\n */\n private async executeMainSession(\n job: JobData,\n signal: AbortSignal,\n timeout: number\n ): Promise<CronRunOutcome> {\n const text = getCronPayloadText(job);\n\n if (!text || !text.trim()) {\n return { status: 'skipped', error: 'Main session job requires non-empty message' };\n }\n\n // Parse delivery from job config, or parse routing from payload text: \"channel:chat_id:content\"\n let channel: string;\n let to: string;\n let actualMessage: string;\n\n if (job.delivery?.channel === 'local') {\n channel = 'local';\n to = '';\n actualMessage = text;\n } else if (job.delivery?.channel && job.delivery?.to) {\n // Use explicit delivery config\n channel = job.delivery.channel;\n to = job.delivery.to;\n actualMessage = text;\n } else {\n // Parse from payload text: \"channel:chat_id:content\"\n const parts = text.split(':');\n const hasAtLeastThreeParts = parts.length >= 3;\n \n // Check if first part looks like a known channel\n const registeredChannelIds = listChannelPlugins().map((p) => p.id);\n const knownChannels = [...new Set([...registeredChannelIds, 'cli', 'gateway', 'local'])];\n const firstPartIsChannel = knownChannels.includes(parts[0]);\n \n if (hasAtLeastThreeParts && firstPartIsChannel) {\n channel = parts[0];\n to = parts[1];\n actualMessage = parts.slice(2).join(':');\n log.info(\n { jobId: job.id, channel, to, parsedFrom: 'message', originalLength: text.length },\n 'Parsed delivery from payload text'\n );\n } else {\n // Fallback to defaults\n channel = 'cli';\n to = 'cron';\n actualMessage = text;\n log.debug(\n { jobId: job.id, partsCount: parts.length, firstPart: parts[0], hasDelivery: !!job.delivery },\n 'Using default delivery - message format not recognized'\n );\n }\n }\n\n // Create timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error(`Job timed out after ${timeout}ms`)), timeout);\n });\n\n // Create execution promise\n const executePromise = (async () => {\n // Check for abort\n if (signal.aborted) {\n throw new Error('Job was aborted');\n }\n\n if (channel === 'local') {\n log.info(\n { jobId: job.id, messageLength: actualMessage.length },\n 'Cron main session: local channel — no outbound publish'\n );\n return {\n status: 'ok' as const,\n summary: actualMessage.slice(0, 200),\n };\n }\n\n const outbound = await this.buildCronOutboundMessage(channel, to, actualMessage);\n\n await this.messageBus.publishOutbound(outbound);\n\n log.info(\n { jobId: job.id, channel, to: outbound.chat_id, messageLength: actualMessage.length },\n 'Sent message to main session'\n );\n\n return {\n status: 'ok' as const,\n summary: actualMessage.slice(0, 200),\n };\n })();\n\n // Race against timeout\n return await Promise.race([executePromise, timeoutPromise]);\n }\n\n /**\n * Execute in isolated mode - runs agent independently\n */\n private async executeIsolated(\n job: JobData,\n signal: AbortSignal,\n timeout: number\n ): Promise<CronRunOutcome> {\n const message = getCronPayloadText(job);\n\n if (!message || !message.trim()) {\n return { status: 'skipped', error: 'Isolated job requires non-empty message' };\n }\n\n const aid = job.agentId?.trim();\n const fallbackAgentId = this.getDefaultCronAgentId?.() ?? DEFAULT_AGENT_ID;\n const sessionKey = buildSessionKey({\n agentId: normalizeAgentId(aid || fallbackAgentId),\n source: 'cron',\n accountId: 'default',\n peerKind: 'dm',\n peerId: job.id,\n });\n\n // Create timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error(`Job timed out after ${timeout}ms`)), timeout);\n });\n\n // Create execution promise\n const executePromise = (async () => {\n // Check for abort\n if (signal.aborted) {\n throw new Error('Job was aborted');\n }\n\n await this.agentService.sessionConfig.applyCronJobWorkingDirectory(sessionKey, job.workingDirectory);\n\n const jobModel = resolveIsolatedCronJobModel(job);\n if (jobModel) {\n const ok = await this.agentService.switchModelForSession(sessionKey, jobModel);\n if (!ok) {\n log.warn({ jobId: job.id, sessionKey, model: jobModel }, 'Cron job model invalid; using agent default');\n await this.agentService.resetSessionModelToAgentDefault(sessionKey);\n }\n } else {\n await this.agentService.resetSessionModelToAgentDefault(sessionKey);\n }\n\n const response = await this.agentService.turnDispatcher.processDirect(message, sessionKey);\n\n const model = this.agentService.getModelForSession(sessionKey);\n\n log.info(\n { jobId: job.id, sessionKey, responseLength: response.length, model },\n 'Agent execution completed'\n );\n\n // Handle delivery (`local` channel or `mode: none` = no outbound; transcript in SessionStore)\n const delivery = job.delivery;\n const outboundChannel = delivery?.channel;\n const shouldPublish =\n delivery &&\n delivery.mode !== 'none' &&\n outboundChannel !== 'local' &&\n delivery.to;\n\n if (shouldPublish) {\n if (shouldSilence(response, DEFAULT_ACK_MAX_CHARS) || response.trim() === NO_REPLY) {\n return {\n status: 'ok' as const,\n summary: response.slice(0, 200),\n sessionId: sessionKey,\n sessionKey,\n sessionType: 'cron',\n model,\n };\n }\n const { stripped } = stripHeartbeatToken(response);\n const outboundText = stripped || response.trim();\n\n const targetChannel = outboundChannel || 'cli';\n const outbound = await this.buildCronOutboundMessage(targetChannel, delivery.to, outboundText);\n\n await this.messageBus.publishOutbound(outbound);\n\n log.info(\n { jobId: job.id, channel: targetChannel, to: outbound.chat_id },\n 'Delivered agent response'\n );\n\n return {\n status: 'ok' as const,\n summary: response.slice(0, 200),\n sessionId: sessionKey,\n sessionKey,\n sessionType: 'cron',\n model,\n };\n }\n\n // No outbound delivery: transcript is in SessionStore under `sessionKey`.\n return {\n status: 'ok' as const,\n summary: response.slice(0, 200),\n sessionId: sessionKey,\n sessionKey,\n sessionType: 'cron',\n model,\n };\n })();\n\n // Race against timeout\n try {\n return await Promise.race([executePromise, timeoutPromise]);\n } finally {\n const { retireSessionMcpRuntimeForSessionKey } = await import('../agent/mcp/bundle-mcp-tools.js');\n await retireSessionMcpRuntimeForSessionKey({\n sessionKey,\n reason: 'cron-isolated-end',\n }).catch(() => {});\n }\n }\n\n /**\n * Basic execution without agent service (fallback)\n */\n private async basicExecute(\n job: JobData,\n signal: AbortSignal,\n timeout: number\n ): Promise<CronRunOutcome> {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error(`Job timed out after ${timeout}ms`));\n }, timeout);\n\n // Listen for abort signal\n const abortHandler = () => {\n clearTimeout(timeoutId);\n reject(new Error('Job was aborted'));\n };\n signal.addEventListener('abort', abortHandler);\n\n // Simulate basic work\n setTimeout(() => {\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', abortHandler);\n\n if (signal.aborted) {\n reject(new Error('Job was aborted'));\n } else {\n resolve({\n status: 'ok',\n summary: `Executed: ${getCronPayloadText(job).slice(0, 100)}`,\n });\n }\n }, 100);\n });\n }\n\n /**\n * Cancel a running job\n */\n cancelJob(jobId: string): boolean {\n const controller = this.runningJobs.get(jobId);\n if (controller) {\n controller.abort();\n this.runningJobs.delete(jobId);\n return true;\n }\n return false;\n }\n\n /**\n * Get execution history for a job\n */\n getHistory(jobId: string, limit = 10): JobExecution[] {\n const history = this.history.get(jobId) || [];\n return history.slice(-limit);\n }\n\n /**\n * Get currently running executions\n */\n getRunningExecutions(): JobExecution[] {\n const result: JobExecution[] = [];\n for (const [jobId] of this.runningJobs) {\n const history = this.history.get(jobId);\n if (history) {\n const running = history.find((e) => e.status === 'running');\n if (running) result.push(running);\n }\n }\n return result;\n }\n\n /**\n * Check if a job is currently running\n */\n isRunning(jobId: string): boolean {\n return this.runningJobs.has(jobId);\n }\n\n /**\n * Get consecutive error count for a job\n */\n getConsecutiveErrors(jobId: string): number {\n const history = this.history.get(jobId) || [];\n // Find last execution\n for (let i = history.length - 1; i >= 0; i--) {\n if (history[i].status !== 'running') {\n if (history[i].status === 'failed' || history[i].status === 'cancelled') {\n // Count consecutive errors before this\n let count = 0;\n for (let j = i - 1; j >= 0; j--) {\n if (history[j].status === 'failed' || history[j].status === 'cancelled') {\n count++;\n } else {\n break;\n }\n }\n return count + 1;\n }\n return 0;\n }\n }\n return 0;\n }\n\n /**\n * Calculate backoff delay for a job\n */\n calculateBackoff(jobId: string): number {\n const errors = this.getConsecutiveErrors(jobId);\n return errorBackoffMs(errors);\n }\n\n /**\n * Clear old history entries\n */\n cleanupHistory(maxAgeDays = 7): void {\n const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;\n\n for (const [jobId, executions] of this.history) {\n this.history.set(\n jobId,\n executions.filter((e) => new Date(e.startedAt).getTime() > cutoff)\n );\n }\n }\n\n private addToHistory(jobId: string, execution: JobExecution): void {\n const existing = this.history.get(jobId) || [];\n existing.push(execution);\n // Keep last 100 executions per job\n if (existing.length > 100) {\n existing.shift();\n }\n this.history.set(jobId, existing);\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"executor.js","names":[],"sources":["../../../src/cron/executor.ts"],"sourcesContent":["// Cron job executor with timeout, retry logic and agent integration\nimport type { WorkflowRunView } from '../workflows/domain/index.js';\nimport type {\n CronRunOutcome,\n CronWorkflowRunStarter,\n HeartbeatWakeSink,\n JobData,\n JobExecution,\n JobExecutor,\n JobExecutorDeps,\n} from './types.js';\nimport type { OutboundMessage } from '../channels/transport-types.js';\nimport { createLogger } from '../utils/logger.js';\nimport {\n getChannelPlugin,\n listChannelPlugins,\n} from '../channels/plugins/registry.js';\nimport { getCronPayloadText } from './job-content.js';\nimport type { SessionStore } from '../session/store.js';\nimport type { CronRunLogStore } from './run-log-store.js';\nimport {\n DEFAULT_ACK_MAX_CHARS,\n NO_REPLY,\n shouldSilence,\n stripHeartbeatToken,\n} from '../heartbeat/tokens.js';\nimport { DEFAULT_AGENT_ID, normalizeAgentId } from '../agent/agent-scope.js';\nimport { buildSessionKey } from '../routing/session-key.js';\nimport {\n buildWorkflowRunCronSummary,\n buildWorkflowRunDeliveryText,\n isWorkflowRunCronSuccess,\n resolveWorkflowCronWaitMs,\n waitForWorkflowRunView,\n} from './workflow-run-completion.js';\n\nconst log = createLogger('CronExecutor');\n\n// Error backoff schedule in ms\nconst ERROR_BACKOFF_MS = [\n 30_000, // 1st error → 30s\n 60_000, // 2nd error → 1min\n 5 * 60_000, // 3rd error → 5min\n 15 * 60_000, // 4th error → 15min\n 60 * 60_000, // 5th+ error → 60min\n];\n\nfunction errorBackoffMs(consecutiveErrors: number): number {\n const idx = Math.min(consecutiveErrors - 1, ERROR_BACKOFF_MS.length - 1);\n return ERROR_BACKOFF_MS[Math.max(0, idx)];\n}\n\nfunction resolveIsolatedCronJobModel(job: JobData): string | undefined {\n const fromJob = job.model?.trim();\n if (fromJob) return fromJob;\n if (job.payload?.kind === 'agentTurn') {\n const m = job.payload.model?.trim();\n if (m) return m;\n }\n return undefined;\n}\n\nexport class DefaultJobExecutor implements JobExecutor {\n private history: Map<string, JobExecution[]> = new Map();\n private runningJobs = new Map<string, AbortController>();\n private agentService: any = null;\n private messageBus: any = null;\n private heartbeatService: HeartbeatWakeSink | null = null;\n private sessionStore: SessionStore | undefined;\n private runLogStore: CronRunLogStore | null = null;\n private getDefaultCronAgentId: (() => string) | null = null;\n private workflowRunService: CronWorkflowRunStarter | null = null;\n private goalRunner: JobExecutorDeps['goalRunner'] | null = null;\n\n setRunLogStore(store: CronRunLogStore | null): void {\n this.runLogStore = store;\n }\n\n setDeps(deps: JobExecutorDeps): void {\n this.agentService = deps.agentService;\n this.messageBus = deps.messageBus;\n this.heartbeatService = deps.heartbeatService ?? null;\n if (deps.sessionStore !== undefined) {\n this.sessionStore = deps.sessionStore;\n }\n this.getDefaultCronAgentId = deps.getDefaultCronAgentId ?? null;\n this.workflowRunService = deps.workflowRunService ?? null;\n this.goalRunner = deps.goalRunner ?? null;\n }\n\n private async buildCronOutboundMessage(\n channel: string,\n to: string,\n content: string,\n ): Promise<OutboundMessage> {\n const plugin = getChannelPlugin(channel);\n if (plugin?.cronDelivery) {\n const { chatId, accountId, metadata } = await plugin.cronDelivery.normalizeDeliveryTarget(\n to,\n this.sessionStore,\n );\n const meta =\n accountId || metadata\n ? { ...(metadata ?? {}), ...(accountId ? { accountId } : {}) }\n : undefined;\n return {\n channel,\n chat_id: chatId,\n content,\n type: 'message',\n ...(meta && Object.keys(meta).length > 0 ? { metadata: meta } : {}),\n };\n }\n return {\n channel,\n chat_id: to,\n content,\n type: 'message',\n };\n }\n\n async execute(job: JobData, signal: AbortSignal, deps?: JobExecutorDeps): Promise<void> {\n // Set deps if provided\n if (deps) {\n this.setDeps(deps);\n }\n\n const executionId = crypto.randomUUID();\n const execution: JobExecution = {\n id: executionId,\n jobId: job.id,\n status: 'running',\n startedAt: new Date().toISOString(),\n retryCount: 0,\n };\n\n // Record execution start\n this.addToHistory(job.id, execution);\n this.runningJobs.set(job.id, new AbortController());\n\n log.info(\n { jobId: job.id, executionId, preview: getCronPayloadText(job).slice(0, 100) },\n 'Job executing'\n );\n\n let result: CronRunOutcome;\n\n try {\n // Check for cancellation\n if (signal.aborted) {\n throw new Error('Job was cancelled before execution');\n }\n\n // Execute the job\n result = await this.performJob(job, signal);\n\n // Mark as success/failed\n execution.status = result.status === 'ok' ? 'success' : result.status === 'skipped' ? 'cancelled' : 'failed';\n execution.endedAt = new Date().toISOString();\n execution.duration = Date.now() - new Date(execution.startedAt).getTime();\n execution.summary = result.summary;\n execution.error = result.error;\n execution.sessionId = result.sessionId;\n execution.sessionKey = result.sessionKey;\n execution.sessionType = result.sessionType;\n execution.model = result.model;\n execution.workflowRunId = result.workflowRunId;\n\n if (result.status === 'ok') {\n log.info(\n { jobId: job.id, executionId, duration: execution.duration },\n 'Job completed'\n );\n } else if (result.status === 'skipped') {\n log.warn({ jobId: job.id, executionId, reason: result.error }, 'Job skipped');\n } else {\n log.error(\n { jobId: job.id, executionId, errorMessage: result.error, phase: 'cron.execute' },\n `Job failed: ${result.error ?? 'unknown'}`,\n );\n }\n\n if (result.status === 'ok' && this.heartbeatService) {\n try {\n this.heartbeatService.requestNow({ reason: `cron:${job.id}` });\n } catch (e) {\n log.warn({ jobId: job.id, err: e }, 'Heartbeat wake after cron failed');\n }\n }\n } catch (error) {\n execution.status = 'failed';\n execution.endedAt = new Date().toISOString();\n execution.duration = Date.now() - new Date(execution.startedAt).getTime();\n execution.error = error instanceof Error ? error.message : String(error);\n\n log.error(\n {\n err: error,\n errorMessage: execution.error,\n jobId: job.id,\n executionId,\n phase: 'cron.execute',\n },\n `Job execution error: ${execution.error}`,\n );\n\n result = {\n status: 'error',\n error: execution.error,\n };\n } finally {\n this.runningJobs.delete(job.id);\n }\n\n if (this.runLogStore) {\n await this.runLogStore.appendCompleted(execution);\n }\n\n return;\n }\n\n /**\n * Perform the actual job work - integrate with AgentService\n */\n protected async performJob(job: JobData, signal: AbortSignal): Promise<CronRunOutcome> {\n const timeout = job.timeout || 60000;\n const sessionTarget = job.sessionTarget || 'main';\n\n // Check for abort before starting\n if (signal.aborted) {\n return { status: 'skipped', error: 'Job was aborted before execution' };\n }\n\n try {\n if (job.payload.kind === 'goalContinue') {\n return await this.executeGoalContinue(job);\n }\n\n if (job.payload.kind === 'workflowRun') {\n return await this.executeWorkflowRun(job, signal);\n }\n\n // If no agent service, fall back to basic execution\n if (!this.agentService || !this.messageBus) {\n log.warn({ jobId: job.id }, 'No agent service configured, using basic execution');\n return this.basicExecute(job, signal, timeout);\n }\n\n if (sessionTarget === 'main') {\n return await this.executeMainSession(job, signal, timeout);\n } else {\n return await this.executeIsolated(job, signal, timeout);\n }\n } catch (error) {\n return {\n status: 'error',\n error: error instanceof Error ? error.message : String(error),\n };\n }\n }\n\n private async executeGoalContinue(job: JobData): Promise<CronRunOutcome> {\n if (job.payload.kind !== 'goalContinue') {\n return { status: 'error', error: 'Cron job payload is not goalContinue' };\n }\n if (!this.goalRunner) {\n return { status: 'error', error: 'Goal runner is not configured for cron' };\n }\n const item = this.goalRunner.enqueue(job.payload.goalId, {\n message: job.payload.message,\n maxRetries: job.payload.maxRetries ?? job.maxRetries,\n source: 'cron',\n });\n return {\n status: 'ok',\n summary: `Queued goal ${job.payload.goalId} (${item.status})`,\n sessionId: item.sessionKey,\n sessionKey: item.sessionKey,\n sessionType: 'goal',\n };\n }\n\n private async executeWorkflowRun(job: JobData, signal: AbortSignal): Promise<CronRunOutcome> {\n if (signal.aborted) {\n return { status: 'skipped', error: 'Job was aborted before workflow run start' };\n }\n\n if (job.payload.kind !== 'workflowRun') {\n return { status: 'error', error: 'Cron job payload is not workflowRun' };\n }\n\n if (!this.workflowRunService) {\n return { status: 'error', error: 'Workflow run service is not configured for cron' };\n }\n\n const fallbackAgentId = this.getDefaultCronAgentId?.() ?? DEFAULT_AGENT_ID;\n const agentId = normalizeAgentId(job.payload.agentId || job.agentId || fallbackAgentId);\n const fireId = job.payload.source?.fireId || crypto.randomUUID();\n const source = {\n kind: 'cron' as const,\n scheduleId: job.payload.source?.scheduleId || job.id,\n fireId,\n scheduledAtMs: job.payload.source?.scheduledAtMs ?? Date.now(),\n };\n const result = await this.workflowRunService.startWorkflowRun({\n agentId,\n definitionId: job.payload.definitionId,\n input: job.payload.input,\n inputEnvelope: job.payload.inputEnvelope,\n goal: job.payload.goal,\n source,\n idempotencyKey: `cron:${job.id}:${fireId}`,\n });\n\n if (result.ok === false) {\n return {\n status: 'error',\n error: result.message,\n };\n }\n\n log.info(\n {\n jobId: job.id,\n workflowRunId: result.runId,\n definitionId: job.payload.definitionId,\n sessionKey: result.sessionKey,\n },\n 'Workflow run started from cron',\n );\n\n const waitForCompletion = job.payload.waitForCompletion !== false;\n if (!waitForCompletion || !this.workflowRunService.readWorkflowRunView) {\n return {\n status: 'ok',\n summary: `Started workflow run ${result.runId}`,\n sessionId: result.sessionKey,\n sessionKey: result.sessionKey,\n sessionType: 'workflow',\n workflowRunId: result.runId,\n };\n }\n\n return this.waitForWorkflowRunOutcome({\n job,\n agentId,\n sessionKey: result.sessionKey,\n initialRunId: result.runId,\n signal,\n });\n }\n\n private async waitForWorkflowRunOutcome(params: {\n job: JobData;\n agentId: string;\n sessionKey: string;\n initialRunId: string;\n signal: AbortSignal;\n }): Promise<CronRunOutcome> {\n const waitMs = resolveWorkflowCronWaitMs(params.job.timeout);\n const maxWorkflowRetries = Math.max(0, params.job.maxRetries ?? 0);\n let runId = params.initialRunId;\n let attempt = 0;\n\n while (attempt <= maxWorkflowRetries) {\n const waitResult = await waitForWorkflowRunView({\n readView: (id) => this.workflowRunService!.readWorkflowRunView!(params.agentId, id),\n runId,\n signal: params.signal,\n timeoutMs: waitMs,\n });\n\n if (waitResult.kind === 'aborted') {\n return { status: 'skipped', error: 'Job was aborted while waiting for workflow run' };\n }\n\n if (waitResult.kind === 'timeout') {\n return {\n status: 'error',\n error: `Workflow run ${runId} did not finish within ${waitMs}ms`,\n summary: waitResult.lastView ? buildWorkflowRunCronSummary(waitResult.lastView) : undefined,\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n }\n\n const view = waitResult.view;\n const summary = buildWorkflowRunCronSummary(view);\n const succeeded = isWorkflowRunCronSuccess(view);\n\n if (succeeded) {\n const baseOutcome: CronRunOutcome = {\n status: 'ok',\n summary,\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n await this.deliverWorkflowRunOutcome(params.job, view, baseOutcome);\n return baseOutcome;\n }\n\n const canRetry =\n attempt < maxWorkflowRetries &&\n view.run.status === 'failed' &&\n Boolean(this.workflowRunService?.retryWorkflowRun);\n\n if (!canRetry) {\n return {\n status: 'error',\n summary,\n error: summary,\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n }\n\n const retryResult = await this.workflowRunService!.retryWorkflowRun!({\n agentId: params.agentId,\n runId,\n });\n if (retryResult.ok === false) {\n return {\n status: 'error',\n error: retryResult.message,\n summary,\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n }\n\n runId = retryResult.runId;\n attempt += 1;\n log.info(\n { jobId: params.job.id, attempt, workflowRunId: runId },\n 'Retrying failed workflow run from cron',\n );\n }\n\n return {\n status: 'error',\n error: 'Workflow run retries exhausted',\n sessionId: params.sessionKey,\n sessionKey: params.sessionKey,\n sessionType: 'workflow',\n workflowRunId: runId,\n };\n }\n\n private async deliverWorkflowRunOutcome(\n job: JobData,\n view: WorkflowRunView,\n outcome: CronRunOutcome,\n ): Promise<void> {\n if (!this.messageBus) return;\n const delivery = job.delivery;\n if (!delivery || delivery.mode === 'none' || delivery.channel === 'local' || !delivery.to?.trim()) {\n return;\n }\n\n try {\n const text = buildWorkflowRunDeliveryText(view);\n const outbound = await this.buildCronOutboundMessage(delivery.channel!, delivery.to!, text);\n await this.messageBus.publishOutbound(outbound);\n log.info(\n { jobId: job.id, channel: delivery.channel, to: outbound.chat_id, workflowRunId: view.run.id },\n 'Delivered workflow run result from cron',\n );\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ jobId: job.id, err, workflowRunId: view.run.id }, `Workflow cron delivery failed: ${em}`);\n if (outcome.status === 'ok') {\n outcome.summary = `${outcome.summary ?? ''} (delivery failed: ${em})`.trim();\n }\n }\n }\n\n /**\n * Execute in main session - sends system event\n */\n private async executeMainSession(\n job: JobData,\n signal: AbortSignal,\n timeout: number\n ): Promise<CronRunOutcome> {\n const text = getCronPayloadText(job);\n\n if (!text || !text.trim()) {\n return { status: 'skipped', error: 'Main session job requires non-empty message' };\n }\n\n // Parse delivery from job config, or parse routing from payload text: \"channel:chat_id:content\"\n let channel: string;\n let to: string;\n let actualMessage: string;\n\n if (job.delivery?.channel === 'local') {\n channel = 'local';\n to = '';\n actualMessage = text;\n } else if (job.delivery?.channel && job.delivery?.to) {\n // Use explicit delivery config\n channel = job.delivery.channel;\n to = job.delivery.to;\n actualMessage = text;\n } else {\n // Parse from payload text: \"channel:chat_id:content\"\n const parts = text.split(':');\n const hasAtLeastThreeParts = parts.length >= 3;\n \n // Check if first part looks like a known channel\n const registeredChannelIds = listChannelPlugins().map((p) => p.id);\n const knownChannels = [...new Set([...registeredChannelIds, 'cli', 'gateway', 'local'])];\n const firstPartIsChannel = knownChannels.includes(parts[0]);\n \n if (hasAtLeastThreeParts && firstPartIsChannel) {\n channel = parts[0];\n to = parts[1];\n actualMessage = parts.slice(2).join(':');\n log.info(\n { jobId: job.id, channel, to, parsedFrom: 'message', originalLength: text.length },\n 'Parsed delivery from payload text'\n );\n } else {\n // Fallback to defaults\n channel = 'cli';\n to = 'cron';\n actualMessage = text;\n log.debug(\n { jobId: job.id, partsCount: parts.length, firstPart: parts[0], hasDelivery: !!job.delivery },\n 'Using default delivery - message format not recognized'\n );\n }\n }\n\n // Create timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error(`Job timed out after ${timeout}ms`)), timeout);\n });\n\n // Create execution promise\n const executePromise = (async () => {\n // Check for abort\n if (signal.aborted) {\n throw new Error('Job was aborted');\n }\n\n if (channel === 'local') {\n log.info(\n { jobId: job.id, messageLength: actualMessage.length },\n 'Cron main session: local channel — no outbound publish'\n );\n return {\n status: 'ok' as const,\n summary: actualMessage.slice(0, 200),\n };\n }\n\n const outbound = await this.buildCronOutboundMessage(channel, to, actualMessage);\n\n await this.messageBus.publishOutbound(outbound);\n\n log.info(\n { jobId: job.id, channel, to: outbound.chat_id, messageLength: actualMessage.length },\n 'Sent message to main session'\n );\n\n return {\n status: 'ok' as const,\n summary: actualMessage.slice(0, 200),\n };\n })();\n\n // Race against timeout\n return await Promise.race([executePromise, timeoutPromise]);\n }\n\n /**\n * Execute in isolated mode - runs agent independently\n */\n private async executeIsolated(\n job: JobData,\n signal: AbortSignal,\n timeout: number\n ): Promise<CronRunOutcome> {\n const message = getCronPayloadText(job);\n\n if (!message || !message.trim()) {\n return { status: 'skipped', error: 'Isolated job requires non-empty message' };\n }\n\n const aid = job.agentId?.trim();\n const fallbackAgentId = this.getDefaultCronAgentId?.() ?? DEFAULT_AGENT_ID;\n const sessionKey = buildSessionKey({\n agentId: normalizeAgentId(aid || fallbackAgentId),\n source: 'cron',\n accountId: 'default',\n peerKind: 'dm',\n peerId: job.id,\n });\n\n // Create timeout promise\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => reject(new Error(`Job timed out after ${timeout}ms`)), timeout);\n });\n\n // Create execution promise\n const executePromise = (async () => {\n // Check for abort\n if (signal.aborted) {\n throw new Error('Job was aborted');\n }\n\n await this.agentService.sessionConfig.applyCronJobWorkingDirectory(sessionKey, job.workingDirectory);\n\n const jobModel = resolveIsolatedCronJobModel(job);\n if (jobModel) {\n const ok = await this.agentService.switchModelForSession(sessionKey, jobModel);\n if (!ok) {\n log.warn({ jobId: job.id, sessionKey, model: jobModel }, 'Cron job model invalid; using agent default');\n await this.agentService.resetSessionModelToAgentDefault(sessionKey);\n }\n } else {\n await this.agentService.resetSessionModelToAgentDefault(sessionKey);\n }\n\n const response = await this.agentService.turnDispatcher.processDirect(message, sessionKey);\n\n const model = this.agentService.getModelForSession(sessionKey);\n\n log.info(\n { jobId: job.id, sessionKey, responseLength: response.length, model },\n 'Agent execution completed'\n );\n\n // Handle delivery (`local` channel or `mode: none` = no outbound; transcript in SessionStore)\n const delivery = job.delivery;\n const outboundChannel = delivery?.channel;\n const shouldPublish =\n delivery &&\n delivery.mode !== 'none' &&\n outboundChannel !== 'local' &&\n delivery.to;\n\n if (shouldPublish) {\n if (shouldSilence(response, DEFAULT_ACK_MAX_CHARS) || response.trim() === NO_REPLY) {\n return {\n status: 'ok' as const,\n summary: response.slice(0, 200),\n sessionId: sessionKey,\n sessionKey,\n sessionType: 'cron',\n model,\n };\n }\n const { stripped } = stripHeartbeatToken(response);\n const outboundText = stripped || response.trim();\n\n const targetChannel = outboundChannel || 'cli';\n const outbound = await this.buildCronOutboundMessage(targetChannel, delivery.to, outboundText);\n\n await this.messageBus.publishOutbound(outbound);\n\n log.info(\n { jobId: job.id, channel: targetChannel, to: outbound.chat_id },\n 'Delivered agent response'\n );\n\n return {\n status: 'ok' as const,\n summary: response.slice(0, 200),\n sessionId: sessionKey,\n sessionKey,\n sessionType: 'cron',\n model,\n };\n }\n\n // No outbound delivery: transcript is in SessionStore under `sessionKey`.\n return {\n status: 'ok' as const,\n summary: response.slice(0, 200),\n sessionId: sessionKey,\n sessionKey,\n sessionType: 'cron',\n model,\n };\n })();\n\n // Race against timeout\n try {\n return await Promise.race([executePromise, timeoutPromise]);\n } finally {\n const { retireSessionMcpRuntimeForSessionKey } = await import('../agent/mcp/bundle-mcp-tools.js');\n await retireSessionMcpRuntimeForSessionKey({\n sessionKey,\n reason: 'cron-isolated-end',\n }).catch(() => {});\n }\n }\n\n /**\n * Basic execution without agent service (fallback)\n */\n private async basicExecute(\n job: JobData,\n signal: AbortSignal,\n timeout: number\n ): Promise<CronRunOutcome> {\n return new Promise((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(new Error(`Job timed out after ${timeout}ms`));\n }, timeout);\n\n // Listen for abort signal\n const abortHandler = () => {\n clearTimeout(timeoutId);\n reject(new Error('Job was aborted'));\n };\n signal.addEventListener('abort', abortHandler);\n\n // Simulate basic work\n setTimeout(() => {\n clearTimeout(timeoutId);\n signal.removeEventListener('abort', abortHandler);\n\n if (signal.aborted) {\n reject(new Error('Job was aborted'));\n } else {\n resolve({\n status: 'ok',\n summary: `Executed: ${getCronPayloadText(job).slice(0, 100)}`,\n });\n }\n }, 100);\n });\n }\n\n /**\n * Cancel a running job\n */\n cancelJob(jobId: string): boolean {\n const controller = this.runningJobs.get(jobId);\n if (controller) {\n controller.abort();\n this.runningJobs.delete(jobId);\n return true;\n }\n return false;\n }\n\n /**\n * Get execution history for a job\n */\n getHistory(jobId: string, limit = 10): JobExecution[] {\n const history = this.history.get(jobId) || [];\n return history.slice(-limit);\n }\n\n /**\n * Get currently running executions\n */\n getRunningExecutions(): JobExecution[] {\n const result: JobExecution[] = [];\n for (const [jobId] of this.runningJobs) {\n const history = this.history.get(jobId);\n if (history) {\n const running = history.find((e) => e.status === 'running');\n if (running) result.push(running);\n }\n }\n return result;\n }\n\n /**\n * Check if a job is currently running\n */\n isRunning(jobId: string): boolean {\n return this.runningJobs.has(jobId);\n }\n\n /**\n * Get consecutive error count for a job\n */\n getConsecutiveErrors(jobId: string): number {\n const history = this.history.get(jobId) || [];\n // Find last execution\n for (let i = history.length - 1; i >= 0; i--) {\n if (history[i].status !== 'running') {\n if (history[i].status === 'failed' || history[i].status === 'cancelled') {\n // Count consecutive errors before this\n let count = 0;\n for (let j = i - 1; j >= 0; j--) {\n if (history[j].status === 'failed' || history[j].status === 'cancelled') {\n count++;\n } else {\n break;\n }\n }\n return count + 1;\n }\n return 0;\n }\n }\n return 0;\n }\n\n /**\n * Calculate backoff delay for a job\n */\n calculateBackoff(jobId: string): number {\n const errors = this.getConsecutiveErrors(jobId);\n return errorBackoffMs(errors);\n }\n\n /**\n * Clear old history entries\n */\n cleanupHistory(maxAgeDays = 7): void {\n const cutoff = Date.now() - maxAgeDays * 24 * 60 * 60 * 1000;\n\n for (const [jobId, executions] of this.history) {\n this.history.set(\n jobId,\n executions.filter((e) => new Date(e.startedAt).getTime() > cutoff)\n );\n }\n }\n\n private addToHistory(jobId: string, execution: JobExecution): void {\n const existing = this.history.get(jobId) || [];\n existing.push(execution);\n // Keep last 100 executions per job\n if (existing.length > 100) {\n existing.shift();\n }\n this.history.set(jobId, existing);\n }\n}\n"],"mappings":";;;;;;;;;aAYkD;kBAc2B;kBACjB;AAS5D,MAAM,MAAM,aAAa,eAAe;AAGxC,MAAM,mBAAmB;CACvB;CACA;CACA,IAAI;CACJ,KAAK;CACL,KAAK;CACN;AAED,SAAS,eAAe,mBAAmC;CACzD,MAAM,MAAM,KAAK,IAAI,oBAAoB,GAAG,iBAAiB,SAAS,EAAE;AACxE,QAAO,iBAAiB,KAAK,IAAI,GAAG,IAAI;;AAG1C,SAAS,4BAA4B,KAAkC;CACrE,MAAM,UAAU,IAAI,OAAO,MAAM;AACjC,KAAI,QAAS,QAAO;AACpB,KAAI,IAAI,SAAS,SAAS,aAAa;EACrC,MAAM,IAAI,IAAI,QAAQ,OAAO,MAAM;AACnC,MAAI,EAAG,QAAO;;;AAKlB,IAAa,qBAAb,MAAuD;CACrD,0BAA+C,IAAI,KAAK;CACxD,8BAAsB,IAAI,KAA8B;CACxD,eAA4B;CAC5B,aAA0B;CAC1B,mBAAqD;CACrD;CACA,cAA8C;CAC9C,wBAAuD;CACvD,qBAA4D;CAC5D,aAA2D;CAE3D,eAAe,OAAqC;AAClD,OAAK,cAAc;;CAGrB,QAAQ,MAA6B;AACnC,OAAK,eAAe,KAAK;AACzB,OAAK,aAAa,KAAK;AACvB,OAAK,mBAAmB,KAAK,oBAAoB;AACjD,MAAI,KAAK,iBAAiB,KAAA,EACxB,MAAK,eAAe,KAAK;AAE3B,OAAK,wBAAwB,KAAK,yBAAyB;AAC3D,OAAK,qBAAqB,KAAK,sBAAsB;AACrD,OAAK,aAAa,KAAK,cAAc;;CAGvC,MAAc,yBACZ,SACA,IACA,SAC0B;EAC1B,MAAM,SAAS,iBAAiB,QAAQ;AACxC,MAAI,QAAQ,cAAc;GACxB,MAAM,EAAE,QAAQ,WAAW,aAAa,MAAM,OAAO,aAAa,wBAChE,IACA,KAAK,aACN;GACD,MAAM,OACJ,aAAa,WACT;IAAE,GAAI,YAAY,EAAE;IAAG,GAAI,YAAY,EAAE,WAAW,GAAG,EAAE;IAAG,GAC5D,KAAA;AACN,UAAO;IACL;IACA,SAAS;IACT;IACA,MAAM;IACN,GAAI,QAAQ,OAAO,KAAK,KAAK,CAAC,SAAS,IAAI,EAAE,UAAU,MAAM,GAAG,EAAE;IACnE;;AAEH,SAAO;GACL;GACA,SAAS;GACT;GACA,MAAM;GACP;;CAGH,MAAM,QAAQ,KAAc,QAAqB,MAAuC;AAEtF,MAAI,KACF,MAAK,QAAQ,KAAK;EAGpB,MAAM,cAAc,OAAO,YAAY;EACvC,MAAM,YAA0B;GAC9B,IAAI;GACJ,OAAO,IAAI;GACX,QAAQ;GACR,4BAAW,IAAI,MAAM,EAAC,aAAa;GACnC,YAAY;GACb;AAGD,OAAK,aAAa,IAAI,IAAI,UAAU;AACpC,OAAK,YAAY,IAAI,IAAI,IAAI,IAAI,iBAAiB,CAAC;AAEnD,MAAI,KACF;GAAE,OAAO,IAAI;GAAI;GAAa,SAAS,mBAAmB,IAAI,CAAC,MAAM,GAAG,IAAI;GAAE,EAC9E,gBACD;EAED,IAAI;AAEJ,MAAI;AAEF,OAAI,OAAO,QACT,OAAM,IAAI,MAAM,qCAAqC;AAIvD,YAAS,MAAM,KAAK,WAAW,KAAK,OAAO;AAG3C,aAAU,SAAS,OAAO,WAAW,OAAO,YAAY,OAAO,WAAW,YAAY,cAAc;AACpG,aAAU,2BAAU,IAAI,MAAM,EAAC,aAAa;AAC5C,aAAU,WAAW,KAAK,KAAK,GAAG,IAAI,KAAK,UAAU,UAAU,CAAC,SAAS;AACzE,aAAU,UAAU,OAAO;AAC3B,aAAU,QAAQ,OAAO;AACzB,aAAU,YAAY,OAAO;AAC7B,aAAU,aAAa,OAAO;AAC9B,aAAU,cAAc,OAAO;AAC/B,aAAU,QAAQ,OAAO;AACzB,aAAU,gBAAgB,OAAO;AAEjC,OAAI,OAAO,WAAW,KACpB,KAAI,KACF;IAAE,OAAO,IAAI;IAAI;IAAa,UAAU,UAAU;IAAU,EAC5D,gBACD;YACQ,OAAO,WAAW,UAC3B,KAAI,KAAK;IAAE,OAAO,IAAI;IAAI;IAAa,QAAQ,OAAO;IAAO,EAAE,cAAc;OAE7E,KAAI,MACF;IAAE,OAAO,IAAI;IAAI;IAAa,cAAc,OAAO;IAAO,OAAO;IAAgB,EACjF,eAAe,OAAO,SAAS,YAChC;AAGH,OAAI,OAAO,WAAW,QAAQ,KAAK,iBACjC,KAAI;AACF,SAAK,iBAAiB,WAAW,EAAE,QAAQ,QAAQ,IAAI,MAAM,CAAC;YACvD,GAAG;AACV,QAAI,KAAK;KAAE,OAAO,IAAI;KAAI,KAAK;KAAG,EAAE,mCAAmC;;WAGpE,OAAO;AACd,aAAU,SAAS;AACnB,aAAU,2BAAU,IAAI,MAAM,EAAC,aAAa;AAC5C,aAAU,WAAW,KAAK,KAAK,GAAG,IAAI,KAAK,UAAU,UAAU,CAAC,SAAS;AACzE,aAAU,QAAQ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAExE,OAAI,MACF;IACE,KAAK;IACL,cAAc,UAAU;IACxB,OAAO,IAAI;IACX;IACA,OAAO;IACR,EACD,wBAAwB,UAAU,QACnC;AAED,YAAS;IACP,QAAQ;IACR,OAAO,UAAU;IAClB;YACO;AACR,QAAK,YAAY,OAAO,IAAI,GAAG;;AAGjC,MAAI,KAAK,YACP,OAAM,KAAK,YAAY,gBAAgB,UAAU;;;;;CASrD,MAAgB,WAAW,KAAc,QAA8C;EACrF,MAAM,UAAU,IAAI,WAAW;EAC/B,MAAM,gBAAgB,IAAI,iBAAiB;AAG3C,MAAI,OAAO,QACT,QAAO;GAAE,QAAQ;GAAW,OAAO;GAAoC;AAGzE,MAAI;AACF,OAAI,IAAI,QAAQ,SAAS,eACvB,QAAO,MAAM,KAAK,oBAAoB,IAAI;AAG5C,OAAI,IAAI,QAAQ,SAAS,cACvB,QAAO,MAAM,KAAK,mBAAmB,KAAK,OAAO;AAInD,OAAI,CAAC,KAAK,gBAAgB,CAAC,KAAK,YAAY;AAC1C,QAAI,KAAK,EAAE,OAAO,IAAI,IAAI,EAAE,qDAAqD;AACjF,WAAO,KAAK,aAAa,KAAK,QAAQ,QAAQ;;AAGhD,OAAI,kBAAkB,OACpB,QAAO,MAAM,KAAK,mBAAmB,KAAK,QAAQ,QAAQ;OAE1D,QAAO,MAAM,KAAK,gBAAgB,KAAK,QAAQ,QAAQ;WAElD,OAAO;AACd,UAAO;IACL,QAAQ;IACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC9D;;;CAIL,MAAc,oBAAoB,KAAuC;AACvE,MAAI,IAAI,QAAQ,SAAS,eACvB,QAAO;GAAE,QAAQ;GAAS,OAAO;GAAwC;AAE3E,MAAI,CAAC,KAAK,WACR,QAAO;GAAE,QAAQ;GAAS,OAAO;GAA0C;EAE7E,MAAM,OAAO,KAAK,WAAW,QAAQ,IAAI,QAAQ,QAAQ;GACvD,SAAS,IAAI,QAAQ;GACrB,YAAY,IAAI,QAAQ,cAAc,IAAI;GAC1C,QAAQ;GACT,CAAC;AACF,SAAO;GACL,QAAQ;GACR,SAAS,eAAe,IAAI,QAAQ,OAAO,IAAI,KAAK,OAAO;GAC3D,WAAW,KAAK;GAChB,YAAY,KAAK;GACjB,aAAa;GACd;;CAGH,MAAc,mBAAmB,KAAc,QAA8C;AAC3F,MAAI,OAAO,QACT,QAAO;GAAE,QAAQ;GAAW,OAAO;GAA6C;AAGlF,MAAI,IAAI,QAAQ,SAAS,cACvB,QAAO;GAAE,QAAQ;GAAS,OAAO;GAAuC;AAG1E,MAAI,CAAC,KAAK,mBACR,QAAO;GAAE,QAAQ;GAAS,OAAO;GAAmD;EAGtF,MAAM,kBAAkB,KAAK,yBAAyB,IAAA;EACtD,MAAM,UAAU,iBAAiB,IAAI,QAAQ,WAAW,IAAI,WAAW,gBAAgB;EACvF,MAAM,SAAS,IAAI,QAAQ,QAAQ,UAAU,OAAO,YAAY;EAChE,MAAM,SAAS;GACb,MAAM;GACN,YAAY,IAAI,QAAQ,QAAQ,cAAc,IAAI;GAClD;GACA,eAAe,IAAI,QAAQ,QAAQ,iBAAiB,KAAK,KAAK;GAC/D;EACD,MAAM,SAAS,MAAM,KAAK,mBAAmB,iBAAiB;GAC5D;GACA,cAAc,IAAI,QAAQ;GAC1B,OAAO,IAAI,QAAQ;GACnB,eAAe,IAAI,QAAQ;GAC3B,MAAM,IAAI,QAAQ;GAClB;GACA,gBAAgB,QAAQ,IAAI,GAAG,GAAG;GACnC,CAAC;AAEF,MAAI,OAAO,OAAO,MAChB,QAAO;GACL,QAAQ;GACR,OAAO,OAAO;GACf;AAGH,MAAI,KACF;GACE,OAAO,IAAI;GACX,eAAe,OAAO;GACtB,cAAc,IAAI,QAAQ;GAC1B,YAAY,OAAO;GACpB,EACD,iCACD;AAGD,MAAI,EADsB,IAAI,QAAQ,sBAAsB,UAClC,CAAC,KAAK,mBAAmB,oBACjD,QAAO;GACL,QAAQ;GACR,SAAS,wBAAwB,OAAO;GACxC,WAAW,OAAO;GAClB,YAAY,OAAO;GACnB,aAAa;GACb,eAAe,OAAO;GACvB;AAGH,SAAO,KAAK,0BAA0B;GACpC;GACA;GACA,YAAY,OAAO;GACnB,cAAc,OAAO;GACrB;GACD,CAAC;;CAGJ,MAAc,0BAA0B,QAMZ;EAC1B,MAAM,SAAS,0BAA0B,OAAO,IAAI,QAAQ;EAC5D,MAAM,qBAAqB,KAAK,IAAI,GAAG,OAAO,IAAI,cAAc,EAAE;EAClE,IAAI,QAAQ,OAAO;EACnB,IAAI,UAAU;AAEd,SAAO,WAAW,oBAAoB;GACpC,MAAM,aAAa,MAAM,uBAAuB;IAC9C,WAAW,OAAO,KAAK,mBAAoB,oBAAqB,OAAO,SAAS,GAAG;IACnF;IACA,QAAQ,OAAO;IACf,WAAW;IACZ,CAAC;AAEF,OAAI,WAAW,SAAS,UACtB,QAAO;IAAE,QAAQ;IAAW,OAAO;IAAkD;AAGvF,OAAI,WAAW,SAAS,UACtB,QAAO;IACL,QAAQ;IACR,OAAO,gBAAgB,MAAM,yBAAyB,OAAO;IAC7D,SAAS,WAAW,WAAW,4BAA4B,WAAW,SAAS,GAAG,KAAA;IAClF,WAAW,OAAO;IAClB,YAAY,OAAO;IACnB,aAAa;IACb,eAAe;IAChB;GAGH,MAAM,OAAO,WAAW;GACxB,MAAM,UAAU,4BAA4B,KAAK;AAGjD,OAFkB,yBAAyB,KAE9B,EAAE;IACb,MAAM,cAA8B;KAClC,QAAQ;KACR;KACA,WAAW,OAAO;KAClB,YAAY,OAAO;KACnB,aAAa;KACb,eAAe;KAChB;AACD,UAAM,KAAK,0BAA0B,OAAO,KAAK,MAAM,YAAY;AACnE,WAAO;;AAQT,OAAI,EAJF,UAAU,sBACV,KAAK,IAAI,WAAW,YACpB,QAAQ,KAAK,oBAAoB,iBAAiB,EAGlD,QAAO;IACL,QAAQ;IACR;IACA,OAAO;IACP,WAAW,OAAO;IAClB,YAAY,OAAO;IACnB,aAAa;IACb,eAAe;IAChB;GAGH,MAAM,cAAc,MAAM,KAAK,mBAAoB,iBAAkB;IACnE,SAAS,OAAO;IAChB;IACD,CAAC;AACF,OAAI,YAAY,OAAO,MACrB,QAAO;IACL,QAAQ;IACR,OAAO,YAAY;IACnB;IACA,WAAW,OAAO;IAClB,YAAY,OAAO;IACnB,aAAa;IACb,eAAe;IAChB;AAGH,WAAQ,YAAY;AACpB,cAAW;AACX,OAAI,KACF;IAAE,OAAO,OAAO,IAAI;IAAI;IAAS,eAAe;IAAO,EACvD,yCACD;;AAGH,SAAO;GACL,QAAQ;GACR,OAAO;GACP,WAAW,OAAO;GAClB,YAAY,OAAO;GACnB,aAAa;GACb,eAAe;GAChB;;CAGH,MAAc,0BACZ,KACA,MACA,SACe;AACf,MAAI,CAAC,KAAK,WAAY;EACtB,MAAM,WAAW,IAAI;AACrB,MAAI,CAAC,YAAY,SAAS,SAAS,UAAU,SAAS,YAAY,WAAW,CAAC,SAAS,IAAI,MAAM,CAC/F;AAGF,MAAI;GACF,MAAM,OAAO,6BAA6B,KAAK;GAC/C,MAAM,WAAW,MAAM,KAAK,yBAAyB,SAAS,SAAU,SAAS,IAAK,KAAK;AAC3F,SAAM,KAAK,WAAW,gBAAgB,SAAS;AAC/C,OAAI,KACF;IAAE,OAAO,IAAI;IAAI,SAAS,SAAS;IAAS,IAAI,SAAS;IAAS,eAAe,KAAK,IAAI;IAAI,EAC9F,0CACD;WACM,KAAK;GACZ,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAI,KAAK;IAAE,OAAO,IAAI;IAAI;IAAK,eAAe,KAAK,IAAI;IAAI,EAAE,kCAAkC,KAAK;AACpG,OAAI,QAAQ,WAAW,KACrB,SAAQ,UAAU,GAAG,QAAQ,WAAW,GAAG,qBAAqB,GAAG,GAAG,MAAM;;;;;;CAQlF,MAAc,mBACZ,KACA,QACA,SACyB;EACzB,MAAM,OAAO,mBAAmB,IAAI;AAEpC,MAAI,CAAC,QAAQ,CAAC,KAAK,MAAM,CACvB,QAAO;GAAE,QAAQ;GAAW,OAAO;GAA+C;EAIpF,IAAI;EACJ,IAAI;EACJ,IAAI;AAEJ,MAAI,IAAI,UAAU,YAAY,SAAS;AACrC,aAAU;AACV,QAAK;AACL,mBAAgB;aACP,IAAI,UAAU,WAAW,IAAI,UAAU,IAAI;AAEpD,aAAU,IAAI,SAAS;AACvB,QAAK,IAAI,SAAS;AAClB,mBAAgB;SACX;GAEL,MAAM,QAAQ,KAAK,MAAM,IAAI;GAC7B,MAAM,uBAAuB,MAAM,UAAU;GAG7C,MAAM,uBAAuB,oBAAoB,CAAC,KAAK,MAAM,EAAE,GAAG;GAElE,MAAM,qBAAqB,CADJ,GAAG,IAAI,IAAI;IAAC,GAAG;IAAsB;IAAO;IAAW;IAAQ,CAAC,CAC/C,CAAC,SAAS,MAAM,GAAG;AAE3D,OAAI,wBAAwB,oBAAoB;AAC9C,cAAU,MAAM;AAChB,SAAK,MAAM;AACX,oBAAgB,MAAM,MAAM,EAAE,CAAC,KAAK,IAAI;AACxC,QAAI,KACF;KAAE,OAAO,IAAI;KAAI;KAAS;KAAI,YAAY;KAAW,gBAAgB,KAAK;KAAQ,EAClF,oCACD;UACI;AAEL,cAAU;AACV,SAAK;AACL,oBAAgB;AAChB,QAAI,MACF;KAAE,OAAO,IAAI;KAAI,YAAY,MAAM;KAAQ,WAAW,MAAM;KAAI,aAAa,CAAC,CAAC,IAAI;KAAU,EAC7F,yDACD;;;EAKL,MAAM,iBAAiB,IAAI,SAAgB,GAAG,WAAW;AACvD,oBAAiB,uBAAO,IAAI,MAAM,uBAAuB,QAAQ,IAAI,CAAC,EAAE,QAAQ;IAChF;EAGF,MAAM,kBAAkB,YAAY;AAElC,OAAI,OAAO,QACT,OAAM,IAAI,MAAM,kBAAkB;AAGpC,OAAI,YAAY,SAAS;AACvB,QAAI,KACF;KAAE,OAAO,IAAI;KAAI,eAAe,cAAc;KAAQ,EACtD,yDACD;AACD,WAAO;KACL,QAAQ;KACR,SAAS,cAAc,MAAM,GAAG,IAAI;KACrC;;GAGH,MAAM,WAAW,MAAM,KAAK,yBAAyB,SAAS,IAAI,cAAc;AAEhF,SAAM,KAAK,WAAW,gBAAgB,SAAS;AAE/C,OAAI,KACF;IAAE,OAAO,IAAI;IAAI;IAAS,IAAI,SAAS;IAAS,eAAe,cAAc;IAAQ,EACrF,+BACD;AAED,UAAO;IACL,QAAQ;IACR,SAAS,cAAc,MAAM,GAAG,IAAI;IACrC;MACC;AAGJ,SAAO,MAAM,QAAQ,KAAK,CAAC,gBAAgB,eAAe,CAAC;;;;;CAM7D,MAAc,gBACZ,KACA,QACA,SACyB;EACzB,MAAM,UAAU,mBAAmB,IAAI;AAEvC,MAAI,CAAC,WAAW,CAAC,QAAQ,MAAM,CAC7B,QAAO;GAAE,QAAQ;GAAW,OAAO;GAA2C;EAGhF,MAAM,MAAM,IAAI,SAAS,MAAM;EAC/B,MAAM,kBAAkB,KAAK,yBAAyB,IAAA;EACtD,MAAM,aAAa,gBAAgB;GACjC,SAAS,iBAAiB,OAAO,gBAAgB;GACjD,QAAQ;GACR,WAAW;GACX,UAAU;GACV,QAAQ,IAAI;GACb,CAAC;EAGF,MAAM,iBAAiB,IAAI,SAAgB,GAAG,WAAW;AACvD,oBAAiB,uBAAO,IAAI,MAAM,uBAAuB,QAAQ,IAAI,CAAC,EAAE,QAAQ;IAChF;EAGF,MAAM,kBAAkB,YAAY;AAElC,OAAI,OAAO,QACT,OAAM,IAAI,MAAM,kBAAkB;AAGpC,SAAM,KAAK,aAAa,cAAc,6BAA6B,YAAY,IAAI,iBAAiB;GAEpG,MAAM,WAAW,4BAA4B,IAAI;AACjD,OAAI;QAEE,CAAC,MADY,KAAK,aAAa,sBAAsB,YAAY,SAAS,EACrE;AACP,SAAI,KAAK;MAAE,OAAO,IAAI;MAAI;MAAY,OAAO;MAAU,EAAE,8CAA8C;AACvG,WAAM,KAAK,aAAa,gCAAgC,WAAW;;SAGrE,OAAM,KAAK,aAAa,gCAAgC,WAAW;GAGrE,MAAM,WAAW,MAAM,KAAK,aAAa,eAAe,cAAc,SAAS,WAAW;GAE1F,MAAM,QAAQ,KAAK,aAAa,mBAAmB,WAAW;AAE9D,OAAI,KACF;IAAE,OAAO,IAAI;IAAI;IAAY,gBAAgB,SAAS;IAAQ;IAAO,EACrE,4BACD;GAGD,MAAM,WAAW,IAAI;GACrB,MAAM,kBAAkB,UAAU;AAOlC,OALE,YACA,SAAS,SAAS,UAClB,oBAAoB,WACpB,SAAS,IAEQ;AACjB,QAAI,cAAc,UAAA,IAAgC,IAAI,SAAS,MAAM,KAAA,WACnE,QAAO;KACL,QAAQ;KACR,SAAS,SAAS,MAAM,GAAG,IAAI;KAC/B,WAAW;KACX;KACA,aAAa;KACb;KACD;IAEH,MAAM,EAAE,aAAa,oBAAoB,SAAS;IAClD,MAAM,eAAe,YAAY,SAAS,MAAM;IAEhD,MAAM,gBAAgB,mBAAmB;IACzC,MAAM,WAAW,MAAM,KAAK,yBAAyB,eAAe,SAAS,IAAI,aAAa;AAE9F,UAAM,KAAK,WAAW,gBAAgB,SAAS;AAE/C,QAAI,KACF;KAAE,OAAO,IAAI;KAAI,SAAS;KAAe,IAAI,SAAS;KAAS,EAC/D,2BACD;AAED,WAAO;KACL,QAAQ;KACR,SAAS,SAAS,MAAM,GAAG,IAAI;KAC/B,WAAW;KACX;KACA,aAAa;KACb;KACD;;AAIH,UAAO;IACL,QAAQ;IACR,SAAS,SAAS,MAAM,GAAG,IAAI;IAC/B,WAAW;IACX;IACA,aAAa;IACb;IACD;MACC;AAGJ,MAAI;AACF,UAAO,MAAM,QAAQ,KAAK,CAAC,gBAAgB,eAAe,CAAC;YACnD;GACR,MAAM,EAAE,yCAAyC,MAAM,OAAO;AAC9D,SAAM,qCAAqC;IACzC;IACA,QAAQ;IACT,CAAC,CAAC,YAAY,GAAG;;;;;;CAOtB,MAAc,aACZ,KACA,QACA,SACyB;AACzB,SAAO,IAAI,SAAS,SAAS,WAAW;GACtC,MAAM,YAAY,iBAAiB;AACjC,2BAAO,IAAI,MAAM,uBAAuB,QAAQ,IAAI,CAAC;MACpD,QAAQ;GAGX,MAAM,qBAAqB;AACzB,iBAAa,UAAU;AACvB,2BAAO,IAAI,MAAM,kBAAkB,CAAC;;AAEtC,UAAO,iBAAiB,SAAS,aAAa;AAG9C,oBAAiB;AACf,iBAAa,UAAU;AACvB,WAAO,oBAAoB,SAAS,aAAa;AAEjD,QAAI,OAAO,QACT,wBAAO,IAAI,MAAM,kBAAkB,CAAC;QAEpC,SAAQ;KACN,QAAQ;KACR,SAAS,aAAa,mBAAmB,IAAI,CAAC,MAAM,GAAG,IAAI;KAC5D,CAAC;MAEH,IAAI;IACP;;;;;CAMJ,UAAU,OAAwB;EAChC,MAAM,aAAa,KAAK,YAAY,IAAI,MAAM;AAC9C,MAAI,YAAY;AACd,cAAW,OAAO;AAClB,QAAK,YAAY,OAAO,MAAM;AAC9B,UAAO;;AAET,SAAO;;;;;CAMT,WAAW,OAAe,QAAQ,IAAoB;AAEpD,UADgB,KAAK,QAAQ,IAAI,MAAM,IAAI,EAAE,EAC9B,MAAM,CAAC,MAAM;;;;;CAM9B,uBAAuC;EACrC,MAAM,SAAyB,EAAE;AACjC,OAAK,MAAM,CAAC,UAAU,KAAK,aAAa;GACtC,MAAM,UAAU,KAAK,QAAQ,IAAI,MAAM;AACvC,OAAI,SAAS;IACX,MAAM,UAAU,QAAQ,MAAM,MAAM,EAAE,WAAW,UAAU;AAC3D,QAAI,QAAS,QAAO,KAAK,QAAQ;;;AAGrC,SAAO;;;;;CAMT,UAAU,OAAwB;AAChC,SAAO,KAAK,YAAY,IAAI,MAAM;;;;;CAMpC,qBAAqB,OAAuB;EAC1C,MAAM,UAAU,KAAK,QAAQ,IAAI,MAAM,IAAI,EAAE;AAE7C,OAAK,IAAI,IAAI,QAAQ,SAAS,GAAG,KAAK,GAAG,IACvC,KAAI,QAAQ,GAAG,WAAW,WAAW;AACnC,OAAI,QAAQ,GAAG,WAAW,YAAY,QAAQ,GAAG,WAAW,aAAa;IAEvE,IAAI,QAAQ;AACZ,SAAK,IAAI,IAAI,IAAI,GAAG,KAAK,GAAG,IAC1B,KAAI,QAAQ,GAAG,WAAW,YAAY,QAAQ,GAAG,WAAW,YAC1D;QAEA;AAGJ,WAAO,QAAQ;;AAEjB,UAAO;;AAGX,SAAO;;;;;CAMT,iBAAiB,OAAuB;AAEtC,SAAO,eADQ,KAAK,qBAAqB,MACb,CAAC;;;;;CAM/B,eAAe,aAAa,GAAS;EACnC,MAAM,SAAS,KAAK,KAAK,GAAG,aAAa,KAAK,KAAK,KAAK;AAExD,OAAK,MAAM,CAAC,OAAO,eAAe,KAAK,QACrC,MAAK,QAAQ,IACX,OACA,WAAW,QAAQ,MAAM,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,GAAG,OAAO,CACnE;;CAIL,aAAqB,OAAe,WAA+B;EACjE,MAAM,WAAW,KAAK,QAAQ,IAAI,MAAM,IAAI,EAAE;AAC9C,WAAS,KAAK,UAAU;AAExB,MAAI,SAAS,SAAS,IACpB,UAAS,OAAO;AAElB,OAAK,QAAQ,IAAI,OAAO,SAAS"}
@@ -6,6 +6,7 @@ function getCronPayloadText(job) {
6
6
  const p = job.payload;
7
7
  if (p.kind === "systemEvent") return p.text;
8
8
  if (p.kind === "agentTurn") return p.message;
9
+ if (p.kind === "goalContinue") return p.message || p.goalId;
9
10
  return p.goal || p.definitionId;
10
11
  }
11
12
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"job-content.js","names":[],"sources":["../../../src/cron/job-content.ts"],"sourcesContent":["import type { JobData } from './types.js';\n\n/**\n * Executable body text from a cron job (`payload` only).\n */\nexport function getCronPayloadText(job: Pick<JobData, 'payload'>): string {\n const p = job.payload;\n if (p.kind === 'systemEvent') return p.text;\n if (p.kind === 'agentTurn') return p.message;\n return p.goal || p.definitionId;\n}\n"],"mappings":";;;;AAKA,SAAgB,mBAAmB,KAAuC;CACxE,MAAM,IAAI,IAAI;AACd,KAAI,EAAE,SAAS,cAAe,QAAO,EAAE;AACvC,KAAI,EAAE,SAAS,YAAa,QAAO,EAAE;AACrC,QAAO,EAAE,QAAQ,EAAE"}
1
+ {"version":3,"file":"job-content.js","names":[],"sources":["../../../src/cron/job-content.ts"],"sourcesContent":["import type { JobData } from './types.js';\n\n/**\n * Executable body text from a cron job (`payload` only).\n */\nexport function getCronPayloadText(job: Pick<JobData, 'payload'>): string {\n const p = job.payload;\n if (p.kind === 'systemEvent') return p.text;\n if (p.kind === 'agentTurn') return p.message;\n if (p.kind === 'goalContinue') return p.message || p.goalId;\n return p.goal || p.definitionId;\n}\n"],"mappings":";;;;AAKA,SAAgB,mBAAmB,KAAuC;CACxE,MAAM,IAAI,IAAI;AACd,KAAI,EAAE,SAAS,cAAe,QAAO,EAAE;AACvC,KAAI,EAAE,SAAS,YAAa,QAAO,EAAE;AACrC,KAAI,EAAE,SAAS,eAAgB,QAAO,EAAE,WAAW,EAAE;AACrD,QAAO,EAAE,QAAQ,EAAE"}
@@ -17,7 +17,13 @@ export type CronPayload = {
17
17
  message: string;
18
18
  model?: string;
19
19
  timeoutSeconds?: number;
20
- } | CronWorkflowRunPayload;
20
+ } | CronGoalContinuePayload | CronWorkflowRunPayload;
21
+ export interface CronGoalContinuePayload {
22
+ kind: 'goalContinue';
23
+ goalId: string;
24
+ message?: string;
25
+ maxRetries?: number;
26
+ }
21
27
  export interface CronWorkflowRunPayload {
22
28
  kind: 'workflowRun';
23
29
  definitionId: string;
@@ -92,6 +98,18 @@ export interface JobExecutorDeps {
92
98
  */
93
99
  getDefaultCronAgentId?: () => string;
94
100
  workflowRunService?: CronWorkflowRunStarter;
101
+ goalRunner?: {
102
+ enqueue(goalId: string, options?: {
103
+ message?: string;
104
+ maxRetries?: number;
105
+ source?: 'api' | 'cron' | 'workflow' | 'system';
106
+ }): {
107
+ id: string;
108
+ goalId: string;
109
+ status: string;
110
+ sessionKey?: string;
111
+ };
112
+ };
95
113
  }
96
114
  export interface JobExecutor {
97
115
  execute(job: JobData, signal: AbortSignal, deps?: JobExecutorDeps): Promise<void>;
@@ -8,6 +8,11 @@ declare const CronPayloadSchema: z.ZodUnion<readonly [z.ZodObject<{
8
8
  message: z.ZodString;
9
9
  model: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
10
10
  timeoutSeconds: z.ZodOptional<z.ZodNumber>;
11
+ }, z.core.$strip>, z.ZodObject<{
12
+ kind: z.ZodLiteral<"goalContinue">;
13
+ goalId: z.ZodString;
14
+ message: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
15
+ maxRetries: z.ZodOptional<z.ZodNumber>;
11
16
  }, z.core.$strip>, z.ZodObject<{
12
17
  kind: z.ZodLiteral<"workflowRun">;
13
18
  definitionId: z.ZodString;
@@ -63,6 +68,11 @@ export declare const JobDataSchema: z.ZodObject<{
63
68
  message: z.ZodString;
64
69
  model: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
65
70
  timeoutSeconds: z.ZodOptional<z.ZodNumber>;
71
+ }, z.core.$strip>, z.ZodObject<{
72
+ kind: z.ZodLiteral<"goalContinue">;
73
+ goalId: z.ZodString;
74
+ message: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
75
+ maxRetries: z.ZodOptional<z.ZodNumber>;
66
76
  }, z.core.$strip>, z.ZodObject<{
67
77
  kind: z.ZodLiteral<"workflowRun">;
68
78
  definitionId: z.ZodString;
@@ -117,6 +127,11 @@ export declare const AddJobRequestSchema: z.ZodObject<{
117
127
  message: z.ZodString;
118
128
  model: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
119
129
  timeoutSeconds: z.ZodOptional<z.ZodNumber>;
130
+ }, z.core.$strip>, z.ZodObject<{
131
+ kind: z.ZodLiteral<"goalContinue">;
132
+ goalId: z.ZodString;
133
+ message: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
134
+ maxRetries: z.ZodOptional<z.ZodNumber>;
120
135
  }, z.core.$strip>, z.ZodObject<{
121
136
  kind: z.ZodLiteral<"workflowRun">;
122
137
  definitionId: z.ZodString;
@@ -171,6 +186,11 @@ export declare const UpdateJobRequestSchema: z.ZodObject<{
171
186
  message: z.ZodString;
172
187
  model: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
173
188
  timeoutSeconds: z.ZodOptional<z.ZodNumber>;
189
+ }, z.core.$strip>, z.ZodObject<{
190
+ kind: z.ZodLiteral<"goalContinue">;
191
+ goalId: z.ZodString;
192
+ message: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
193
+ maxRetries: z.ZodOptional<z.ZodNumber>;
174
194
  }, z.core.$strip>, z.ZodObject<{
175
195
  kind: z.ZodLiteral<"workflowRun">;
176
196
  definitionId: z.ZodString;
@@ -76,6 +76,12 @@ const CronAgentTurnPayloadSchema = z.object({
76
76
  model: optionalTrimmedString(100, 1),
77
77
  timeoutSeconds: z.number().int().min(10).max(3600).optional()
78
78
  });
79
+ const CronGoalContinuePayloadSchema = z.object({
80
+ kind: z.literal("goalContinue"),
81
+ goalId: z.string().min(1).max(100),
82
+ message: optionalTrimmedString(5e4, 1),
83
+ maxRetries: z.number().int().min(0).max(10).optional()
84
+ });
79
85
  const WorkflowRunInputEnvelopeSchema = z.object({
80
86
  payload: z.unknown(),
81
87
  goal: optionalTrimmedString(5e3, 1),
@@ -101,6 +107,7 @@ const CronWorkflowRunPayloadSchema = z.object({
101
107
  const CronPayloadSchema = z.union([
102
108
  CronSystemEventPayloadSchema,
103
109
  CronAgentTurnPayloadSchema,
110
+ CronGoalContinuePayloadSchema,
104
111
  CronWorkflowRunPayloadSchema
105
112
  ]);
106
113
  const CronDeliverySchema = z.object({
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","names":[],"sources":["../../../src/cron/validation.ts"],"sourcesContent":["// Cron input validation using Zod\nimport { z } from 'zod';\nimport nodeCron from 'node-cron';\n\n// Custom cron validation\nconst cronExpression = z.string().superRefine((val, ctx) => {\n if (!nodeCron.validate(val)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Invalid cron expression: ${val}`,\n });\n }\n});\n\n// Valid timezones (subset of IANA timezones)\nconst validTimezones = [\n 'UTC',\n 'America/New_York',\n 'America/Chicago',\n 'America/Denver',\n 'America/Los_Angeles',\n 'America/Toronto',\n 'Europe/London',\n 'Europe/Paris',\n 'Europe/Berlin',\n 'Europe/Moscow',\n 'Asia/Tokyo',\n 'Asia/Shanghai',\n 'Asia/Hong_Kong',\n 'Asia/Singapore',\n 'Asia/Seoul',\n 'Asia/Dubai',\n 'Asia/Mumbai',\n 'Australia/Sydney',\n 'Pacific/Auckland',\n];\n\nconst CronDeliveryMode = z.enum(['none', 'announce', 'direct']);\n\n/** Treat `''` / `null` / whitespace-only as absent so optional fields do not fail `.min(1)` */\nfunction optionalTrimmedString(max: number, min = 1) {\n return z.preprocess((v) => {\n if (v === null || v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? undefined : t;\n }, z.string().min(min).max(max).optional());\n}\n\n/** Optional agent id on create; empty string → undefined. */\nconst optionalJobAgentId = optionalTrimmedString(64, 1);\n\n/** Optional absolute workspace path on create; empty string → undefined. */\nconst optionalJobWorkingDirectory = optionalTrimmedString(4096, 1);\n\n/**\n * PATCH: set string, or `null` / empty to clear `workingDirectory` on the job.\n */\nconst patchJobWorkingDirectory = z.preprocess((v) => {\n if (v === null) return null;\n if (v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? null : t;\n}, z.union([z.string().min(1).max(4096), z.null()]).optional());\n\n/**\n * PATCH: set string, or `null` / empty to clear `agentId` on the job.\n */\nconst patchJobAgentId = z.preprocess((v) => {\n if (v === null) return null;\n if (v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? null : t;\n}, z.union([z.string().min(1).max(64), z.null()]).optional());\n\n// CronPayload validation\nconst CronSystemEventPayloadSchema = z.object({\n kind: z.literal('systemEvent'),\n text: z.string().min(1).max(50000),\n});\n\nconst CronAgentTurnPayloadSchema = z.object({\n kind: z.literal('agentTurn'),\n message: z.string().min(1).max(50000),\n model: optionalTrimmedString(100, 1),\n timeoutSeconds: z.number().int().min(10).max(3600).optional(),\n});\n\nconst WorkflowRunInputEnvelopeSchema = z.object({\n payload: z.unknown(),\n goal: optionalTrimmedString(5000, 1),\n variables: z.record(z.string(), z.unknown()).optional(),\n context: z.record(z.string(), z.unknown()).optional(),\n});\n\nconst CronWorkflowRunPayloadSchema = z.object({\n kind: z.literal('workflowRun'),\n definitionId: z.string().min(1).max(200),\n input: z.unknown().optional(),\n inputEnvelope: WorkflowRunInputEnvelopeSchema.optional(),\n goal: optionalTrimmedString(5000, 1),\n agentId: optionalTrimmedString(64, 1),\n sessionKey: optionalTrimmedString(300, 1),\n waitForCompletion: z.boolean().optional(),\n source: z.object({\n kind: z.literal('cron').optional(),\n scheduleId: optionalTrimmedString(200, 1),\n fireId: optionalTrimmedString(200, 1),\n scheduledAtMs: z.number().int().nonnegative().optional(),\n }).optional(),\n});\n\nconst CronPayloadSchema = z.union([\n CronSystemEventPayloadSchema,\n CronAgentTurnPayloadSchema,\n CronWorkflowRunPayloadSchema,\n]);\n\n// CronDelivery validation — channel must match gateway UI / message bus ids (telegram, weixin, cli, local, …)\nconst CronDeliverySchema = z.object({\n mode: CronDeliveryMode.default('none'),\n channel: optionalTrimmedString(32, 1),\n to: z.preprocess(\n (v) => (v === '' || v === null || v === undefined ? undefined : v),\n z.string().max(100).optional(),\n ),\n bestEffort: z.boolean().optional(),\n});\n\nexport const JobDataSchema = z\n .object({\n id: z.string().min(1).max(32),\n name: z.string().max(100).optional(),\n schedule: cronExpression,\n enabled: z.boolean(),\n timezone: z.string().superRefine((val, ctx) => {\n if (val && !validTimezones.includes(val)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Invalid timezone: ${val}. Use IANA timezone names.`,\n });\n }\n }).optional(),\n maxRetries: z.number().int().min(0).max(10).default(3),\n timeout: z.number().int().min(1000).max(7_200_000).default(180000),\n created_at: z.string().datetime(),\n updated_at: z.string().datetime(),\n sessionTarget: z.enum(['main', 'isolated']).optional(),\n agentId: optionalTrimmedString(64, 1),\n workingDirectory: optionalJobWorkingDirectory,\n payload: CronPayloadSchema,\n delivery: CronDeliverySchema.optional(),\n model: optionalTrimmedString(100, 1),\n state: z.any().optional(),\n })\n .strict();\n\nexport const AddJobRequestSchema = z.object({\n schedule: cronExpression,\n name: z.string().max(100).optional(),\n timezone: z.string().optional(),\n maxRetries: z.number().int().min(0).max(10).optional(),\n timeout: z.number().int().min(1000).max(7_200_000).optional(),\n sessionTarget: z.enum(['main', 'isolated']).optional(),\n agentId: optionalJobAgentId,\n workingDirectory: optionalJobWorkingDirectory,\n payload: CronPayloadSchema,\n delivery: CronDeliverySchema.optional(),\n model: optionalTrimmedString(100, 1),\n});\n\nexport const UpdateJobRequestSchema = z.object({\n name: z.string().max(100).optional(),\n schedule: cronExpression.optional(),\n timezone: z.string().optional(),\n maxRetries: z.number().int().min(0).max(10).optional(),\n timeout: z.number().int().min(1000).max(7_200_000).optional(),\n enabled: z.boolean().optional(),\n sessionTarget: z.enum(['main', 'isolated']).optional(),\n agentId: patchJobAgentId,\n workingDirectory: patchJobWorkingDirectory,\n payload: CronPayloadSchema.optional(),\n delivery: CronDeliverySchema.optional(),\n model: optionalTrimmedString(100, 1),\n}).refine(\n (data) => Object.keys(data).length > 0,\n { message: 'At least one field must be provided for update' }\n);\n\nexport type ValidatedJobData = z.infer<typeof JobDataSchema>;\nexport type ValidatedAddJobRequest = z.infer<typeof AddJobRequestSchema>;\nexport type ValidatedUpdateJobRequest = z.infer<typeof UpdateJobRequestSchema>;\nexport type ValidatedCronPayload = z.infer<typeof CronPayloadSchema>;\nexport type ValidatedCronDelivery = z.infer<typeof CronDeliverySchema>;\n\n// Re-export common validation helpers\nexport { cronExpression };\n"],"mappings":"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"}
1
+ {"version":3,"file":"validation.js","names":[],"sources":["../../../src/cron/validation.ts"],"sourcesContent":["// Cron input validation using Zod\nimport { z } from 'zod';\nimport nodeCron from 'node-cron';\n\n// Custom cron validation\nconst cronExpression = z.string().superRefine((val, ctx) => {\n if (!nodeCron.validate(val)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Invalid cron expression: ${val}`,\n });\n }\n});\n\n// Valid timezones (subset of IANA timezones)\nconst validTimezones = [\n 'UTC',\n 'America/New_York',\n 'America/Chicago',\n 'America/Denver',\n 'America/Los_Angeles',\n 'America/Toronto',\n 'Europe/London',\n 'Europe/Paris',\n 'Europe/Berlin',\n 'Europe/Moscow',\n 'Asia/Tokyo',\n 'Asia/Shanghai',\n 'Asia/Hong_Kong',\n 'Asia/Singapore',\n 'Asia/Seoul',\n 'Asia/Dubai',\n 'Asia/Mumbai',\n 'Australia/Sydney',\n 'Pacific/Auckland',\n];\n\nconst CronDeliveryMode = z.enum(['none', 'announce', 'direct']);\n\n/** Treat `''` / `null` / whitespace-only as absent so optional fields do not fail `.min(1)` */\nfunction optionalTrimmedString(max: number, min = 1) {\n return z.preprocess((v) => {\n if (v === null || v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? undefined : t;\n }, z.string().min(min).max(max).optional());\n}\n\n/** Optional agent id on create; empty string → undefined. */\nconst optionalJobAgentId = optionalTrimmedString(64, 1);\n\n/** Optional absolute workspace path on create; empty string → undefined. */\nconst optionalJobWorkingDirectory = optionalTrimmedString(4096, 1);\n\n/**\n * PATCH: set string, or `null` / empty to clear `workingDirectory` on the job.\n */\nconst patchJobWorkingDirectory = z.preprocess((v) => {\n if (v === null) return null;\n if (v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? null : t;\n}, z.union([z.string().min(1).max(4096), z.null()]).optional());\n\n/**\n * PATCH: set string, or `null` / empty to clear `agentId` on the job.\n */\nconst patchJobAgentId = z.preprocess((v) => {\n if (v === null) return null;\n if (v === undefined) return undefined;\n if (typeof v !== 'string') return v;\n const t = v.trim();\n return t.length === 0 ? null : t;\n}, z.union([z.string().min(1).max(64), z.null()]).optional());\n\n// CronPayload validation\nconst CronSystemEventPayloadSchema = z.object({\n kind: z.literal('systemEvent'),\n text: z.string().min(1).max(50000),\n});\n\nconst CronAgentTurnPayloadSchema = z.object({\n kind: z.literal('agentTurn'),\n message: z.string().min(1).max(50000),\n model: optionalTrimmedString(100, 1),\n timeoutSeconds: z.number().int().min(10).max(3600).optional(),\n});\n\nconst CronGoalContinuePayloadSchema = z.object({\n kind: z.literal('goalContinue'),\n goalId: z.string().min(1).max(100),\n message: optionalTrimmedString(50000, 1),\n maxRetries: z.number().int().min(0).max(10).optional(),\n});\n\nconst WorkflowRunInputEnvelopeSchema = z.object({\n payload: z.unknown(),\n goal: optionalTrimmedString(5000, 1),\n variables: z.record(z.string(), z.unknown()).optional(),\n context: z.record(z.string(), z.unknown()).optional(),\n});\n\nconst CronWorkflowRunPayloadSchema = z.object({\n kind: z.literal('workflowRun'),\n definitionId: z.string().min(1).max(200),\n input: z.unknown().optional(),\n inputEnvelope: WorkflowRunInputEnvelopeSchema.optional(),\n goal: optionalTrimmedString(5000, 1),\n agentId: optionalTrimmedString(64, 1),\n sessionKey: optionalTrimmedString(300, 1),\n waitForCompletion: z.boolean().optional(),\n source: z.object({\n kind: z.literal('cron').optional(),\n scheduleId: optionalTrimmedString(200, 1),\n fireId: optionalTrimmedString(200, 1),\n scheduledAtMs: z.number().int().nonnegative().optional(),\n }).optional(),\n});\n\nconst CronPayloadSchema = z.union([\n CronSystemEventPayloadSchema,\n CronAgentTurnPayloadSchema,\n CronGoalContinuePayloadSchema,\n CronWorkflowRunPayloadSchema,\n]);\n\n// CronDelivery validation — channel must match gateway UI / message bus ids (telegram, weixin, cli, local, …)\nconst CronDeliverySchema = z.object({\n mode: CronDeliveryMode.default('none'),\n channel: optionalTrimmedString(32, 1),\n to: z.preprocess(\n (v) => (v === '' || v === null || v === undefined ? undefined : v),\n z.string().max(100).optional(),\n ),\n bestEffort: z.boolean().optional(),\n});\n\nexport const JobDataSchema = z\n .object({\n id: z.string().min(1).max(32),\n name: z.string().max(100).optional(),\n schedule: cronExpression,\n enabled: z.boolean(),\n timezone: z.string().superRefine((val, ctx) => {\n if (val && !validTimezones.includes(val)) {\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message: `Invalid timezone: ${val}. Use IANA timezone names.`,\n });\n }\n }).optional(),\n maxRetries: z.number().int().min(0).max(10).default(3),\n timeout: z.number().int().min(1000).max(7_200_000).default(180000),\n created_at: z.string().datetime(),\n updated_at: z.string().datetime(),\n sessionTarget: z.enum(['main', 'isolated']).optional(),\n agentId: optionalTrimmedString(64, 1),\n workingDirectory: optionalJobWorkingDirectory,\n payload: CronPayloadSchema,\n delivery: CronDeliverySchema.optional(),\n model: optionalTrimmedString(100, 1),\n state: z.any().optional(),\n })\n .strict();\n\nexport const AddJobRequestSchema = z.object({\n schedule: cronExpression,\n name: z.string().max(100).optional(),\n timezone: z.string().optional(),\n maxRetries: z.number().int().min(0).max(10).optional(),\n timeout: z.number().int().min(1000).max(7_200_000).optional(),\n sessionTarget: z.enum(['main', 'isolated']).optional(),\n agentId: optionalJobAgentId,\n workingDirectory: optionalJobWorkingDirectory,\n payload: CronPayloadSchema,\n delivery: CronDeliverySchema.optional(),\n model: optionalTrimmedString(100, 1),\n});\n\nexport const UpdateJobRequestSchema = z.object({\n name: z.string().max(100).optional(),\n schedule: cronExpression.optional(),\n timezone: z.string().optional(),\n maxRetries: z.number().int().min(0).max(10).optional(),\n timeout: z.number().int().min(1000).max(7_200_000).optional(),\n enabled: z.boolean().optional(),\n sessionTarget: z.enum(['main', 'isolated']).optional(),\n agentId: patchJobAgentId,\n workingDirectory: patchJobWorkingDirectory,\n payload: CronPayloadSchema.optional(),\n delivery: CronDeliverySchema.optional(),\n model: optionalTrimmedString(100, 1),\n}).refine(\n (data) => Object.keys(data).length > 0,\n { message: 'At least one field must be provided for update' }\n);\n\nexport type ValidatedJobData = z.infer<typeof JobDataSchema>;\nexport type ValidatedAddJobRequest = z.infer<typeof AddJobRequestSchema>;\nexport type ValidatedUpdateJobRequest = z.infer<typeof UpdateJobRequestSchema>;\nexport type ValidatedCronPayload = z.infer<typeof CronPayloadSchema>;\nexport type ValidatedCronDelivery = z.infer<typeof CronDeliverySchema>;\n\n// Re-export common validation helpers\nexport { cronExpression };\n"],"mappings":"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"}
@@ -270,6 +270,20 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
270
270
  maxConsecutiveParseFailures: number;
271
271
  judgeTimeoutMs: number;
272
272
  checklistHistoryChars: number;
273
+ notifications: {
274
+ enabled: boolean;
275
+ includeLinkedSessions: boolean;
276
+ channels: string[];
277
+ events: ("done" | "blocked" | "needs_input" | "queue_failed" | "queue_retry" | "queue_succeeded" | "queue_skipped")[];
278
+ targets: {
279
+ channel: string;
280
+ chatId: string;
281
+ accountId?: string;
282
+ threadId?: string | number;
283
+ silent?: boolean;
284
+ events?: ("done" | "blocked" | "needs_input" | "queue_failed" | "queue_retry" | "queue_succeeded" | "queue_skipped")[];
285
+ }[];
286
+ };
273
287
  judgeModelRef?: string;
274
288
  };
275
289
  session: {
@@ -1,4 +1,4 @@
1
1
  import type { Hono } from 'hono';
2
2
  import type { AuthenticatedRouteDeps } from './deps.js';
3
- /** Webchat persistent `/goal` REST API. */
3
+ /** First-class Goal API. Sessions are execution context; goals are durable product objects. */
4
4
  export declare function registerGoalsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void;