botmux 2.33.0 → 2.34.0

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 (281) hide show
  1. package/README.en.md +12 -1
  2. package/README.md +45 -1
  3. package/dist/adapters/cli/claude-code.d.ts.map +1 -1
  4. package/dist/adapters/cli/claude-code.js +11 -0
  5. package/dist/adapters/cli/claude-code.js.map +1 -1
  6. package/dist/cli/bots-list-output.d.ts +21 -0
  7. package/dist/cli/bots-list-output.d.ts.map +1 -0
  8. package/dist/cli/bots-list-output.js +23 -0
  9. package/dist/cli/bots-list-output.js.map +1 -0
  10. package/dist/cli/workflow.d.ts +13 -0
  11. package/dist/cli/workflow.d.ts.map +1 -0
  12. package/dist/cli/workflow.js +781 -0
  13. package/dist/cli/workflow.js.map +1 -0
  14. package/dist/cli.js +69 -14
  15. package/dist/cli.js.map +1 -1
  16. package/dist/core/command-handler.d.ts.map +1 -1
  17. package/dist/core/command-handler.js +219 -6
  18. package/dist/core/command-handler.js.map +1 -1
  19. package/dist/core/session-manager.d.ts +6 -1
  20. package/dist/core/session-manager.d.ts.map +1 -1
  21. package/dist/core/session-manager.js +22 -12
  22. package/dist/core/session-manager.js.map +1 -1
  23. package/dist/core/worker-pool.d.ts +13 -0
  24. package/dist/core/worker-pool.d.ts.map +1 -1
  25. package/dist/core/worker-pool.js +100 -6
  26. package/dist/core/worker-pool.js.map +1 -1
  27. package/dist/daemon.d.ts +3 -0
  28. package/dist/daemon.d.ts.map +1 -1
  29. package/dist/daemon.js +884 -3
  30. package/dist/daemon.js.map +1 -1
  31. package/dist/dashboard/auth.d.ts +36 -0
  32. package/dist/dashboard/auth.d.ts.map +1 -1
  33. package/dist/dashboard/auth.js +22 -0
  34. package/dist/dashboard/auth.js.map +1 -1
  35. package/dist/dashboard/web/app.js +20 -1
  36. package/dist/dashboard/web/app.js.map +1 -1
  37. package/dist/dashboard/web/i18n.d.ts.map +1 -1
  38. package/dist/dashboard/web/i18n.js +356 -0
  39. package/dist/dashboard/web/i18n.js.map +1 -1
  40. package/dist/dashboard/web/workflow-catalog.d.ts +2 -0
  41. package/dist/dashboard/web/workflow-catalog.d.ts.map +1 -0
  42. package/dist/dashboard/web/workflow-catalog.js +323 -0
  43. package/dist/dashboard/web/workflow-catalog.js.map +1 -0
  44. package/dist/dashboard/web/workflows.d.ts +2 -0
  45. package/dist/dashboard/web/workflows.d.ts.map +1 -0
  46. package/dist/dashboard/web/workflows.js +1618 -0
  47. package/dist/dashboard/web/workflows.js.map +1 -0
  48. package/dist/dashboard/workflow-api.d.ts +23 -0
  49. package/dist/dashboard/workflow-api.d.ts.map +1 -0
  50. package/dist/dashboard/workflow-api.js +463 -0
  51. package/dist/dashboard/workflow-api.js.map +1 -0
  52. package/dist/dashboard-web/app.js +494 -199
  53. package/dist/dashboard-web/index.html +1 -0
  54. package/dist/dashboard-web/style.css +160 -6
  55. package/dist/dashboard-web/terminal-replay.html +227 -0
  56. package/dist/dashboard.js +29 -12
  57. package/dist/dashboard.js.map +1 -1
  58. package/dist/i18n/en.d.ts.map +1 -1
  59. package/dist/i18n/en.js +12 -0
  60. package/dist/i18n/en.js.map +1 -1
  61. package/dist/i18n/zh.d.ts.map +1 -1
  62. package/dist/i18n/zh.js +12 -0
  63. package/dist/i18n/zh.js.map +1 -1
  64. package/dist/im/lark/card-handler.d.ts +3 -0
  65. package/dist/im/lark/card-handler.d.ts.map +1 -1
  66. package/dist/im/lark/card-handler.js +27 -1
  67. package/dist/im/lark/card-handler.js.map +1 -1
  68. package/dist/im/lark/client.d.ts +19 -2
  69. package/dist/im/lark/client.d.ts.map +1 -1
  70. package/dist/im/lark/client.js +21 -2
  71. package/dist/im/lark/client.js.map +1 -1
  72. package/dist/im/lark/workflow-card-handler.d.ts +50 -0
  73. package/dist/im/lark/workflow-card-handler.d.ts.map +1 -0
  74. package/dist/im/lark/workflow-card-handler.js +152 -0
  75. package/dist/im/lark/workflow-card-handler.js.map +1 -0
  76. package/dist/im/lark/workflow-cards.d.ts +46 -0
  77. package/dist/im/lark/workflow-cards.d.ts.map +1 -0
  78. package/dist/im/lark/workflow-cards.js +226 -0
  79. package/dist/im/lark/workflow-cards.js.map +1 -0
  80. package/dist/im/lark/workflow-progress-card.d.ts +76 -0
  81. package/dist/im/lark/workflow-progress-card.d.ts.map +1 -0
  82. package/dist/im/lark/workflow-progress-card.js +279 -0
  83. package/dist/im/lark/workflow-progress-card.js.map +1 -0
  84. package/dist/im/lark/workflow-slash-command.d.ts +92 -0
  85. package/dist/im/lark/workflow-slash-command.d.ts.map +1 -0
  86. package/dist/im/lark/workflow-slash-command.js +185 -0
  87. package/dist/im/lark/workflow-slash-command.js.map +1 -0
  88. package/dist/services/group-creator.d.ts.map +1 -1
  89. package/dist/services/group-creator.js +17 -4
  90. package/dist/services/group-creator.js.map +1 -1
  91. package/dist/services/groups-store.d.ts +11 -0
  92. package/dist/services/groups-store.d.ts.map +1 -1
  93. package/dist/services/groups-store.js +26 -0
  94. package/dist/services/groups-store.js.map +1 -1
  95. package/dist/services/jsonl-cursor.d.ts +12 -0
  96. package/dist/services/jsonl-cursor.d.ts.map +1 -0
  97. package/dist/services/jsonl-cursor.js +45 -0
  98. package/dist/services/jsonl-cursor.js.map +1 -0
  99. package/dist/services/schedule-store.d.ts +35 -0
  100. package/dist/services/schedule-store.d.ts.map +1 -1
  101. package/dist/services/schedule-store.js +108 -1
  102. package/dist/services/schedule-store.js.map +1 -1
  103. package/dist/skills/definitions.d.ts.map +1 -1
  104. package/dist/skills/definitions.js +399 -0
  105. package/dist/skills/definitions.js.map +1 -1
  106. package/dist/types.d.ts +4 -0
  107. package/dist/types.d.ts.map +1 -1
  108. package/dist/utils/cli-usage-limit.d.ts.map +1 -1
  109. package/dist/utils/cli-usage-limit.js +4 -0
  110. package/dist/utils/cli-usage-limit.js.map +1 -1
  111. package/dist/worker.js +118 -14
  112. package/dist/worker.js.map +1 -1
  113. package/dist/workflows/attempt-resume.d.ts +114 -0
  114. package/dist/workflows/attempt-resume.d.ts.map +1 -0
  115. package/dist/workflows/attempt-resume.js +385 -0
  116. package/dist/workflows/attempt-resume.js.map +1 -0
  117. package/dist/workflows/attempt-terminal.d.ts +21 -0
  118. package/dist/workflows/attempt-terminal.d.ts.map +1 -0
  119. package/dist/workflows/attempt-terminal.js +7 -0
  120. package/dist/workflows/attempt-terminal.js.map +1 -0
  121. package/dist/workflows/blob.d.ts +27 -0
  122. package/dist/workflows/blob.d.ts.map +1 -0
  123. package/dist/workflows/blob.js +39 -0
  124. package/dist/workflows/blob.js.map +1 -0
  125. package/dist/workflows/cancel-run.d.ts +45 -0
  126. package/dist/workflows/cancel-run.d.ts.map +1 -0
  127. package/dist/workflows/cancel-run.js +99 -0
  128. package/dist/workflows/cancel-run.js.map +1 -0
  129. package/dist/workflows/cancel.d.ts +111 -0
  130. package/dist/workflows/cancel.d.ts.map +1 -0
  131. package/dist/workflows/cancel.js +120 -0
  132. package/dist/workflows/cancel.js.map +1 -0
  133. package/dist/workflows/catalog.d.ts +60 -0
  134. package/dist/workflows/catalog.d.ts.map +1 -0
  135. package/dist/workflows/catalog.js +119 -0
  136. package/dist/workflows/catalog.js.map +1 -0
  137. package/dist/workflows/cold-attach.d.ts +30 -0
  138. package/dist/workflows/cold-attach.d.ts.map +1 -0
  139. package/dist/workflows/cold-attach.js +40 -0
  140. package/dist/workflows/cold-attach.js.map +1 -0
  141. package/dist/workflows/cold-scan.d.ts +21 -0
  142. package/dist/workflows/cold-scan.d.ts.map +1 -0
  143. package/dist/workflows/cold-scan.js +70 -0
  144. package/dist/workflows/cold-scan.js.map +1 -0
  145. package/dist/workflows/daemon-spawn.d.ts +117 -0
  146. package/dist/workflows/daemon-spawn.d.ts.map +1 -0
  147. package/dist/workflows/daemon-spawn.js +551 -0
  148. package/dist/workflows/daemon-spawn.js.map +1 -0
  149. package/dist/workflows/definition.d.ts +1309 -0
  150. package/dist/workflows/definition.d.ts.map +1 -0
  151. package/dist/workflows/definition.js +334 -0
  152. package/dist/workflows/definition.js.map +1 -0
  153. package/dist/workflows/effect-input.d.ts +4 -0
  154. package/dist/workflows/effect-input.d.ts.map +1 -0
  155. package/dist/workflows/effect-input.js +18 -0
  156. package/dist/workflows/effect-input.js.map +1 -0
  157. package/dist/workflows/events/append.d.ts +77 -0
  158. package/dist/workflows/events/append.d.ts.map +1 -0
  159. package/dist/workflows/events/append.js +214 -0
  160. package/dist/workflows/events/append.js.map +1 -0
  161. package/dist/workflows/events/idempotency.d.ts +77 -0
  162. package/dist/workflows/events/idempotency.d.ts.map +1 -0
  163. package/dist/workflows/events/idempotency.js +116 -0
  164. package/dist/workflows/events/idempotency.js.map +1 -0
  165. package/dist/workflows/events/index.d.ts +7 -0
  166. package/dist/workflows/events/index.d.ts.map +1 -0
  167. package/dist/workflows/events/index.js +7 -0
  168. package/dist/workflows/events/index.js.map +1 -0
  169. package/dist/workflows/events/payloads.d.ts +917 -0
  170. package/dist/workflows/events/payloads.d.ts.map +1 -0
  171. package/dist/workflows/events/payloads.js +337 -0
  172. package/dist/workflows/events/payloads.js.map +1 -0
  173. package/dist/workflows/events/replay.d.ts +238 -0
  174. package/dist/workflows/events/replay.d.ts.map +1 -0
  175. package/dist/workflows/events/replay.js +608 -0
  176. package/dist/workflows/events/replay.js.map +1 -0
  177. package/dist/workflows/events/schema.d.ts +5242 -0
  178. package/dist/workflows/events/schema.d.ts.map +1 -0
  179. package/dist/workflows/events/schema.js +295 -0
  180. package/dist/workflows/events/schema.js.map +1 -0
  181. package/dist/workflows/events/types.d.ts +34 -0
  182. package/dist/workflows/events/types.d.ts.map +1 -0
  183. package/dist/workflows/events/types.js +2 -0
  184. package/dist/workflows/events/types.js.map +1 -0
  185. package/dist/workflows/fanout.d.ts +36 -0
  186. package/dist/workflows/fanout.d.ts.map +1 -0
  187. package/dist/workflows/fanout.js +114 -0
  188. package/dist/workflows/fanout.js.map +1 -0
  189. package/dist/workflows/hostExecutors/botmux-schedule.d.ts +41 -0
  190. package/dist/workflows/hostExecutors/botmux-schedule.d.ts.map +1 -0
  191. package/dist/workflows/hostExecutors/botmux-schedule.js +121 -0
  192. package/dist/workflows/hostExecutors/botmux-schedule.js.map +1 -0
  193. package/dist/workflows/hostExecutors/feishu-im.d.ts +12 -0
  194. package/dist/workflows/hostExecutors/feishu-im.d.ts.map +1 -0
  195. package/dist/workflows/hostExecutors/feishu-im.js +49 -0
  196. package/dist/workflows/hostExecutors/feishu-im.js.map +1 -0
  197. package/dist/workflows/hostExecutors/feishu-reply.d.ts +24 -0
  198. package/dist/workflows/hostExecutors/feishu-reply.d.ts.map +1 -0
  199. package/dist/workflows/hostExecutors/feishu-reply.js +88 -0
  200. package/dist/workflows/hostExecutors/feishu-reply.js.map +1 -0
  201. package/dist/workflows/hostExecutors/feishu-send.d.ts +23 -0
  202. package/dist/workflows/hostExecutors/feishu-send.d.ts.map +1 -0
  203. package/dist/workflows/hostExecutors/feishu-send.js +124 -0
  204. package/dist/workflows/hostExecutors/feishu-send.js.map +1 -0
  205. package/dist/workflows/hostExecutors/index.d.ts +8 -0
  206. package/dist/workflows/hostExecutors/index.d.ts.map +1 -0
  207. package/dist/workflows/hostExecutors/index.js +8 -0
  208. package/dist/workflows/hostExecutors/index.js.map +1 -0
  209. package/dist/workflows/hostExecutors/protocol.d.ts +42 -0
  210. package/dist/workflows/hostExecutors/protocol.d.ts.map +1 -0
  211. package/dist/workflows/hostExecutors/protocol.js +181 -0
  212. package/dist/workflows/hostExecutors/protocol.js.map +1 -0
  213. package/dist/workflows/hostExecutors/registry.d.ts +10 -0
  214. package/dist/workflows/hostExecutors/registry.d.ts.map +1 -0
  215. package/dist/workflows/hostExecutors/registry.js +36 -0
  216. package/dist/workflows/hostExecutors/registry.js.map +1 -0
  217. package/dist/workflows/hostExecutors/types.d.ts +78 -0
  218. package/dist/workflows/hostExecutors/types.d.ts.map +1 -0
  219. package/dist/workflows/hostExecutors/types.js +2 -0
  220. package/dist/workflows/hostExecutors/types.js.map +1 -0
  221. package/dist/workflows/loader.d.ts +16 -0
  222. package/dist/workflows/loader.d.ts.map +1 -0
  223. package/dist/workflows/loader.js +56 -0
  224. package/dist/workflows/loader.js.map +1 -0
  225. package/dist/workflows/loop.d.ts +50 -0
  226. package/dist/workflows/loop.d.ts.map +1 -0
  227. package/dist/workflows/loop.js +350 -0
  228. package/dist/workflows/loop.js.map +1 -0
  229. package/dist/workflows/ops-projection.d.ts +168 -0
  230. package/dist/workflows/ops-projection.d.ts.map +1 -0
  231. package/dist/workflows/ops-projection.js +707 -0
  232. package/dist/workflows/ops-projection.js.map +1 -0
  233. package/dist/workflows/orchestrator.d.ts +107 -0
  234. package/dist/workflows/orchestrator.d.ts.map +1 -0
  235. package/dist/workflows/orchestrator.js +197 -0
  236. package/dist/workflows/orchestrator.js.map +1 -0
  237. package/dist/workflows/output-binding.d.ts +70 -0
  238. package/dist/workflows/output-binding.d.ts.map +1 -0
  239. package/dist/workflows/output-binding.js +265 -0
  240. package/dist/workflows/output-binding.js.map +1 -0
  241. package/dist/workflows/params.d.ts +61 -0
  242. package/dist/workflows/params.d.ts.map +1 -0
  243. package/dist/workflows/params.js +195 -0
  244. package/dist/workflows/params.js.map +1 -0
  245. package/dist/workflows/resume.d.ts +263 -0
  246. package/dist/workflows/resume.d.ts.map +1 -0
  247. package/dist/workflows/resume.js +808 -0
  248. package/dist/workflows/resume.js.map +1 -0
  249. package/dist/workflows/run-id.d.ts +2 -0
  250. package/dist/workflows/run-id.d.ts.map +1 -0
  251. package/dist/workflows/run-id.js +7 -0
  252. package/dist/workflows/run-id.js.map +1 -0
  253. package/dist/workflows/run-init.d.ts +48 -0
  254. package/dist/workflows/run-init.d.ts.map +1 -0
  255. package/dist/workflows/run-init.js +99 -0
  256. package/dist/workflows/run-init.js.map +1 -0
  257. package/dist/workflows/runs-dir.d.ts +4 -0
  258. package/dist/workflows/runs-dir.d.ts.map +1 -0
  259. package/dist/workflows/runs-dir.js +15 -0
  260. package/dist/workflows/runs-dir.js.map +1 -0
  261. package/dist/workflows/runtime.d.ts +211 -0
  262. package/dist/workflows/runtime.d.ts.map +1 -0
  263. package/dist/workflows/runtime.js +594 -0
  264. package/dist/workflows/runtime.js.map +1 -0
  265. package/dist/workflows/spawn-bot.d.ts +165 -0
  266. package/dist/workflows/spawn-bot.d.ts.map +1 -0
  267. package/dist/workflows/spawn-bot.js +215 -0
  268. package/dist/workflows/spawn-bot.js.map +1 -0
  269. package/dist/workflows/system.d.ts +49 -0
  270. package/dist/workflows/system.d.ts.map +1 -0
  271. package/dist/workflows/system.js +48 -0
  272. package/dist/workflows/system.js.map +1 -0
  273. package/dist/workflows/trigger-run.d.ts +70 -0
  274. package/dist/workflows/trigger-run.d.ts.map +1 -0
  275. package/dist/workflows/trigger-run.js +88 -0
  276. package/dist/workflows/trigger-run.js.map +1 -0
  277. package/dist/workflows/wait.d.ts +120 -0
  278. package/dist/workflows/wait.d.ts.map +1 -0
  279. package/dist/workflows/wait.js +181 -0
  280. package/dist/workflows/wait.js.map +1 -0
  281. package/package.json +3 -3
@@ -0,0 +1,99 @@
1
+ import { runLoop } from './loop.js';
2
+ import { replay } from './events/replay.js';
3
+ import { completeNodeCancel, completeRunCancel, requestCancel, } from './cancel.js';
4
+ import { isValidRunId, readRunSnapshot } from './ops-projection.js';
5
+ /**
6
+ * IM cancel is scoped to the chat that created the run. This is a pure
7
+ * guard: callers must run it before writing cancelRequested.
8
+ */
9
+ export async function guardWorkflowRunCancelChatScope(runsDir, runId, expectedChatId) {
10
+ if (!isValidRunId(runId))
11
+ return { ok: false, error: 'bad_run_id' };
12
+ const snapshot = await readRunSnapshot(runsDir, runId);
13
+ if (!snapshot)
14
+ return { ok: false, error: 'unknown_run' };
15
+ if (snapshot.chatBinding?.chatId !== expectedChatId) {
16
+ return { ok: false, error: 'wrong_chat', status: snapshot.run.status };
17
+ }
18
+ return { ok: true };
19
+ }
20
+ /**
21
+ * Shared run-level cancel operation used by CLI and dashboard/daemon IPC.
22
+ *
23
+ * The operation is idempotent:
24
+ * - terminal runs write zero events;
25
+ * - repeated cancels reuse the existing run-level cancel intent;
26
+ * - parent node/run cancel terminal events are written only once by replay
27
+ * intent markers.
28
+ */
29
+ export async function cancelWorkflowRun(input) {
30
+ const { ctx, reason, by, actor = 'human', maxTicks = 200 } = input;
31
+ let snapshot = replay(await ctx.log.readAll());
32
+ if (isTerminalRunStatus(snapshot.run.status)) {
33
+ return { snapshot, cancelAlreadyRequested: false, alreadyTerminal: true };
34
+ }
35
+ let cancelEventId = snapshot.cancelledRunIntent?.cancelOriginEventId;
36
+ const cancelAlreadyRequested = !!snapshot.cancelledRunIntent;
37
+ if (!snapshot.cancelledRunIntent) {
38
+ const cancel = await requestCancel(ctx.log, {
39
+ target: { kind: 'run', runId: ctx.log.runId },
40
+ reason,
41
+ by,
42
+ }, actor);
43
+ cancelEventId = cancel.eventId;
44
+ }
45
+ snapshot = replay(await ctx.log.readAll());
46
+ await finalizeRunCancelIfPossible(ctx.log, ctx.def, snapshot);
47
+ const loopResult = await runLoop(ctx, { maxTicks });
48
+ snapshot = replay(await ctx.log.readAll());
49
+ await finalizeRunCancelIfPossible(ctx.log, ctx.def, snapshot);
50
+ snapshot = replay(await ctx.log.readAll());
51
+ return {
52
+ snapshot,
53
+ loopResult,
54
+ cancelEventId,
55
+ cancelAlreadyRequested,
56
+ alreadyTerminal: false,
57
+ };
58
+ }
59
+ export async function finalizeRunCancelIfPossible(log, def, snapshot) {
60
+ const intent = snapshot.cancelledRunIntent;
61
+ if (!intent)
62
+ return;
63
+ for (const nodeId of Object.keys(def.nodes)) {
64
+ const nodeStatus = snapshot.nodes.get(nodeId)?.status ?? 'idle';
65
+ if (isTerminalNodeStatus(nodeStatus))
66
+ continue;
67
+ const ownedActivities = [...snapshot.activities.values()].filter((activity) => activity.ownerNodeId === nodeId);
68
+ const hasNonTerminalActivity = ownedActivities.some((activity) => !isTerminalActivityStatus(activity.status));
69
+ if (hasNonTerminalActivity)
70
+ continue;
71
+ await completeNodeCancel(log, {
72
+ nodeId,
73
+ cancelOriginEventId: intent.cancelOriginEventId,
74
+ }, 'scheduler');
75
+ }
76
+ const afterNodes = replay(await log.readAll());
77
+ if (!afterNodes.cancelledRunIntent)
78
+ return;
79
+ const allNodesTerminal = Object.keys(def.nodes).every((nodeId) => isTerminalNodeStatus(afterNodes.nodes.get(nodeId)?.status ?? 'idle'));
80
+ if (!allNodesTerminal)
81
+ return;
82
+ await completeRunCancel(log, { cancelOriginEventId: afterNodes.cancelledRunIntent.cancelOriginEventId }, 'scheduler');
83
+ }
84
+ export function isTerminalRunStatus(status) {
85
+ return status === 'succeeded' || status === 'failed' || status === 'cancelled';
86
+ }
87
+ function isTerminalNodeStatus(status) {
88
+ return (status === 'succeeded' ||
89
+ status === 'failed' ||
90
+ status === 'skipped' ||
91
+ status === 'cancelled');
92
+ }
93
+ function isTerminalActivityStatus(status) {
94
+ return (status === 'succeeded' ||
95
+ status === 'failed' ||
96
+ status === 'timedOut' ||
97
+ status === 'cancelled');
98
+ }
99
+ //# sourceMappingURL=cancel-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel-run.js","sourceRoot":"","sources":["../../src/workflows/cancel-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,111 @@
1
+ /**
2
+ * Cancel propagation (events doc v0.1.2 §2.5, Step 9 of 10).
3
+ *
4
+ * Cancel is a TERMINAL REASON, not an error — Run/Node/Activity each
5
+ * have an independent `cancelled` terminal state. The chain (§2.5):
6
+ *
7
+ * cancelRequested(target)
8
+ * → scheduler broadcasts to non-terminal nodes
9
+ * → for each running activity: send cancel signal
10
+ * → cancelDelivered (worker acknowledges)
11
+ * → worker cleans up
12
+ * → activityCanceled (Activity terminal)
13
+ * → nodeCanceled (Node terminal, only after ALL its activities
14
+ * reach a terminal state; spec §2.5 "partial
15
+ * cancel": cancelRequested(activityId) does NOT
16
+ * auto-cancel parent node)
17
+ * → runCanceled (Run terminal, only when all nodes terminal;
18
+ * spec §2.5: cancelRequested(nodeId) does NOT
19
+ * auto-cancel parent run)
20
+ *
21
+ * Step 9 deliverables:
22
+ * - `requestCancel`, `deliverCancel`, `completeActivityCancel` —
23
+ * host functions that write the corresponding events.
24
+ * - replay projection of in-flight cancel state so resume can
25
+ * detect dangling cancels (cancelRequested written, terminal
26
+ * missing) and complete them.
27
+ * - resume integration: a third recovery branch alongside
28
+ * reconcile + wait recovery.
29
+ *
30
+ * Step 9 does NOT:
31
+ * - implement the scheduler broadcast (run/node → activity fan-out
32
+ * is Step 10+ scheduler concern; this layer assumes the caller
33
+ * supplies activity-level cancels);
34
+ * - decide retry policy (cancel preempts retry — once canceled,
35
+ * terminal stays canceled, not failed/retryable).
36
+ */
37
+ import type { EventLog } from './events/append.js';
38
+ import type { ActivityCanceledEvent, CancelDeliveredEvent, CancelRequestedEvent, NodeCanceledEvent, RunCanceledEvent } from './events/types.js';
39
+ export type CancelTarget = {
40
+ kind: 'run';
41
+ runId: string;
42
+ } | {
43
+ kind: 'node';
44
+ nodeId: string;
45
+ } | {
46
+ kind: 'activity';
47
+ activityId: string;
48
+ };
49
+ export type RequestCancelInput = {
50
+ target: CancelTarget;
51
+ /** Free-form human-readable reason; recorded for audit + dashboard. */
52
+ reason: string;
53
+ /** Identifier of the requester — open_id, system actor name, etc. */
54
+ by: string;
55
+ };
56
+ export type DeliverCancelInput = {
57
+ target: CancelTarget;
58
+ /** Activity that the worker actually acknowledged the cancel on.
59
+ * For node/run-level cancels broadcast to multiple activities, the
60
+ * worker writes one cancelDelivered per activity it acknowledges. */
61
+ activityId: string;
62
+ };
63
+ export type CompleteActivityCancelInput = {
64
+ activityId: string;
65
+ attemptId: string;
66
+ /** eventId of the originating cancelRequested — surfaced on the
67
+ * terminal so post-hoc forensics can follow the cancel chain. */
68
+ cancelOriginEventId: string;
69
+ };
70
+ export type CompleteNodeCancelInput = {
71
+ nodeId: string;
72
+ cancelOriginEventId: string;
73
+ };
74
+ export type CompleteRunCancelInput = {
75
+ cancelOriginEventId: string;
76
+ };
77
+ export type RequestCancelActor = 'human' | 'supervisor' | 'system';
78
+ export type DeliverCancelActor = 'worker' | 'system';
79
+ export type CompleteCancelActor = 'scheduler' | 'worker' | 'system';
80
+ /**
81
+ * Originating cancel event. Records the intent without changing any
82
+ * entity state — the actual transitions happen via cancelDelivered →
83
+ * activityCanceled.
84
+ */
85
+ export declare function requestCancel(log: EventLog, input: RequestCancelInput, actor?: RequestCancelActor): Promise<CancelRequestedEvent>;
86
+ /**
87
+ * Worker acknowledges the cancel signal for a specific activity.
88
+ * Multiple cancelDelivered events may fan out from a single
89
+ * cancelRequested(run|node).
90
+ */
91
+ export declare function deliverCancel(log: EventLog, input: DeliverCancelInput, actor?: DeliverCancelActor): Promise<CancelDeliveredEvent>;
92
+ /**
93
+ * Activity terminal in the cancel branch. Spec §2.5: cancel produces
94
+ * a distinct terminal state (not activityFailed/canceled error code).
95
+ */
96
+ export declare function completeActivityCancel(log: EventLog, input: CompleteActivityCancelInput, actor?: CompleteCancelActor): Promise<ActivityCanceledEvent>;
97
+ /**
98
+ * Node terminal in the cancel branch. Spec §2.5: nodeCanceled fires
99
+ * only after ALL of the node's activities have reached terminal — the
100
+ * caller (scheduler / supervisor) is responsible for verifying that
101
+ * precondition before invoking. This helper merely writes the event.
102
+ */
103
+ export declare function completeNodeCancel(log: EventLog, input: CompleteNodeCancelInput, actor?: CompleteCancelActor): Promise<NodeCanceledEvent>;
104
+ /**
105
+ * Run terminal in the cancel branch. Spec §2.5: runCanceled fires
106
+ * only after ALL of the run's nodes have reached terminal. Same
107
+ * precondition responsibility as `completeNodeCancel` — this helper
108
+ * writes the event but doesn't enforce dependencies.
109
+ */
110
+ export declare function completeRunCancel(log: EventLog, input: CompleteRunCancelInput, actor?: CompleteCancelActor): Promise<RunCanceledEvent>;
111
+ //# sourceMappingURL=cancel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel.d.ts","sourceRoot":"","sources":["../../src/workflows/cancel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EACV,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAI3B,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB,uEAAuE;IACvE,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,EAAE,YAAY,CAAC;IACrB;;0EAEsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB;sEACkE;IAClE,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,YAAY,GAAG,QAAQ,CAAC;AACnE,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AACrD,MAAM,MAAM,mBAAmB,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAIpE;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,kBAAkB,EACzB,KAAK,GAAE,kBAA4B,GAClC,OAAO,CAAC,oBAAoB,CAAC,CAW/B;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,kBAAkB,EACzB,KAAK,GAAE,kBAA6B,GACnC,OAAO,CAAC,oBAAoB,CAAC,CAU/B;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,2BAA2B,EAClC,KAAK,GAAE,mBAAiC,GACvC,OAAO,CAAC,qBAAqB,CAAC,CAWhC;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,uBAAuB,EAC9B,KAAK,GAAE,mBAAiC,GACvC,OAAO,CAAC,iBAAiB,CAAC,CAU5B;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,sBAAsB,EAC7B,KAAK,GAAE,mBAAiC,GACvC,OAAO,CAAC,gBAAgB,CAAC,CAS3B"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Cancel propagation (events doc v0.1.2 §2.5, Step 9 of 10).
3
+ *
4
+ * Cancel is a TERMINAL REASON, not an error — Run/Node/Activity each
5
+ * have an independent `cancelled` terminal state. The chain (§2.5):
6
+ *
7
+ * cancelRequested(target)
8
+ * → scheduler broadcasts to non-terminal nodes
9
+ * → for each running activity: send cancel signal
10
+ * → cancelDelivered (worker acknowledges)
11
+ * → worker cleans up
12
+ * → activityCanceled (Activity terminal)
13
+ * → nodeCanceled (Node terminal, only after ALL its activities
14
+ * reach a terminal state; spec §2.5 "partial
15
+ * cancel": cancelRequested(activityId) does NOT
16
+ * auto-cancel parent node)
17
+ * → runCanceled (Run terminal, only when all nodes terminal;
18
+ * spec §2.5: cancelRequested(nodeId) does NOT
19
+ * auto-cancel parent run)
20
+ *
21
+ * Step 9 deliverables:
22
+ * - `requestCancel`, `deliverCancel`, `completeActivityCancel` —
23
+ * host functions that write the corresponding events.
24
+ * - replay projection of in-flight cancel state so resume can
25
+ * detect dangling cancels (cancelRequested written, terminal
26
+ * missing) and complete them.
27
+ * - resume integration: a third recovery branch alongside
28
+ * reconcile + wait recovery.
29
+ *
30
+ * Step 9 does NOT:
31
+ * - implement the scheduler broadcast (run/node → activity fan-out
32
+ * is Step 10+ scheduler concern; this layer assumes the caller
33
+ * supplies activity-level cancels);
34
+ * - decide retry policy (cancel preempts retry — once canceled,
35
+ * terminal stays canceled, not failed/retryable).
36
+ */
37
+ // ─── Host API ─────────────────────────────────────────────────────────────
38
+ /**
39
+ * Originating cancel event. Records the intent without changing any
40
+ * entity state — the actual transitions happen via cancelDelivered →
41
+ * activityCanceled.
42
+ */
43
+ export async function requestCancel(log, input, actor = 'human') {
44
+ return (await log.append({
45
+ runId: log.runId,
46
+ type: 'cancelRequested',
47
+ actor,
48
+ payload: {
49
+ target: input.target,
50
+ reason: input.reason,
51
+ by: input.by,
52
+ },
53
+ }));
54
+ }
55
+ /**
56
+ * Worker acknowledges the cancel signal for a specific activity.
57
+ * Multiple cancelDelivered events may fan out from a single
58
+ * cancelRequested(run|node).
59
+ */
60
+ export async function deliverCancel(log, input, actor = 'worker') {
61
+ return (await log.append({
62
+ runId: log.runId,
63
+ type: 'cancelDelivered',
64
+ actor,
65
+ payload: {
66
+ target: input.target,
67
+ activityId: input.activityId,
68
+ },
69
+ }));
70
+ }
71
+ /**
72
+ * Activity terminal in the cancel branch. Spec §2.5: cancel produces
73
+ * a distinct terminal state (not activityFailed/canceled error code).
74
+ */
75
+ export async function completeActivityCancel(log, input, actor = 'scheduler') {
76
+ return (await log.append({
77
+ runId: log.runId,
78
+ type: 'activityCanceled',
79
+ actor,
80
+ payload: {
81
+ activityId: input.activityId,
82
+ attemptId: input.attemptId,
83
+ cancelOriginEventId: input.cancelOriginEventId,
84
+ },
85
+ }));
86
+ }
87
+ /**
88
+ * Node terminal in the cancel branch. Spec §2.5: nodeCanceled fires
89
+ * only after ALL of the node's activities have reached terminal — the
90
+ * caller (scheduler / supervisor) is responsible for verifying that
91
+ * precondition before invoking. This helper merely writes the event.
92
+ */
93
+ export async function completeNodeCancel(log, input, actor = 'scheduler') {
94
+ return (await log.append({
95
+ runId: log.runId,
96
+ type: 'nodeCanceled',
97
+ actor,
98
+ payload: {
99
+ nodeId: input.nodeId,
100
+ cancelOriginEventId: input.cancelOriginEventId,
101
+ },
102
+ }));
103
+ }
104
+ /**
105
+ * Run terminal in the cancel branch. Spec §2.5: runCanceled fires
106
+ * only after ALL of the run's nodes have reached terminal. Same
107
+ * precondition responsibility as `completeNodeCancel` — this helper
108
+ * writes the event but doesn't enforce dependencies.
109
+ */
110
+ export async function completeRunCancel(log, input, actor = 'scheduler') {
111
+ return (await log.append({
112
+ runId: log.runId,
113
+ type: 'runCanceled',
114
+ actor,
115
+ payload: {
116
+ cancelOriginEventId: input.cancelOriginEventId,
117
+ },
118
+ }));
119
+ }
120
+ //# sourceMappingURL=cancel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cancel.js","sourceRoot":"","sources":["../../src/workflows/cancel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAuDH,6EAA6E;AAE7E;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAa,EACb,KAAyB,EACzB,QAA4B,OAAO;IAEnC,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC;QACvB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI,EAAE,iBAAiB;QACvB,KAAK;QACL,OAAO,EAAE;YACP,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,EAAE,EAAE,KAAK,CAAC,EAAE;SACb;KACF,CAAC,CAAyB,CAAC;AAC9B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAa,EACb,KAAyB,EACzB,QAA4B,QAAQ;IAEpC,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC;QACvB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI,EAAE,iBAAiB;QACvB,KAAK;QACL,OAAO,EAAE;YACP,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B;KACF,CAAC,CAAyB,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,GAAa,EACb,KAAkC,EAClC,QAA6B,WAAW;IAExC,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC;QACvB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI,EAAE,kBAAkB;QACxB,KAAK;QACL,OAAO,EAAE;YACP,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;SAC/C;KACF,CAAC,CAA0B,CAAC;AAC/B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAa,EACb,KAA8B,EAC9B,QAA6B,WAAW;IAExC,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC;QACvB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI,EAAE,cAAc;QACpB,KAAK;QACL,OAAO,EAAE;YACP,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;SAC/C;KACF,CAAC,CAAsB,CAAC;AAC3B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAa,EACb,KAA6B,EAC7B,QAA6B,WAAW;IAExC,OAAO,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC;QACvB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,IAAI,EAAE,aAAa;QACnB,KAAK;QACL,OAAO,EAAE;YACP,mBAAmB,EAAE,KAAK,CAAC,mBAAmB;SAC/C;KACF,CAAC,CAAqB,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Workflow catalog — discovery + summary load for the dashboard catalog page.
3
+ *
4
+ * Reuses `workflowDefinitionSearchPaths()` so the catalog list and CLI/IM
5
+ * `loadWorkflowDefinition()` see the same files. Two search paths today:
6
+ * - `<cwd>/workflows/*.workflow.json` (per-project)
7
+ * - `$HOME/.botmux/workflows/*.workflow.json` (global, daemon default)
8
+ *
9
+ * Dedupe rule when the same `workflowId` appears in both: cwd wins, then
10
+ * HOME. Matches `loadWorkflowDefinition()` which short-circuits on the first
11
+ * search path that resolves.
12
+ *
13
+ * Read-only and pure: never writes or normalizes the source files — the
14
+ * dashboard catalog list should reflect exactly what the daemon would resolve.
15
+ */
16
+ import { type WorkflowDefinition } from './definition.js';
17
+ export type CatalogEntry = {
18
+ workflowId: string;
19
+ version: number;
20
+ path: string;
21
+ revisionId: string;
22
+ paramCount: number;
23
+ requiredParamCount: number;
24
+ nodeCount: number;
25
+ };
26
+ export type CatalogDefinition = {
27
+ definition: WorkflowDefinition;
28
+ revisionId: string;
29
+ path: string;
30
+ };
31
+ export declare function isValidWorkflowId(id: string): boolean;
32
+ /**
33
+ * List every parseable workflow visible to the daemon.
34
+ *
35
+ * Files that fail to parse (zod errors, cycles, etc.) are skipped silently so
36
+ * one bad authoring attempt doesn't poison the whole catalog. The CLI's
37
+ * `botmux workflow validate` is the right surface for line-level errors.
38
+ *
39
+ * Search-path priority matches `loadWorkflowDefinition`: cwd-local before
40
+ * HOME global so per-project drafts override globals with the same id.
41
+ *
42
+ * `opts.dirs` is a test seam — production callers use the default search
43
+ * paths. Tests pass scoped tmp directories so they don't read whatever
44
+ * happens to live under `$HOME/.botmux/workflows`.
45
+ */
46
+ export declare function listWorkflowDefinitions(opts?: {
47
+ dirs?: string[];
48
+ }): Promise<CatalogEntry[]>;
49
+ /**
50
+ * Load a single workflow definition by id and surface its source path +
51
+ * revisionId in the response envelope. Returns `undefined` when no file in
52
+ * any search path resolves the id, so the caller can return 404.
53
+ *
54
+ * `opts.searchPaths` is a test seam; production callers use the default
55
+ * search paths derived from cwd + `$HOME/.botmux/workflows`.
56
+ */
57
+ export declare function loadCatalogDefinition(workflowId: string, opts?: {
58
+ searchPaths?: string[];
59
+ }): Promise<CatalogDefinition | undefined>;
60
+ //# sourceMappingURL=catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../src/workflows/catalog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAKH,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,iBAAiB,CAAC;AAKzB,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,kBAAkB,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAErD;AAsCD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,GAAE;IAClD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;CACZ,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAoB/B;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GACpC,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAaxC"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Workflow catalog — discovery + summary load for the dashboard catalog page.
3
+ *
4
+ * Reuses `workflowDefinitionSearchPaths()` so the catalog list and CLI/IM
5
+ * `loadWorkflowDefinition()` see the same files. Two search paths today:
6
+ * - `<cwd>/workflows/*.workflow.json` (per-project)
7
+ * - `$HOME/.botmux/workflows/*.workflow.json` (global, daemon default)
8
+ *
9
+ * Dedupe rule when the same `workflowId` appears in both: cwd wins, then
10
+ * HOME. Matches `loadWorkflowDefinition()` which short-circuits on the first
11
+ * search path that resolves.
12
+ *
13
+ * Read-only and pure: never writes or normalizes the source files — the
14
+ * dashboard catalog list should reflect exactly what the daemon would resolve.
15
+ */
16
+ import { promises as fs } from 'node:fs';
17
+ import { join, dirname } from 'node:path';
18
+ import { computeRevisionId, parseWorkflowDefinition, } from './definition.js';
19
+ import { workflowDefinitionSearchPaths } from './loader.js';
20
+ const WORKFLOW_ID_PATTERN = /^[A-Za-z0-9_.-]+$/;
21
+ export function isValidWorkflowId(id) {
22
+ return WORKFLOW_ID_PATTERN.test(id);
23
+ }
24
+ function searchDirectories() {
25
+ // workflowDefinitionSearchPaths returns full file paths for a given id; we
26
+ // strip the filename so we can scan the parent directories instead. Filter
27
+ // duplicates so home-only setups don't double-walk.
28
+ const dirs = new Set();
29
+ for (const path of workflowDefinitionSearchPaths('__sentinel__')) {
30
+ dirs.add(dirname(path));
31
+ }
32
+ return [...dirs];
33
+ }
34
+ async function readEntriesFromDir(dir) {
35
+ try {
36
+ const names = await fs.readdir(dir);
37
+ return names.filter((n) => n.endsWith('.workflow.json'));
38
+ }
39
+ catch (err) {
40
+ if (err.code === 'ENOENT')
41
+ return [];
42
+ throw err;
43
+ }
44
+ }
45
+ function summarize(def, path) {
46
+ const params = def.params ?? {};
47
+ const paramCount = Object.keys(params).length;
48
+ const requiredParamCount = Object.values(params).filter((p) => p.required).length;
49
+ return {
50
+ workflowId: def.workflowId,
51
+ version: def.version,
52
+ path,
53
+ revisionId: computeRevisionId(def),
54
+ paramCount,
55
+ requiredParamCount,
56
+ nodeCount: Object.keys(def.nodes).length,
57
+ };
58
+ }
59
+ /**
60
+ * List every parseable workflow visible to the daemon.
61
+ *
62
+ * Files that fail to parse (zod errors, cycles, etc.) are skipped silently so
63
+ * one bad authoring attempt doesn't poison the whole catalog. The CLI's
64
+ * `botmux workflow validate` is the right surface for line-level errors.
65
+ *
66
+ * Search-path priority matches `loadWorkflowDefinition`: cwd-local before
67
+ * HOME global so per-project drafts override globals with the same id.
68
+ *
69
+ * `opts.dirs` is a test seam — production callers use the default search
70
+ * paths. Tests pass scoped tmp directories so they don't read whatever
71
+ * happens to live under `$HOME/.botmux/workflows`.
72
+ */
73
+ export async function listWorkflowDefinitions(opts = {}) {
74
+ const dirs = opts.dirs ?? searchDirectories();
75
+ const seen = new Map();
76
+ for (const dir of dirs) {
77
+ const files = await readEntriesFromDir(dir);
78
+ for (const name of files) {
79
+ const path = join(dir, name);
80
+ try {
81
+ const raw = await fs.readFile(path, 'utf-8');
82
+ const def = parseWorkflowDefinition(JSON.parse(raw));
83
+ // First occurrence wins (cwd before HOME by search-path order).
84
+ if (!seen.has(def.workflowId)) {
85
+ seen.set(def.workflowId, summarize(def, path));
86
+ }
87
+ }
88
+ catch {
89
+ // Skip unreadable / unparseable file — see comment block above.
90
+ }
91
+ }
92
+ }
93
+ return [...seen.values()].sort((a, b) => a.workflowId.localeCompare(b.workflowId));
94
+ }
95
+ /**
96
+ * Load a single workflow definition by id and surface its source path +
97
+ * revisionId in the response envelope. Returns `undefined` when no file in
98
+ * any search path resolves the id, so the caller can return 404.
99
+ *
100
+ * `opts.searchPaths` is a test seam; production callers use the default
101
+ * search paths derived from cwd + `$HOME/.botmux/workflows`.
102
+ */
103
+ export async function loadCatalogDefinition(workflowId, opts = {}) {
104
+ const paths = opts.searchPaths ?? workflowDefinitionSearchPaths(workflowId);
105
+ for (const path of paths) {
106
+ try {
107
+ const raw = await fs.readFile(path, 'utf-8');
108
+ const def = parseWorkflowDefinition(JSON.parse(raw));
109
+ return { definition: def, revisionId: computeRevisionId(def), path };
110
+ }
111
+ catch (err) {
112
+ if (err.code === 'ENOENT')
113
+ continue;
114
+ throw err;
115
+ }
116
+ }
117
+ return undefined;
118
+ }
119
+ //# sourceMappingURL=catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/workflows/catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import { EventLog } from './events/append.js';
2
+ import type { RunLoopResult } from './loop.js';
3
+ import type { WorkflowRuntimeContext } from './runtime.js';
4
+ import { type ColdWorkflowRun } from './cold-scan.js';
5
+ export type ColdWorkflowWatcherHandle = {
6
+ ready?: Promise<unknown>;
7
+ };
8
+ export type AttachColdWorkflowRunsOptions = {
9
+ runsDir: string;
10
+ ownerLarkAppId: string;
11
+ isAttached?: (runId: string) => boolean;
12
+ makeContext: (run: ColdWorkflowRun, log: EventLog) => WorkflowRuntimeContext;
13
+ attachWatcher: (runId: string, ctx: WorkflowRuntimeContext) => ColdWorkflowWatcherHandle;
14
+ driveRun: (runId: string, ctx: WorkflowRuntimeContext) => Promise<RunLoopResult>;
15
+ awaitDrive?: boolean;
16
+ onSkip?: (runId: string, reason: string) => void;
17
+ onAttached?: (run: ColdWorkflowRun) => void;
18
+ onDriveError?: (runId: string, err: unknown) => void;
19
+ };
20
+ export type AttachColdWorkflowRunsResult = {
21
+ discovered: number;
22
+ attached: string[];
23
+ };
24
+ /**
25
+ * Daemon cold-start attach path: scan persisted runs owned by this Lark app,
26
+ * attach fan-out watchers, then kick the runtime loop so recovery can settle
27
+ * dangling effects / crashed workers.
28
+ */
29
+ export declare function attachColdWorkflowRunsForDaemon(opts: AttachColdWorkflowRunsOptions): Promise<AttachColdWorkflowRunsResult>;
30
+ //# sourceMappingURL=cold-attach.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cold-attach.d.ts","sourceRoot":"","sources":["../../src/workflows/cold-attach.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,WAAW,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,QAAQ,KAAK,sBAAsB,CAAC;IAC7E,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,sBAAsB,KAAK,yBAAyB,CAAC;IACzF,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,sBAAsB,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC;IACjF,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAsB,+BAA+B,CACnD,IAAI,EAAE,6BAA6B,GAClC,OAAO,CAAC,4BAA4B,CAAC,CAmCvC"}
@@ -0,0 +1,40 @@
1
+ import { EventLog } from './events/append.js';
2
+ import { scanColdWorkflowRuns, } from './cold-scan.js';
3
+ /**
4
+ * Daemon cold-start attach path: scan persisted runs owned by this Lark app,
5
+ * attach fan-out watchers, then kick the runtime loop so recovery can settle
6
+ * dangling effects / crashed workers.
7
+ */
8
+ export async function attachColdWorkflowRunsForDaemon(opts) {
9
+ const runs = await scanColdWorkflowRuns({
10
+ runsDir: opts.runsDir,
11
+ ownerLarkAppId: opts.ownerLarkAppId,
12
+ onSkip: opts.onSkip,
13
+ });
14
+ const attached = [];
15
+ for (const run of runs) {
16
+ if (opts.isAttached?.(run.runId))
17
+ continue;
18
+ const log = new EventLog(run.runId, opts.runsDir);
19
+ const ctx = opts.makeContext(run, log);
20
+ const watcher = opts.attachWatcher(run.runId, ctx);
21
+ try {
22
+ await watcher.ready;
23
+ }
24
+ catch (err) {
25
+ opts.onSkip?.(run.runId, `watcher-start-failed: ${err instanceof Error ? err.message : String(err)}`);
26
+ continue;
27
+ }
28
+ attached.push(run.runId);
29
+ opts.onAttached?.(run);
30
+ const driven = opts.driveRun(run.runId, ctx);
31
+ if (opts.awaitDrive) {
32
+ await driven;
33
+ }
34
+ else {
35
+ driven.catch((err) => opts.onDriveError?.(run.runId, err));
36
+ }
37
+ }
38
+ return { discovered: runs.length, attached };
39
+ }
40
+ //# sourceMappingURL=cold-attach.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cold-attach.js","sourceRoot":"","sources":["../../src/workflows/cold-attach.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,OAAO,EACL,oBAAoB,GAErB,MAAM,gBAAgB,CAAC;AAwBxB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,IAAmC;IAEnC,MAAM,IAAI,GAAG,MAAM,oBAAoB,CAAC;QACtC,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,cAAc,EAAE,IAAI,CAAC,cAAc;QACnC,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IACH,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QAC3C,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACnD,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,KAAK,CAAC;QACtB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,EAAE,CACX,GAAG,CAAC,KAAK,EACT,yBAAyB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAC5E,CAAC;YACF,SAAS;QACX,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACzB,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC;QAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,MAAM,CAAC;QACf,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type WorkflowDefinition } from './definition.js';
2
+ import { type Snapshot } from './events/replay.js';
3
+ import { type RunChatBinding } from './loader.js';
4
+ export type ColdWorkflowRun = {
5
+ runId: string;
6
+ def: WorkflowDefinition;
7
+ snapshot: Snapshot;
8
+ binding: RunChatBinding;
9
+ };
10
+ export type ScanColdWorkflowRunsOptions = {
11
+ runsDir?: string;
12
+ /**
13
+ * Only this daemon should attach runs whose approval cards / IM entrypoint
14
+ * were bound to its Lark app. CLI-only runs have no chat-binding and are
15
+ * skipped; users can recover those via `botmux workflow resume`.
16
+ */
17
+ ownerLarkAppId: string;
18
+ onSkip?: (runId: string, reason: string) => void;
19
+ };
20
+ export declare function scanColdWorkflowRuns(opts: ScanColdWorkflowRunsOptions): Promise<ColdWorkflowRun[]>;
21
+ //# sourceMappingURL=cold-scan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cold-scan.d.ts","sourceRoot":"","sources":["../../src/workflows/cold-scan.ts"],"names":[],"mappings":"AAGA,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEnF,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE3D,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,kBAAkB,CAAC;IACxB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,cAAc,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CAClD,CAAC;AAEF,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,2BAA2B,GAChC,OAAO,CAAC,eAAe,EAAE,CAAC,CAqE5B"}