@xopcai/xopc 0.0.88 → 0.0.90

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 (275) hide show
  1. package/README.md +8 -1
  2. package/README.zh-CN.md +8 -1
  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/agents-cPvvYLXo.js +222 -0
  6. package/dist/gateway/static/root/assets/apps-page-Bk1_P5FJ.js +1 -0
  7. package/dist/gateway/static/root/assets/channels-settings-CZoeQwHz.js +1 -0
  8. package/dist/gateway/static/root/assets/{channels-status-swr-DIsl75Y3.js → channels-status-swr-BrtH2VzC.js} +1 -1
  9. package/dist/gateway/static/root/assets/circle-check-C23XjkUj.js +1 -0
  10. package/dist/gateway/static/root/assets/cron-api-CyqbgfHM.js +1 -0
  11. package/dist/gateway/static/root/assets/cron-dreaming-jobs-Ip703-qM.js +2 -0
  12. package/dist/gateway/static/root/assets/cron-page-BpLdiQN8.js +1 -0
  13. package/dist/gateway/static/root/assets/dist-BpAiK86n.js +1 -0
  14. package/dist/gateway/static/root/assets/{extension-debug-page-BVJohZoZ.js → extension-debug-page-D6Ak0STa.js} +1 -1
  15. package/dist/gateway/static/root/assets/{extension-page-BT2tmElC.js → extension-page-Q0P3d6DW.js} +1 -1
  16. package/dist/gateway/static/root/assets/{extension-settings-page-BSS47c2j.js → extension-settings-page-CL55LwU_.js} +1 -1
  17. package/dist/gateway/static/root/assets/eye-DAfL1U7M.js +1 -0
  18. package/dist/gateway/static/root/assets/{fetch-BaFNUtkE.js → fetch-Dqa9iTWl.js} +1 -1
  19. package/dist/gateway/static/root/assets/{field-primitives-QwYEq6Hz.js → field-primitives-HUR6JElP.js} +1 -1
  20. package/dist/gateway/static/root/assets/{heartbeat-config-api-BVSidEDJ.js → heartbeat-config-api-DusckjUX.js} +1 -1
  21. package/dist/gateway/static/root/assets/{index-qNrVJp-y.js → index-BYcGfwcE.js} +97 -97
  22. package/dist/gateway/static/root/assets/index-V7MQ7834.css +1 -0
  23. package/dist/gateway/static/root/assets/{logs-page-DDonPVLn.js → logs-page-_HcZ2fgK.js} +1 -1
  24. package/dist/gateway/static/root/assets/sessions-page-iezSMjho.js +1 -0
  25. package/dist/gateway/static/root/assets/{settings-form-section-B8N3A3Zo.js → settings-form-section-a0qGVOlr.js} +1 -1
  26. package/dist/gateway/static/root/assets/settings-page-C9_nYQwM.js +3 -0
  27. package/dist/gateway/static/root/assets/{share-preview-page-Q7KqkO-u.js → share-preview-page-DExl7CJy.js} +1 -1
  28. package/dist/gateway/static/root/assets/skills-page-BlgGD93t.js +2 -0
  29. package/dist/gateway/static/root/assets/{theme-store-BbRc5ugR.js → theme-store-C0Ehmdo5.js} +1 -1
  30. package/dist/gateway/static/root/assets/url-fxyYANfA.js +3 -0
  31. package/dist/gateway/static/root/assets/{utils-CxDGduqK.js → utils-DRQryzdn.js} +1 -1
  32. package/dist/gateway/static/root/assets/voice-api-key-field-D0viACE2.js +1 -0
  33. package/dist/gateway/static/root/assets/workflow-page.utils-DnG8JBhV.js +1 -0
  34. package/dist/gateway/static/root/assets/workflows-page-BvMobnJP.js +27 -0
  35. package/dist/gateway/static/root/index.html +7 -6
  36. package/dist/package.js +1 -1
  37. package/dist/src/agent/agent-manager.d.ts +2 -0
  38. package/dist/src/agent/agent-manager.js +1 -0
  39. package/dist/src/agent/agent-manager.js.map +1 -1
  40. package/dist/src/agent/service.js +2 -1
  41. package/dist/src/agent/service.js.map +1 -1
  42. package/dist/src/agent/service.types.d.ts +3 -1
  43. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +20 -18
  44. package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
  45. package/dist/src/agent/tools/cronjob-tool.d.ts +6 -0
  46. package/dist/src/agent/tools/cronjob-tool.js +76 -10
  47. package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
  48. package/dist/src/agent/tools/edit.d.ts +5 -1
  49. package/dist/src/agent/tools/edit.js +7 -5
  50. package/dist/src/agent/tools/edit.js.map +1 -1
  51. package/dist/src/agent/tools/factory.d.ts +3 -0
  52. package/dist/src/agent/tools/factory.js +4 -25
  53. package/dist/src/agent/tools/factory.js.map +1 -1
  54. package/dist/src/agent/tools/workflow-tool.d.ts +6 -28
  55. package/dist/src/agent/tools/workflow-tool.js +60 -260
  56. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  57. package/dist/src/agent/tools/write.d.ts +5 -1
  58. package/dist/src/agent/tools/write.js +7 -5
  59. package/dist/src/agent/tools/write.js.map +1 -1
  60. package/dist/src/agent/workflow/agent-progress.js +2 -0
  61. package/dist/src/agent/workflow/agent-progress.js.map +1 -1
  62. package/dist/src/agent/workflow/builtins/client-proposal.d.ts +12 -0
  63. package/dist/src/agent/workflow/builtins/client-proposal.js +155 -0
  64. package/dist/src/agent/workflow/builtins/client-proposal.js.map +1 -0
  65. package/dist/src/agent/workflow/builtins/competitor-scan.d.ts +12 -0
  66. package/dist/src/agent/workflow/builtins/competitor-scan.js +150 -0
  67. package/dist/src/agent/workflow/builtins/competitor-scan.js.map +1 -0
  68. package/dist/src/agent/workflow/builtins/content-draft.d.ts +13 -0
  69. package/dist/src/agent/workflow/builtins/content-draft.js +146 -0
  70. package/dist/src/agent/workflow/builtins/content-draft.js.map +1 -0
  71. package/dist/src/agent/workflow/builtins/content-repurpose.d.ts +11 -0
  72. package/dist/src/agent/workflow/builtins/content-repurpose.js +137 -0
  73. package/dist/src/agent/workflow/builtins/content-repurpose.js.map +1 -0
  74. package/dist/src/agent/workflow/builtins/decision-compare.d.ts +13 -0
  75. package/dist/src/agent/workflow/builtins/decision-compare.js +173 -0
  76. package/dist/src/agent/workflow/builtins/decision-compare.js.map +1 -0
  77. package/dist/src/agent/workflow/builtins/inbox-triage.d.ts +11 -0
  78. package/dist/src/agent/workflow/builtins/inbox-triage.js +148 -0
  79. package/dist/src/agent/workflow/builtins/inbox-triage.js.map +1 -0
  80. package/dist/src/agent/workflow/builtins/index.d.ts +10 -1
  81. package/dist/src/agent/workflow/builtins/index.js +46 -1
  82. package/dist/src/agent/workflow/builtins/index.js.map +1 -1
  83. package/dist/src/agent/workflow/builtins/meeting-prep.d.ts +12 -0
  84. package/dist/src/agent/workflow/builtins/meeting-prep.js +144 -0
  85. package/dist/src/agent/workflow/builtins/meeting-prep.js.map +1 -0
  86. package/dist/src/agent/workflow/builtins/offer-design.d.ts +12 -0
  87. package/dist/src/agent/workflow/builtins/offer-design.js +161 -0
  88. package/dist/src/agent/workflow/builtins/offer-design.js.map +1 -0
  89. package/dist/src/agent/workflow/builtins/weekly-review.d.ts +12 -0
  90. package/dist/src/agent/workflow/builtins/weekly-review.js +131 -0
  91. package/dist/src/agent/workflow/builtins/weekly-review.js.map +1 -0
  92. package/dist/src/agent/workflow/step-labels.js +2 -2
  93. package/dist/src/agent/workflow/step-labels.js.map +1 -1
  94. package/dist/src/agent/workflow/subagent-runner.js +3 -1
  95. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  96. package/dist/src/agent/workflow/types.d.ts +4 -0
  97. package/dist/src/agent/workflow/workflow-child-tools.d.ts +4 -0
  98. package/dist/src/agent/workflow/workflow-child-tools.js +21 -0
  99. package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -0
  100. package/dist/src/auth/credentials.d.ts +14 -2
  101. package/dist/src/auth/credentials.js +38 -13
  102. package/dist/src/auth/credentials.js.map +1 -1
  103. package/dist/src/auth/oauth/types.d.ts +16 -0
  104. package/dist/src/chat-commands/agent-edit.d.ts +4 -0
  105. package/dist/src/chat-commands/agent-edit.js +136 -0
  106. package/dist/src/chat-commands/agent-edit.js.map +1 -0
  107. package/dist/src/chat-commands/index.d.ts +1 -0
  108. package/dist/src/chat-commands/index.js +3 -1
  109. package/dist/src/chat-commands/index.js.map +1 -1
  110. package/dist/src/cli/bin.js +2 -0
  111. package/dist/src/cli/bin.js.map +1 -1
  112. package/dist/src/cli/commands/auth.js +6 -0
  113. package/dist/src/cli/commands/auth.js.map +1 -1
  114. package/dist/src/cli/commands/cron.js +42 -3
  115. package/dist/src/cli/commands/cron.js.map +1 -1
  116. package/dist/src/cli/commands/doctor/checks/session-integrity.js +79 -56
  117. package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
  118. package/dist/src/cli/commands/onboard/model.js +6 -0
  119. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  120. package/dist/src/cli/commands/update.js +86 -79
  121. package/dist/src/cli/commands/update.js.map +1 -1
  122. package/dist/src/commands/agents.config.d.ts +3 -2
  123. package/dist/src/commands/agents.config.js +5 -2
  124. package/dist/src/commands/agents.config.js.map +1 -1
  125. package/dist/src/config/agent-typed-models.d.ts +2 -7
  126. package/dist/src/config/agent-typed-models.js +3 -14
  127. package/dist/src/config/agent-typed-models.js.map +1 -1
  128. package/dist/src/config/localized-text.d.ts +6 -0
  129. package/dist/src/config/localized-text.js +42 -0
  130. package/dist/src/config/localized-text.js.map +1 -0
  131. package/dist/src/config/models-json.d.ts +6 -6
  132. package/dist/src/config/schema.d.ts +6 -21
  133. package/dist/src/config/schema.js +4 -4
  134. package/dist/src/config/schema.js.map +1 -1
  135. package/dist/src/cron/executor.d.ts +4 -0
  136. package/dist/src/cron/executor.js +169 -5
  137. package/dist/src/cron/executor.js.map +1 -1
  138. package/dist/src/cron/job-content.js +2 -1
  139. package/dist/src/cron/job-content.js.map +1 -1
  140. package/dist/src/cron/types.d.ts +28 -1
  141. package/dist/src/cron/validation.d.ts +80 -0
  142. package/dist/src/cron/validation.js +30 -4
  143. package/dist/src/cron/validation.js.map +1 -1
  144. package/dist/src/cron/workflow-run-completion.d.ts +23 -0
  145. package/dist/src/cron/workflow-run-completion.js +72 -0
  146. package/dist/src/cron/workflow-run-completion.js.map +1 -0
  147. package/dist/src/extensions/update.d.ts +51 -0
  148. package/dist/src/extensions/update.js +260 -0
  149. package/dist/src/extensions/update.js.map +1 -0
  150. package/dist/src/gateway/agents-admin.d.ts +15 -8
  151. package/dist/src/gateway/agents-admin.js +77 -28
  152. package/dist/src/gateway/agents-admin.js.map +1 -1
  153. package/dist/src/gateway/gateway-workflow-host.types.d.ts +17 -0
  154. package/dist/src/gateway/gateway-workflow-host.types.js +1 -0
  155. package/dist/src/gateway/heartbeat/service.js +1 -1
  156. package/dist/src/gateway/hono/lib/config-payload.d.ts +5 -0
  157. package/dist/src/gateway/hono/lib/config-payload.js +2 -1
  158. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  159. package/dist/src/gateway/hono/middleware/auth.d.ts +2 -0
  160. package/dist/src/gateway/hono/middleware/auth.js +12 -7
  161. package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
  162. package/dist/src/gateway/hono/oauth-async.js +40 -15
  163. package/dist/src/gateway/hono/oauth-async.js.map +1 -1
  164. package/dist/src/gateway/hono/oauth.js +31 -6
  165. package/dist/src/gateway/hono/oauth.js.map +1 -1
  166. package/dist/src/gateway/hono/routes/agents.js +55 -12
  167. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  168. package/dist/src/gateway/hono/routes/config-patch/agents.js +1 -1
  169. package/dist/src/gateway/hono/routes/models.js +11 -5
  170. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  171. package/dist/src/gateway/hono/routes/update.js +55 -107
  172. package/dist/src/gateway/hono/routes/update.js.map +1 -1
  173. package/dist/src/gateway/hono/routes/workflows.js +72 -191
  174. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  175. package/dist/src/gateway/server.js +2 -0
  176. package/dist/src/gateway/server.js.map +1 -1
  177. package/dist/src/gateway/service.d.ts +5 -0
  178. package/dist/src/gateway/service.js +24 -3
  179. package/dist/src/gateway/service.js.map +1 -1
  180. package/dist/src/heartbeat/index.js +1 -1
  181. package/dist/src/infra/brew.d.ts +4 -0
  182. package/dist/src/infra/brew.js +20 -0
  183. package/dist/src/infra/brew.js.map +1 -0
  184. package/dist/src/infra/package-json.d.ts +2 -0
  185. package/dist/src/infra/package-json.js +23 -0
  186. package/dist/src/infra/package-json.js.map +1 -0
  187. package/dist/src/infra/package-update-steps.d.ts +35 -0
  188. package/dist/src/infra/package-update-steps.js +304 -0
  189. package/dist/src/infra/package-update-steps.js.map +1 -0
  190. package/dist/src/infra/path-env.d.ts +11 -0
  191. package/dist/src/infra/path-env.js +90 -0
  192. package/dist/src/infra/path-env.js.map +1 -0
  193. package/dist/src/infra/path-prepend.d.ts +7 -0
  194. package/dist/src/infra/path-prepend.js +44 -0
  195. package/dist/src/infra/path-prepend.js.map +1 -0
  196. package/dist/src/infra/stable-node-path.d.ts +2 -0
  197. package/dist/src/infra/stable-node-path.js +28 -0
  198. package/dist/src/infra/stable-node-path.js.map +1 -0
  199. package/dist/src/infra/update-global.d.ts +30 -23
  200. package/dist/src/infra/update-global.js +113 -64
  201. package/dist/src/infra/update-global.js.map +1 -1
  202. package/dist/src/infra/update-log.d.ts +1 -0
  203. package/dist/src/infra/update-log.js +12 -0
  204. package/dist/src/infra/update-log.js.map +1 -0
  205. package/dist/src/infra/update-restart.d.ts +20 -0
  206. package/dist/src/infra/update-restart.js +165 -0
  207. package/dist/src/infra/update-restart.js.map +1 -0
  208. package/dist/src/infra/update-runner.d.ts +89 -1
  209. package/dist/src/infra/update-runner.js +604 -173
  210. package/dist/src/infra/update-runner.js.map +1 -1
  211. package/dist/src/infra/update-startup.d.ts +3 -0
  212. package/dist/src/infra/update-startup.js +8 -4
  213. package/dist/src/infra/update-startup.js.map +1 -1
  214. package/dist/src/providers/index.d.ts +8 -0
  215. package/dist/src/providers/index.js +51 -12
  216. package/dist/src/providers/index.js.map +1 -1
  217. package/dist/src/routing/resolve-route.d.ts +3 -1
  218. package/dist/src/routing/resolve-route.js.map +1 -1
  219. package/dist/src/session/store.d.ts +5 -3
  220. package/dist/src/session/store.js +66 -20
  221. package/dist/src/session/store.js.map +1 -1
  222. package/dist/src/share/site-share-config.d.ts +3 -2
  223. package/dist/src/share/site-share-config.js.map +1 -1
  224. package/dist/src/utils/logger/stats.d.ts +1 -1
  225. package/dist/src/workflows/domain/command.d.ts +2 -1
  226. package/dist/src/workflows/domain/definition-utils.d.ts +14 -0
  227. package/dist/src/workflows/domain/definition-utils.js +50 -0
  228. package/dist/src/workflows/domain/definition-utils.js.map +1 -0
  229. package/dist/src/workflows/domain/event.d.ts +3 -0
  230. package/dist/src/workflows/domain/index.d.ts +2 -0
  231. package/dist/src/workflows/domain/index.js +3 -1
  232. package/dist/src/workflows/domain/run.d.ts +60 -0
  233. package/dist/src/workflows/domain/run.js.map +1 -1
  234. package/dist/src/workflows/domain/validation.d.ts +19 -0
  235. package/dist/src/workflows/domain/validation.js +66 -0
  236. package/dist/src/workflows/domain/validation.js.map +1 -0
  237. package/dist/src/workflows/engine/projector.js +17 -0
  238. package/dist/src/workflows/engine/projector.js.map +1 -1
  239. package/dist/src/workflows/engine/workflow-engine.d.ts +2 -1
  240. package/dist/src/workflows/engine/workflow-engine.js +128 -0
  241. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  242. package/dist/src/workflows/index.d.ts +4 -0
  243. package/dist/src/workflows/index.js +9 -2
  244. package/dist/src/workflows/service/run-view-to-snapshot.d.ts +4 -0
  245. package/dist/src/workflows/service/run-view-to-snapshot.js +63 -0
  246. package/dist/src/workflows/service/run-view-to-snapshot.js.map +1 -0
  247. package/dist/src/workflows/service/workflow-run-service.d.ts +37 -0
  248. package/dist/src/workflows/service/workflow-run-service.js +282 -0
  249. package/dist/src/workflows/service/workflow-run-service.js.map +1 -0
  250. package/dist/src/workflows/service/workflow-run-service.types.d.ts +47 -0
  251. package/dist/src/workflows/service/workflow-run-service.types.js +1 -0
  252. package/dist/src/workflows/service/workflow-session-bridge.d.ts +29 -0
  253. package/dist/src/workflows/service/workflow-session-bridge.js +177 -0
  254. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -0
  255. package/dist/src/workflows/service/workflow-session-key.d.ts +3 -0
  256. package/dist/src/workflows/service/workflow-session-key.js +21 -0
  257. package/dist/src/workflows/service/workflow-session-key.js.map +1 -0
  258. package/dist/src/workflows/store/run-store.js +1 -0
  259. package/dist/src/workflows/store/run-store.js.map +1 -1
  260. package/package.json +1 -1
  261. package/dist/gateway/static/root/assets/agents-CRxETUZx.js +0 -222
  262. package/dist/gateway/static/root/assets/apps-page-wKWf3l57.js +0 -1
  263. package/dist/gateway/static/root/assets/channels-settings-DDbqVNkx.js +0 -1
  264. package/dist/gateway/static/root/assets/copy-SxMW6Xpc.js +0 -1
  265. package/dist/gateway/static/root/assets/cron-api-N9hvuRrn.js +0 -1
  266. package/dist/gateway/static/root/assets/cron-dreaming-jobs-DueM3rBz.js +0 -2
  267. package/dist/gateway/static/root/assets/cron-page-tlNGNxhP.js +0 -1
  268. package/dist/gateway/static/root/assets/dist-CJwfHYvT.js +0 -1
  269. package/dist/gateway/static/root/assets/index-CqZzHNEg.css +0 -1
  270. package/dist/gateway/static/root/assets/sessions-page-DKt-Wmib.js +0 -1
  271. package/dist/gateway/static/root/assets/settings-page-DcJjvvw4.js +0 -3
  272. package/dist/gateway/static/root/assets/skills-page-DuJ4BTO3.js +0 -2
  273. package/dist/gateway/static/root/assets/url-D6jvVYIA.js +0 -7
  274. package/dist/gateway/static/root/assets/voice-api-key-field-CTyHz7L_.js +0 -1
  275. package/dist/gateway/static/root/assets/workflows-page-GacJ41Fv.js +0 -27
@@ -2,10 +2,11 @@ import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { init_agent_scope, normalizeAgentId } from "../agent/agent-scope.js";
4
4
  import { buildSessionKey, init_session_key } from "../routing/session-key.js";
5
+ import { getCronPayloadText } from "./job-content.js";
6
+ import { buildWorkflowRunCronSummary, buildWorkflowRunDeliveryText, isWorkflowRunCronSuccess, resolveWorkflowCronWaitMs, waitForWorkflowRunView } from "./workflow-run-completion.js";
5
7
  import { bundledChannelPlugins } from "../generated/bundled-channel-plugins.js";
6
8
  import { shouldSilence, stripHeartbeatToken } from "../heartbeat/tokens.js";
7
9
  import { getChannelPlugin, listChannelPlugins, syncChannelPluginsFromManager } from "../channels/plugins/registry.js";
8
- import { getCronPayloadText } from "./job-content.js";
9
10
  //#region src/cron/executor.ts
10
11
  init_logger();
11
12
  init_agent_scope();
@@ -39,6 +40,7 @@ var DefaultJobExecutor = class {
39
40
  sessionStore;
40
41
  runLogStore = null;
41
42
  getDefaultCronAgentId = null;
43
+ workflowRunService = null;
42
44
  setRunLogStore(store) {
43
45
  this.runLogStore = store;
44
46
  }
@@ -48,6 +50,7 @@ var DefaultJobExecutor = class {
48
50
  this.heartbeatService = deps.heartbeatService ?? null;
49
51
  if (deps.sessionStore !== void 0) this.sessionStore = deps.sessionStore;
50
52
  this.getDefaultCronAgentId = deps.getDefaultCronAgentId ?? null;
53
+ this.workflowRunService = deps.workflowRunService ?? null;
51
54
  }
52
55
  async buildCronOutboundMessage(channel, to, content) {
53
56
  if (listChannelPlugins().length === 0) syncChannelPluginsFromManager(bundledChannelPlugins);
@@ -103,6 +106,7 @@ var DefaultJobExecutor = class {
103
106
  execution.sessionKey = result.sessionKey;
104
107
  execution.sessionType = result.sessionType;
105
108
  execution.model = result.model;
109
+ execution.workflowRunId = result.workflowRunId;
106
110
  if (result.status === "ok") log.info({
107
111
  jobId: job.id,
108
112
  executionId,
@@ -155,11 +159,12 @@ var DefaultJobExecutor = class {
155
159
  status: "skipped",
156
160
  error: "Job was aborted before execution"
157
161
  };
158
- if (!this.agentService || !this.messageBus) {
159
- log.warn({ jobId: job.id }, "No agent service configured, using basic execution");
160
- return this.basicExecute(job, signal, timeout);
161
- }
162
162
  try {
163
+ if (job.payload.kind === "workflowRun") return await this.executeWorkflowRun(job, signal);
164
+ if (!this.agentService || !this.messageBus) {
165
+ log.warn({ jobId: job.id }, "No agent service configured, using basic execution");
166
+ return this.basicExecute(job, signal, timeout);
167
+ }
163
168
  if (sessionTarget === "main") return await this.executeMainSession(job, signal, timeout);
164
169
  else return await this.executeIsolated(job, signal, timeout);
165
170
  } catch (error) {
@@ -169,6 +174,165 @@ var DefaultJobExecutor = class {
169
174
  };
170
175
  }
171
176
  }
177
+ async executeWorkflowRun(job, signal) {
178
+ if (signal.aborted) return {
179
+ status: "skipped",
180
+ error: "Job was aborted before workflow run start"
181
+ };
182
+ if (job.payload.kind !== "workflowRun") return {
183
+ status: "error",
184
+ error: "Cron job payload is not workflowRun"
185
+ };
186
+ if (!this.workflowRunService) return {
187
+ status: "error",
188
+ error: "Workflow run service is not configured for cron"
189
+ };
190
+ const fallbackAgentId = this.getDefaultCronAgentId?.() ?? "main";
191
+ const agentId = normalizeAgentId(job.payload.agentId || job.agentId || fallbackAgentId);
192
+ const fireId = job.payload.source?.fireId || crypto.randomUUID();
193
+ const source = {
194
+ kind: "cron",
195
+ scheduleId: job.payload.source?.scheduleId || job.id,
196
+ fireId,
197
+ scheduledAtMs: job.payload.source?.scheduledAtMs ?? Date.now()
198
+ };
199
+ const result = await this.workflowRunService.startWorkflowRun({
200
+ agentId,
201
+ definitionId: job.payload.definitionId,
202
+ input: job.payload.input,
203
+ inputEnvelope: job.payload.inputEnvelope,
204
+ goal: job.payload.goal,
205
+ source,
206
+ idempotencyKey: `cron:${job.id}:${fireId}`
207
+ });
208
+ if (result.ok === false) return {
209
+ status: "error",
210
+ error: result.message
211
+ };
212
+ log.info({
213
+ jobId: job.id,
214
+ workflowRunId: result.runId,
215
+ definitionId: job.payload.definitionId,
216
+ sessionKey: result.sessionKey
217
+ }, "Workflow run started from cron");
218
+ if (!(job.payload.waitForCompletion !== false) || !this.workflowRunService.readWorkflowRunView) return {
219
+ status: "ok",
220
+ summary: `Started workflow run ${result.runId}`,
221
+ sessionId: result.sessionKey,
222
+ sessionKey: result.sessionKey,
223
+ sessionType: "workflow",
224
+ workflowRunId: result.runId
225
+ };
226
+ return this.waitForWorkflowRunOutcome({
227
+ job,
228
+ agentId,
229
+ sessionKey: result.sessionKey,
230
+ initialRunId: result.runId,
231
+ signal
232
+ });
233
+ }
234
+ async waitForWorkflowRunOutcome(params) {
235
+ const waitMs = resolveWorkflowCronWaitMs(params.job.timeout);
236
+ const maxWorkflowRetries = Math.max(0, params.job.maxRetries ?? 0);
237
+ let runId = params.initialRunId;
238
+ let attempt = 0;
239
+ while (attempt <= maxWorkflowRetries) {
240
+ const waitResult = await waitForWorkflowRunView({
241
+ readView: (id) => this.workflowRunService.readWorkflowRunView(params.agentId, id),
242
+ runId,
243
+ signal: params.signal,
244
+ timeoutMs: waitMs
245
+ });
246
+ if (waitResult.kind === "aborted") return {
247
+ status: "skipped",
248
+ error: "Job was aborted while waiting for workflow run"
249
+ };
250
+ if (waitResult.kind === "timeout") return {
251
+ status: "error",
252
+ error: `Workflow run ${runId} did not finish within ${waitMs}ms`,
253
+ summary: waitResult.lastView ? buildWorkflowRunCronSummary(waitResult.lastView) : void 0,
254
+ sessionId: params.sessionKey,
255
+ sessionKey: params.sessionKey,
256
+ sessionType: "workflow",
257
+ workflowRunId: runId
258
+ };
259
+ const view = waitResult.view;
260
+ const summary = buildWorkflowRunCronSummary(view);
261
+ if (isWorkflowRunCronSuccess(view)) {
262
+ const baseOutcome = {
263
+ status: "ok",
264
+ summary,
265
+ sessionId: params.sessionKey,
266
+ sessionKey: params.sessionKey,
267
+ sessionType: "workflow",
268
+ workflowRunId: runId
269
+ };
270
+ await this.deliverWorkflowRunOutcome(params.job, view, baseOutcome);
271
+ return baseOutcome;
272
+ }
273
+ if (!(attempt < maxWorkflowRetries && view.run.status === "failed" && Boolean(this.workflowRunService?.retryWorkflowRun))) return {
274
+ status: "error",
275
+ summary,
276
+ error: summary,
277
+ sessionId: params.sessionKey,
278
+ sessionKey: params.sessionKey,
279
+ sessionType: "workflow",
280
+ workflowRunId: runId
281
+ };
282
+ const retryResult = await this.workflowRunService.retryWorkflowRun({
283
+ agentId: params.agentId,
284
+ runId
285
+ });
286
+ if (retryResult.ok === false) return {
287
+ status: "error",
288
+ error: retryResult.message,
289
+ summary,
290
+ sessionId: params.sessionKey,
291
+ sessionKey: params.sessionKey,
292
+ sessionType: "workflow",
293
+ workflowRunId: runId
294
+ };
295
+ runId = retryResult.runId;
296
+ attempt += 1;
297
+ log.info({
298
+ jobId: params.job.id,
299
+ attempt,
300
+ workflowRunId: runId
301
+ }, "Retrying failed workflow run from cron");
302
+ }
303
+ return {
304
+ status: "error",
305
+ error: "Workflow run retries exhausted",
306
+ sessionId: params.sessionKey,
307
+ sessionKey: params.sessionKey,
308
+ sessionType: "workflow",
309
+ workflowRunId: runId
310
+ };
311
+ }
312
+ async deliverWorkflowRunOutcome(job, view, outcome) {
313
+ if (!this.messageBus) return;
314
+ const delivery = job.delivery;
315
+ if (!delivery || delivery.mode === "none" || delivery.channel === "local" || !delivery.to?.trim()) return;
316
+ try {
317
+ const text = buildWorkflowRunDeliveryText(view);
318
+ const outbound = await this.buildCronOutboundMessage(delivery.channel, delivery.to, text);
319
+ await this.messageBus.publishOutbound(outbound);
320
+ log.info({
321
+ jobId: job.id,
322
+ channel: delivery.channel,
323
+ to: outbound.chat_id,
324
+ workflowRunId: view.run.id
325
+ }, "Delivered workflow run result from cron");
326
+ } catch (err) {
327
+ const em = err instanceof Error ? err.message : String(err);
328
+ log.warn({
329
+ jobId: job.id,
330
+ err,
331
+ workflowRunId: view.run.id
332
+ }, `Workflow cron delivery failed: ${em}`);
333
+ if (outcome.status === "ok") outcome.summary = `${outcome.summary ?? ""} (delivery failed: ${em})`.trim();
334
+ }
335
+ }
172
336
  /**
173
337
  * Execute in main session - sends system event
174
338
  */
@@ -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 {\n CronRunOutcome,\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 syncChannelPluginsFromManager,\n} from '../channels/plugins/registry.js';\nimport { bundledChannelPlugins } from '../generated/bundled-channel-plugins.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';\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\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 }\n\n private async buildCronOutboundMessage(\n channel: string,\n to: string,\n content: string,\n ): Promise<OutboundMessage> {\n if (listChannelPlugins().length === 0) {\n syncChannelPluginsFromManager(bundledChannelPlugins);\n }\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\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, error: result.error },\n 'Job failed'\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 { jobId: job.id, executionId, error: execution.error },\n 'Job 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 // 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 try {\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 /**\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 if (listChannelPlugins().length === 0) {\n syncChannelPluginsFromManager(bundledChannelPlugins);\n }\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 syncChannelPluginsFromManager,\n} from '../channels/plugins/registry.js';\nimport { bundledChannelPlugins } from '../generated/bundled-channel-plugins.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 if (listChannelPlugins().length === 0) {\n syncChannelPluginsFromManager(bundledChannelPlugins);\n }\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, error: result.error },\n 'Job failed'\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 { jobId: job.id, executionId, error: execution.error },\n 'Job 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 if (listChannelPlugins().length === 0) {\n syncChannelPluginsFromManager(bundledChannelPlugins);\n }\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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"}
@@ -5,7 +5,8 @@
5
5
  function getCronPayloadText(job) {
6
6
  const p = job.payload;
7
7
  if (p.kind === "systemEvent") return p.text;
8
- return p.message;
8
+ if (p.kind === "agentTurn") return p.message;
9
+ return p.goal || p.definitionId;
9
10
  }
10
11
  //#endregion
11
12
  export { getCronPayloadText };
@@ -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 return p.message;\n}\n"],"mappings":";;;;AAKA,SAAgB,mBAAmB,KAAuC;CACxE,MAAM,IAAI,IAAI;AACd,KAAI,EAAE,SAAS,cAAe,QAAO,EAAE;AACvC,QAAO,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 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,4 +1,6 @@
1
1
  import type { SessionStore } from '../session/store.js';
2
+ import type { WorkflowRunInputEnvelope, WorkflowRunSource, WorkflowRunView } from '../workflows/domain/index.js';
3
+ import type { StartWorkflowRunServiceParams, WorkflowRunServiceResult } from '../workflows/service/workflow-run-service.types.js';
2
4
  export type CronDeliveryMode = 'none' | 'announce' | 'direct';
3
5
  export interface CronDelivery {
4
6
  mode: CronDeliveryMode;
@@ -14,7 +16,21 @@ export type CronPayload = {
14
16
  message: string;
15
17
  model?: string;
16
18
  timeoutSeconds?: number;
17
- };
19
+ } | CronWorkflowRunPayload;
20
+ export interface CronWorkflowRunPayload {
21
+ kind: 'workflowRun';
22
+ definitionId: string;
23
+ input?: unknown;
24
+ inputEnvelope?: WorkflowRunInputEnvelope;
25
+ goal?: string;
26
+ agentId?: string;
27
+ sessionKey?: string;
28
+ /** When true (default), cron waits for terminal workflow status before marking the job result. */
29
+ waitForCompletion?: boolean;
30
+ source?: Partial<Extract<WorkflowRunSource, {
31
+ kind: 'cron';
32
+ }>>;
33
+ }
18
34
  export type CronSessionTarget = 'main' | 'isolated';
19
35
  export interface JobData {
20
36
  id: string;
@@ -67,6 +83,7 @@ export interface JobExecution {
67
83
  model?: string;
68
84
  provider?: string;
69
85
  usage?: CronUsageSummary;
86
+ workflowRunId?: string;
70
87
  }
71
88
  export interface CronUsageSummary {
72
89
  input_tokens?: number;
@@ -88,6 +105,15 @@ export interface CronRunOutcome {
88
105
  model?: string;
89
106
  provider?: string;
90
107
  usage?: CronUsageSummary;
108
+ workflowRunId?: string;
109
+ }
110
+ export interface CronWorkflowRunStarter {
111
+ startWorkflowRun(params: StartWorkflowRunServiceParams): Promise<WorkflowRunServiceResult>;
112
+ readWorkflowRunView?(agentId: string, runId: string): Promise<WorkflowRunView | null>;
113
+ retryWorkflowRun?(params: {
114
+ agentId: string;
115
+ runId: string;
116
+ }): Promise<WorkflowRunServiceResult>;
91
117
  }
92
118
  /** Optional hook after a successful cron run (e.g. wake gateway heartbeat). */
93
119
  export interface HeartbeatWakeSink {
@@ -106,6 +132,7 @@ export interface JobExecutorDeps {
106
132
  * (same as {@link JobData.agentId} set to the default agent). Typically `getDefaultAgentId(config)`.
107
133
  */
108
134
  getDefaultCronAgentId?: () => string;
135
+ workflowRunService?: CronWorkflowRunStarter;
109
136
  }
110
137
  export interface JobExecutor {
111
138
  execute(job: JobData, signal: AbortSignal, deps?: JobExecutorDeps): Promise<void>;
@@ -8,6 +8,26 @@ 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<"workflowRun">;
13
+ definitionId: z.ZodString;
14
+ input: z.ZodOptional<z.ZodUnknown>;
15
+ inputEnvelope: z.ZodOptional<z.ZodObject<{
16
+ payload: z.ZodUnknown;
17
+ goal: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
18
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
19
+ context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
20
+ }, z.core.$strip>>;
21
+ goal: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
22
+ agentId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
23
+ sessionKey: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
24
+ waitForCompletion: z.ZodOptional<z.ZodBoolean>;
25
+ source: z.ZodOptional<z.ZodObject<{
26
+ kind: z.ZodOptional<z.ZodLiteral<"cron">>;
27
+ scheduleId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
28
+ fireId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
29
+ scheduledAtMs: z.ZodOptional<z.ZodNumber>;
30
+ }, z.core.$strip>>;
11
31
  }, z.core.$strip>]>;
12
32
  declare const CronDeliverySchema: z.ZodObject<{
13
33
  mode: z.ZodDefault<z.ZodEnum<{
@@ -43,6 +63,26 @@ export declare const JobDataSchema: z.ZodObject<{
43
63
  message: z.ZodString;
44
64
  model: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
45
65
  timeoutSeconds: z.ZodOptional<z.ZodNumber>;
66
+ }, z.core.$strip>, z.ZodObject<{
67
+ kind: z.ZodLiteral<"workflowRun">;
68
+ definitionId: z.ZodString;
69
+ input: z.ZodOptional<z.ZodUnknown>;
70
+ inputEnvelope: z.ZodOptional<z.ZodObject<{
71
+ payload: z.ZodUnknown;
72
+ goal: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
73
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
74
+ context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
75
+ }, z.core.$strip>>;
76
+ goal: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
77
+ agentId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
78
+ sessionKey: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
79
+ waitForCompletion: z.ZodOptional<z.ZodBoolean>;
80
+ source: z.ZodOptional<z.ZodObject<{
81
+ kind: z.ZodOptional<z.ZodLiteral<"cron">>;
82
+ scheduleId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
83
+ fireId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
84
+ scheduledAtMs: z.ZodOptional<z.ZodNumber>;
85
+ }, z.core.$strip>>;
46
86
  }, z.core.$strip>]>;
47
87
  delivery: z.ZodOptional<z.ZodObject<{
48
88
  mode: z.ZodDefault<z.ZodEnum<{
@@ -77,6 +117,26 @@ export declare const AddJobRequestSchema: z.ZodObject<{
77
117
  message: z.ZodString;
78
118
  model: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
79
119
  timeoutSeconds: z.ZodOptional<z.ZodNumber>;
120
+ }, z.core.$strip>, z.ZodObject<{
121
+ kind: z.ZodLiteral<"workflowRun">;
122
+ definitionId: z.ZodString;
123
+ input: z.ZodOptional<z.ZodUnknown>;
124
+ inputEnvelope: z.ZodOptional<z.ZodObject<{
125
+ payload: z.ZodUnknown;
126
+ goal: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
127
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
128
+ context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
129
+ }, z.core.$strip>>;
130
+ goal: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
131
+ agentId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
132
+ sessionKey: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
133
+ waitForCompletion: z.ZodOptional<z.ZodBoolean>;
134
+ source: z.ZodOptional<z.ZodObject<{
135
+ kind: z.ZodOptional<z.ZodLiteral<"cron">>;
136
+ scheduleId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
137
+ fireId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
138
+ scheduledAtMs: z.ZodOptional<z.ZodNumber>;
139
+ }, z.core.$strip>>;
80
140
  }, z.core.$strip>]>;
81
141
  delivery: z.ZodOptional<z.ZodObject<{
82
142
  mode: z.ZodDefault<z.ZodEnum<{
@@ -111,6 +171,26 @@ export declare const UpdateJobRequestSchema: z.ZodObject<{
111
171
  message: z.ZodString;
112
172
  model: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
113
173
  timeoutSeconds: z.ZodOptional<z.ZodNumber>;
174
+ }, z.core.$strip>, z.ZodObject<{
175
+ kind: z.ZodLiteral<"workflowRun">;
176
+ definitionId: z.ZodString;
177
+ input: z.ZodOptional<z.ZodUnknown>;
178
+ inputEnvelope: z.ZodOptional<z.ZodObject<{
179
+ payload: z.ZodUnknown;
180
+ goal: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
181
+ variables: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
182
+ context: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
183
+ }, z.core.$strip>>;
184
+ goal: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
185
+ agentId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
186
+ sessionKey: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
187
+ waitForCompletion: z.ZodOptional<z.ZodBoolean>;
188
+ source: z.ZodOptional<z.ZodObject<{
189
+ kind: z.ZodOptional<z.ZodLiteral<"cron">>;
190
+ scheduleId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
191
+ fireId: z.ZodPreprocess<z.ZodOptional<z.ZodString>>;
192
+ scheduledAtMs: z.ZodOptional<z.ZodNumber>;
193
+ }, z.core.$strip>>;
114
194
  }, z.core.$strip>]>>;
115
195
  delivery: z.ZodOptional<z.ZodObject<{
116
196
  mode: z.ZodDefault<z.ZodEnum<{
@@ -76,7 +76,33 @@ 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 CronPayloadSchema = z.union([CronSystemEventPayloadSchema, CronAgentTurnPayloadSchema]);
79
+ const WorkflowRunInputEnvelopeSchema = z.object({
80
+ payload: z.unknown(),
81
+ goal: optionalTrimmedString(5e3, 1),
82
+ variables: z.record(z.string(), z.unknown()).optional(),
83
+ context: z.record(z.string(), z.unknown()).optional()
84
+ });
85
+ const CronWorkflowRunPayloadSchema = z.object({
86
+ kind: z.literal("workflowRun"),
87
+ definitionId: z.string().min(1).max(200),
88
+ input: z.unknown().optional(),
89
+ inputEnvelope: WorkflowRunInputEnvelopeSchema.optional(),
90
+ goal: optionalTrimmedString(5e3, 1),
91
+ agentId: optionalTrimmedString(64, 1),
92
+ sessionKey: optionalTrimmedString(300, 1),
93
+ waitForCompletion: z.boolean().optional(),
94
+ source: z.object({
95
+ kind: z.literal("cron").optional(),
96
+ scheduleId: optionalTrimmedString(200, 1),
97
+ fireId: optionalTrimmedString(200, 1),
98
+ scheduledAtMs: z.number().int().nonnegative().optional()
99
+ }).optional()
100
+ });
101
+ const CronPayloadSchema = z.union([
102
+ CronSystemEventPayloadSchema,
103
+ CronAgentTurnPayloadSchema,
104
+ CronWorkflowRunPayloadSchema
105
+ ]);
80
106
  const CronDeliverySchema = z.object({
81
107
  mode: CronDeliveryMode.default("none"),
82
108
  channel: optionalTrimmedString(32, 1),
@@ -95,7 +121,7 @@ const JobDataSchema = z.object({
95
121
  });
96
122
  }).optional(),
97
123
  maxRetries: z.number().int().min(0).max(10).default(3),
98
- timeout: z.number().int().min(1e3).max(3e5).default(18e4),
124
+ timeout: z.number().int().min(1e3).max(72e5).default(18e4),
99
125
  created_at: z.string().datetime(),
100
126
  updated_at: z.string().datetime(),
101
127
  sessionTarget: z.enum(["main", "isolated"]).optional(),
@@ -111,7 +137,7 @@ const AddJobRequestSchema = z.object({
111
137
  name: z.string().max(100).optional(),
112
138
  timezone: z.string().optional(),
113
139
  maxRetries: z.number().int().min(0).max(10).optional(),
114
- timeout: z.number().int().min(1e3).max(3e5).optional(),
140
+ timeout: z.number().int().min(1e3).max(72e5).optional(),
115
141
  sessionTarget: z.enum(["main", "isolated"]).optional(),
116
142
  agentId: optionalJobAgentId,
117
143
  workingDirectory: optionalJobWorkingDirectory,
@@ -124,7 +150,7 @@ const UpdateJobRequestSchema = z.object({
124
150
  schedule: cronExpression.optional(),
125
151
  timezone: z.string().optional(),
126
152
  maxRetries: z.number().int().min(0).max(10).optional(),
127
- timeout: z.number().int().min(1e3).max(3e5).optional(),
153
+ timeout: z.number().int().min(1e3).max(72e5).optional(),
128
154
  enabled: z.boolean().optional(),
129
155
  sessionTarget: z.enum(["main", "isolated"]).optional(),
130
156
  agentId: patchJobAgentId,