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.
- package/README.en.md +12 -1
- package/README.md +45 -1
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +11 -0
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/cli/bots-list-output.d.ts +21 -0
- package/dist/cli/bots-list-output.d.ts.map +1 -0
- package/dist/cli/bots-list-output.js +23 -0
- package/dist/cli/bots-list-output.js.map +1 -0
- package/dist/cli/workflow.d.ts +13 -0
- package/dist/cli/workflow.d.ts.map +1 -0
- package/dist/cli/workflow.js +781 -0
- package/dist/cli/workflow.js.map +1 -0
- package/dist/cli.js +69 -14
- package/dist/cli.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +219 -6
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/session-manager.d.ts +6 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +22 -12
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/worker-pool.d.ts +13 -0
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +100 -6
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.d.ts +3 -0
- package/dist/daemon.d.ts.map +1 -1
- package/dist/daemon.js +884 -3
- package/dist/daemon.js.map +1 -1
- package/dist/dashboard/auth.d.ts +36 -0
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +22 -0
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/web/app.js +20 -1
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +356 -0
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/workflow-catalog.d.ts +2 -0
- package/dist/dashboard/web/workflow-catalog.d.ts.map +1 -0
- package/dist/dashboard/web/workflow-catalog.js +323 -0
- package/dist/dashboard/web/workflow-catalog.js.map +1 -0
- package/dist/dashboard/web/workflows.d.ts +2 -0
- package/dist/dashboard/web/workflows.d.ts.map +1 -0
- package/dist/dashboard/web/workflows.js +1618 -0
- package/dist/dashboard/web/workflows.js.map +1 -0
- package/dist/dashboard/workflow-api.d.ts +23 -0
- package/dist/dashboard/workflow-api.d.ts.map +1 -0
- package/dist/dashboard/workflow-api.js +463 -0
- package/dist/dashboard/workflow-api.js.map +1 -0
- package/dist/dashboard-web/app.js +494 -199
- package/dist/dashboard-web/index.html +1 -0
- package/dist/dashboard-web/style.css +160 -6
- package/dist/dashboard-web/terminal-replay.html +227 -0
- package/dist/dashboard.js +29 -12
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +12 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +12 -0
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts +3 -0
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +27 -1
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/client.d.ts +19 -2
- package/dist/im/lark/client.d.ts.map +1 -1
- package/dist/im/lark/client.js +21 -2
- package/dist/im/lark/client.js.map +1 -1
- package/dist/im/lark/workflow-card-handler.d.ts +50 -0
- package/dist/im/lark/workflow-card-handler.d.ts.map +1 -0
- package/dist/im/lark/workflow-card-handler.js +152 -0
- package/dist/im/lark/workflow-card-handler.js.map +1 -0
- package/dist/im/lark/workflow-cards.d.ts +46 -0
- package/dist/im/lark/workflow-cards.d.ts.map +1 -0
- package/dist/im/lark/workflow-cards.js +226 -0
- package/dist/im/lark/workflow-cards.js.map +1 -0
- package/dist/im/lark/workflow-progress-card.d.ts +76 -0
- package/dist/im/lark/workflow-progress-card.d.ts.map +1 -0
- package/dist/im/lark/workflow-progress-card.js +279 -0
- package/dist/im/lark/workflow-progress-card.js.map +1 -0
- package/dist/im/lark/workflow-slash-command.d.ts +92 -0
- package/dist/im/lark/workflow-slash-command.d.ts.map +1 -0
- package/dist/im/lark/workflow-slash-command.js +185 -0
- package/dist/im/lark/workflow-slash-command.js.map +1 -0
- package/dist/services/group-creator.d.ts.map +1 -1
- package/dist/services/group-creator.js +17 -4
- package/dist/services/group-creator.js.map +1 -1
- package/dist/services/groups-store.d.ts +11 -0
- package/dist/services/groups-store.d.ts.map +1 -1
- package/dist/services/groups-store.js +26 -0
- package/dist/services/groups-store.js.map +1 -1
- package/dist/services/jsonl-cursor.d.ts +12 -0
- package/dist/services/jsonl-cursor.d.ts.map +1 -0
- package/dist/services/jsonl-cursor.js +45 -0
- package/dist/services/jsonl-cursor.js.map +1 -0
- package/dist/services/schedule-store.d.ts +35 -0
- package/dist/services/schedule-store.d.ts.map +1 -1
- package/dist/services/schedule-store.js +108 -1
- package/dist/services/schedule-store.js.map +1 -1
- package/dist/skills/definitions.d.ts.map +1 -1
- package/dist/skills/definitions.js +399 -0
- package/dist/skills/definitions.js.map +1 -1
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/cli-usage-limit.d.ts.map +1 -1
- package/dist/utils/cli-usage-limit.js +4 -0
- package/dist/utils/cli-usage-limit.js.map +1 -1
- package/dist/worker.js +118 -14
- package/dist/worker.js.map +1 -1
- package/dist/workflows/attempt-resume.d.ts +114 -0
- package/dist/workflows/attempt-resume.d.ts.map +1 -0
- package/dist/workflows/attempt-resume.js +385 -0
- package/dist/workflows/attempt-resume.js.map +1 -0
- package/dist/workflows/attempt-terminal.d.ts +21 -0
- package/dist/workflows/attempt-terminal.d.ts.map +1 -0
- package/dist/workflows/attempt-terminal.js +7 -0
- package/dist/workflows/attempt-terminal.js.map +1 -0
- package/dist/workflows/blob.d.ts +27 -0
- package/dist/workflows/blob.d.ts.map +1 -0
- package/dist/workflows/blob.js +39 -0
- package/dist/workflows/blob.js.map +1 -0
- package/dist/workflows/cancel-run.d.ts +45 -0
- package/dist/workflows/cancel-run.d.ts.map +1 -0
- package/dist/workflows/cancel-run.js +99 -0
- package/dist/workflows/cancel-run.js.map +1 -0
- package/dist/workflows/cancel.d.ts +111 -0
- package/dist/workflows/cancel.d.ts.map +1 -0
- package/dist/workflows/cancel.js +120 -0
- package/dist/workflows/cancel.js.map +1 -0
- package/dist/workflows/catalog.d.ts +60 -0
- package/dist/workflows/catalog.d.ts.map +1 -0
- package/dist/workflows/catalog.js +119 -0
- package/dist/workflows/catalog.js.map +1 -0
- package/dist/workflows/cold-attach.d.ts +30 -0
- package/dist/workflows/cold-attach.d.ts.map +1 -0
- package/dist/workflows/cold-attach.js +40 -0
- package/dist/workflows/cold-attach.js.map +1 -0
- package/dist/workflows/cold-scan.d.ts +21 -0
- package/dist/workflows/cold-scan.d.ts.map +1 -0
- package/dist/workflows/cold-scan.js +70 -0
- package/dist/workflows/cold-scan.js.map +1 -0
- package/dist/workflows/daemon-spawn.d.ts +117 -0
- package/dist/workflows/daemon-spawn.d.ts.map +1 -0
- package/dist/workflows/daemon-spawn.js +551 -0
- package/dist/workflows/daemon-spawn.js.map +1 -0
- package/dist/workflows/definition.d.ts +1309 -0
- package/dist/workflows/definition.d.ts.map +1 -0
- package/dist/workflows/definition.js +334 -0
- package/dist/workflows/definition.js.map +1 -0
- package/dist/workflows/effect-input.d.ts +4 -0
- package/dist/workflows/effect-input.d.ts.map +1 -0
- package/dist/workflows/effect-input.js +18 -0
- package/dist/workflows/effect-input.js.map +1 -0
- package/dist/workflows/events/append.d.ts +77 -0
- package/dist/workflows/events/append.d.ts.map +1 -0
- package/dist/workflows/events/append.js +214 -0
- package/dist/workflows/events/append.js.map +1 -0
- package/dist/workflows/events/idempotency.d.ts +77 -0
- package/dist/workflows/events/idempotency.d.ts.map +1 -0
- package/dist/workflows/events/idempotency.js +116 -0
- package/dist/workflows/events/idempotency.js.map +1 -0
- package/dist/workflows/events/index.d.ts +7 -0
- package/dist/workflows/events/index.d.ts.map +1 -0
- package/dist/workflows/events/index.js +7 -0
- package/dist/workflows/events/index.js.map +1 -0
- package/dist/workflows/events/payloads.d.ts +917 -0
- package/dist/workflows/events/payloads.d.ts.map +1 -0
- package/dist/workflows/events/payloads.js +337 -0
- package/dist/workflows/events/payloads.js.map +1 -0
- package/dist/workflows/events/replay.d.ts +238 -0
- package/dist/workflows/events/replay.d.ts.map +1 -0
- package/dist/workflows/events/replay.js +608 -0
- package/dist/workflows/events/replay.js.map +1 -0
- package/dist/workflows/events/schema.d.ts +5242 -0
- package/dist/workflows/events/schema.d.ts.map +1 -0
- package/dist/workflows/events/schema.js +295 -0
- package/dist/workflows/events/schema.js.map +1 -0
- package/dist/workflows/events/types.d.ts +34 -0
- package/dist/workflows/events/types.d.ts.map +1 -0
- package/dist/workflows/events/types.js +2 -0
- package/dist/workflows/events/types.js.map +1 -0
- package/dist/workflows/fanout.d.ts +36 -0
- package/dist/workflows/fanout.d.ts.map +1 -0
- package/dist/workflows/fanout.js +114 -0
- package/dist/workflows/fanout.js.map +1 -0
- package/dist/workflows/hostExecutors/botmux-schedule.d.ts +41 -0
- package/dist/workflows/hostExecutors/botmux-schedule.d.ts.map +1 -0
- package/dist/workflows/hostExecutors/botmux-schedule.js +121 -0
- package/dist/workflows/hostExecutors/botmux-schedule.js.map +1 -0
- package/dist/workflows/hostExecutors/feishu-im.d.ts +12 -0
- package/dist/workflows/hostExecutors/feishu-im.d.ts.map +1 -0
- package/dist/workflows/hostExecutors/feishu-im.js +49 -0
- package/dist/workflows/hostExecutors/feishu-im.js.map +1 -0
- package/dist/workflows/hostExecutors/feishu-reply.d.ts +24 -0
- package/dist/workflows/hostExecutors/feishu-reply.d.ts.map +1 -0
- package/dist/workflows/hostExecutors/feishu-reply.js +88 -0
- package/dist/workflows/hostExecutors/feishu-reply.js.map +1 -0
- package/dist/workflows/hostExecutors/feishu-send.d.ts +23 -0
- package/dist/workflows/hostExecutors/feishu-send.d.ts.map +1 -0
- package/dist/workflows/hostExecutors/feishu-send.js +124 -0
- package/dist/workflows/hostExecutors/feishu-send.js.map +1 -0
- package/dist/workflows/hostExecutors/index.d.ts +8 -0
- package/dist/workflows/hostExecutors/index.d.ts.map +1 -0
- package/dist/workflows/hostExecutors/index.js +8 -0
- package/dist/workflows/hostExecutors/index.js.map +1 -0
- package/dist/workflows/hostExecutors/protocol.d.ts +42 -0
- package/dist/workflows/hostExecutors/protocol.d.ts.map +1 -0
- package/dist/workflows/hostExecutors/protocol.js +181 -0
- package/dist/workflows/hostExecutors/protocol.js.map +1 -0
- package/dist/workflows/hostExecutors/registry.d.ts +10 -0
- package/dist/workflows/hostExecutors/registry.d.ts.map +1 -0
- package/dist/workflows/hostExecutors/registry.js +36 -0
- package/dist/workflows/hostExecutors/registry.js.map +1 -0
- package/dist/workflows/hostExecutors/types.d.ts +78 -0
- package/dist/workflows/hostExecutors/types.d.ts.map +1 -0
- package/dist/workflows/hostExecutors/types.js +2 -0
- package/dist/workflows/hostExecutors/types.js.map +1 -0
- package/dist/workflows/loader.d.ts +16 -0
- package/dist/workflows/loader.d.ts.map +1 -0
- package/dist/workflows/loader.js +56 -0
- package/dist/workflows/loader.js.map +1 -0
- package/dist/workflows/loop.d.ts +50 -0
- package/dist/workflows/loop.d.ts.map +1 -0
- package/dist/workflows/loop.js +350 -0
- package/dist/workflows/loop.js.map +1 -0
- package/dist/workflows/ops-projection.d.ts +168 -0
- package/dist/workflows/ops-projection.d.ts.map +1 -0
- package/dist/workflows/ops-projection.js +707 -0
- package/dist/workflows/ops-projection.js.map +1 -0
- package/dist/workflows/orchestrator.d.ts +107 -0
- package/dist/workflows/orchestrator.d.ts.map +1 -0
- package/dist/workflows/orchestrator.js +197 -0
- package/dist/workflows/orchestrator.js.map +1 -0
- package/dist/workflows/output-binding.d.ts +70 -0
- package/dist/workflows/output-binding.d.ts.map +1 -0
- package/dist/workflows/output-binding.js +265 -0
- package/dist/workflows/output-binding.js.map +1 -0
- package/dist/workflows/params.d.ts +61 -0
- package/dist/workflows/params.d.ts.map +1 -0
- package/dist/workflows/params.js +195 -0
- package/dist/workflows/params.js.map +1 -0
- package/dist/workflows/resume.d.ts +263 -0
- package/dist/workflows/resume.d.ts.map +1 -0
- package/dist/workflows/resume.js +808 -0
- package/dist/workflows/resume.js.map +1 -0
- package/dist/workflows/run-id.d.ts +2 -0
- package/dist/workflows/run-id.d.ts.map +1 -0
- package/dist/workflows/run-id.js +7 -0
- package/dist/workflows/run-id.js.map +1 -0
- package/dist/workflows/run-init.d.ts +48 -0
- package/dist/workflows/run-init.d.ts.map +1 -0
- package/dist/workflows/run-init.js +99 -0
- package/dist/workflows/run-init.js.map +1 -0
- package/dist/workflows/runs-dir.d.ts +4 -0
- package/dist/workflows/runs-dir.d.ts.map +1 -0
- package/dist/workflows/runs-dir.js +15 -0
- package/dist/workflows/runs-dir.js.map +1 -0
- package/dist/workflows/runtime.d.ts +211 -0
- package/dist/workflows/runtime.d.ts.map +1 -0
- package/dist/workflows/runtime.js +594 -0
- package/dist/workflows/runtime.js.map +1 -0
- package/dist/workflows/spawn-bot.d.ts +165 -0
- package/dist/workflows/spawn-bot.d.ts.map +1 -0
- package/dist/workflows/spawn-bot.js +215 -0
- package/dist/workflows/spawn-bot.js.map +1 -0
- package/dist/workflows/system.d.ts +49 -0
- package/dist/workflows/system.d.ts.map +1 -0
- package/dist/workflows/system.js +48 -0
- package/dist/workflows/system.js.map +1 -0
- package/dist/workflows/trigger-run.d.ts +70 -0
- package/dist/workflows/trigger-run.d.ts.map +1 -0
- package/dist/workflows/trigger-run.js +88 -0
- package/dist/workflows/trigger-run.js.map +1 -0
- package/dist/workflows/wait.d.ts +120 -0
- package/dist/workflows/wait.d.ts.map +1 -0
- package/dist/workflows/wait.js +181 -0
- package/dist/workflows/wait.js.map +1 -0
- 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"}
|