botmux 2.88.0 → 2.89.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/dist/bot-registry.d.ts +2 -0
- package/dist/bot-registry.d.ts.map +1 -1
- package/dist/bot-registry.js +4 -0
- package/dist/bot-registry.js.map +1 -1
- package/dist/cli/dashboard-endpoint.d.ts.map +1 -1
- package/dist/cli/dashboard-endpoint.js +9 -3
- package/dist/cli/dashboard-endpoint.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -3
- package/dist/cli.js.map +1 -1
- package/dist/core/command-handler.d.ts.map +1 -1
- package/dist/core/command-handler.js +9 -1
- package/dist/core/command-handler.js.map +1 -1
- package/dist/core/dashboard-command/groups.d.ts +20 -0
- package/dist/core/dashboard-command/groups.d.ts.map +1 -0
- package/dist/core/dashboard-command/groups.js +52 -0
- package/dist/core/dashboard-command/groups.js.map +1 -0
- package/dist/core/dashboard-command/index.d.ts +30 -0
- package/dist/core/dashboard-command/index.d.ts.map +1 -0
- package/dist/core/dashboard-command/index.js +81 -0
- package/dist/core/dashboard-command/index.js.map +1 -0
- package/dist/core/dashboard-command/overview.d.ts +29 -0
- package/dist/core/dashboard-command/overview.d.ts.map +1 -0
- package/dist/core/dashboard-command/overview.js +61 -0
- package/dist/core/dashboard-command/overview.js.map +1 -0
- package/dist/core/dashboard-command/owner-gate.d.ts +41 -0
- package/dist/core/dashboard-command/owner-gate.d.ts.map +1 -0
- package/dist/core/dashboard-command/owner-gate.js +40 -0
- package/dist/core/dashboard-command/owner-gate.js.map +1 -0
- package/dist/core/dashboard-command/schedules.d.ts +20 -0
- package/dist/core/dashboard-command/schedules.d.ts.map +1 -0
- package/dist/core/dashboard-command/schedules.js +47 -0
- package/dist/core/dashboard-command/schedules.js.map +1 -0
- package/dist/core/dashboard-command/sessions.d.ts +22 -0
- package/dist/core/dashboard-command/sessions.d.ts.map +1 -0
- package/dist/core/dashboard-command/sessions.js +43 -0
- package/dist/core/dashboard-command/sessions.js.map +1 -0
- package/dist/core/dashboard-command/settings.d.ts +21 -0
- package/dist/core/dashboard-command/settings.d.ts.map +1 -0
- package/dist/core/dashboard-command/settings.js +55 -0
- package/dist/core/dashboard-command/settings.js.map +1 -0
- package/dist/core/dashboard-command/stub.d.ts +16 -0
- package/dist/core/dashboard-command/stub.d.ts.map +1 -0
- package/dist/core/dashboard-command/stub.js +28 -0
- package/dist/core/dashboard-command/stub.js.map +1 -0
- package/dist/core/dashboard-command/workflows.d.ts +20 -0
- package/dist/core/dashboard-command/workflows.d.ts.map +1 -0
- package/dist/core/dashboard-command/workflows.js +45 -0
- package/dist/core/dashboard-command/workflows.js.map +1 -0
- package/dist/core/passthrough-commands.d.ts.map +1 -1
- package/dist/core/passthrough-commands.js +1 -1
- package/dist/core/passthrough-commands.js.map +1 -1
- package/dist/core/session-create.d.ts +0 -1
- package/dist/core/session-create.d.ts.map +1 -1
- package/dist/core/session-create.js +0 -3
- package/dist/core/session-create.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +3 -2
- package/dist/core/session-manager.js.map +1 -1
- package/dist/daemon-internal-client-wrapper.d.ts +41 -0
- package/dist/daemon-internal-client-wrapper.d.ts.map +1 -0
- package/dist/daemon-internal-client-wrapper.js +65 -0
- package/dist/daemon-internal-client-wrapper.js.map +1 -0
- package/dist/dashboard/aggregator.d.ts +12 -0
- package/dist/dashboard/aggregator.d.ts.map +1 -1
- package/dist/dashboard/aggregator.js +16 -0
- package/dist/dashboard/aggregator.js.map +1 -1
- package/dist/dashboard/auth.d.ts +7 -0
- package/dist/dashboard/auth.d.ts.map +1 -1
- package/dist/dashboard/auth.js +21 -0
- package/dist/dashboard/auth.js.map +1 -1
- package/dist/dashboard/card-model-types.d.ts +50 -0
- package/dist/dashboard/card-model-types.d.ts.map +1 -0
- package/dist/dashboard/card-model-types.js +9 -0
- package/dist/dashboard/card-model-types.js.map +1 -0
- package/dist/dashboard/daemon-internal-api.d.ts +90 -0
- package/dist/dashboard/daemon-internal-api.d.ts.map +1 -0
- package/dist/dashboard/daemon-internal-api.js +534 -0
- package/dist/dashboard/daemon-internal-api.js.map +1 -0
- package/dist/dashboard/daemon-internal-auth.d.ts +124 -0
- package/dist/dashboard/daemon-internal-auth.d.ts.map +1 -0
- package/dist/dashboard/daemon-internal-auth.js +188 -0
- package/dist/dashboard/daemon-internal-auth.js.map +1 -0
- package/dist/dashboard/daemon-internal-client.d.ts +67 -0
- package/dist/dashboard/daemon-internal-client.d.ts.map +1 -0
- package/dist/dashboard/daemon-internal-client.js +157 -0
- package/dist/dashboard/daemon-internal-client.js.map +1 -0
- package/dist/dashboard/dashboard-admins.d.ts +8 -0
- package/dist/dashboard/dashboard-admins.d.ts.map +1 -0
- package/dist/dashboard/dashboard-admins.js +15 -0
- package/dist/dashboard/dashboard-admins.js.map +1 -0
- package/dist/dashboard/federation-spoke-api.d.ts +3 -0
- package/dist/dashboard/federation-spoke-api.d.ts.map +1 -1
- package/dist/dashboard/federation-spoke-api.js +11 -8
- package/dist/dashboard/federation-spoke-api.js.map +1 -1
- package/dist/dashboard/groups-action-helpers.d.ts +69 -0
- package/dist/dashboard/groups-action-helpers.d.ts.map +1 -0
- package/dist/dashboard/groups-action-helpers.js +141 -0
- package/dist/dashboard/groups-action-helpers.js.map +1 -0
- package/dist/dashboard/groups-card-model.d.ts +120 -0
- package/dist/dashboard/groups-card-model.d.ts.map +1 -0
- package/dist/dashboard/groups-card-model.js +175 -0
- package/dist/dashboard/groups-card-model.js.map +1 -0
- package/dist/dashboard/schedule-card-model.d.ts +172 -0
- package/dist/dashboard/schedule-card-model.d.ts.map +1 -0
- package/dist/dashboard/schedule-card-model.js +290 -0
- package/dist/dashboard/schedule-card-model.js.map +1 -0
- package/dist/dashboard/session-card-model.d.ts +83 -0
- package/dist/dashboard/session-card-model.d.ts.map +1 -0
- package/dist/dashboard/session-card-model.js +196 -0
- package/dist/dashboard/session-card-model.js.map +1 -0
- package/dist/dashboard/settings-card-model.d.ts +73 -0
- package/dist/dashboard/settings-card-model.d.ts.map +1 -0
- package/dist/dashboard/settings-card-model.js +94 -0
- package/dist/dashboard/settings-card-model.js.map +1 -0
- package/dist/dashboard/settings-owner-resolver.d.ts +32 -0
- package/dist/dashboard/settings-owner-resolver.d.ts.map +1 -0
- package/dist/dashboard/settings-owner-resolver.js +43 -0
- package/dist/dashboard/settings-owner-resolver.js.map +1 -0
- package/dist/dashboard/settings-write-applier.d.ts +84 -0
- package/dist/dashboard/settings-write-applier.d.ts.map +1 -0
- package/dist/dashboard/settings-write-applier.js +119 -0
- package/dist/dashboard/settings-write-applier.js.map +1 -0
- package/dist/dashboard/workflow-api.d.ts.map +1 -1
- package/dist/dashboard/workflow-api.js +38 -119
- package/dist/dashboard/workflow-api.js.map +1 -1
- package/dist/dashboard/workflow-card-model.d.ts +127 -0
- package/dist/dashboard/workflow-card-model.d.ts.map +1 -0
- package/dist/dashboard/workflow-card-model.js +186 -0
- package/dist/dashboard/workflow-card-model.js.map +1 -0
- package/dist/dashboard/workflows-action-helpers.d.ts +105 -0
- package/dist/dashboard/workflows-action-helpers.d.ts.map +1 -0
- package/dist/dashboard/workflows-action-helpers.js +196 -0
- package/dist/dashboard/workflows-action-helpers.js.map +1 -0
- package/dist/dashboard.js +196 -271
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +266 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +266 -0
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +2 -0
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +2 -1
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts +54 -2
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +127 -1
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +22 -0
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/groups-card.d.ts +90 -0
- package/dist/im/lark/groups-card.d.ts.map +1 -0
- package/dist/im/lark/groups-card.js +832 -0
- package/dist/im/lark/groups-card.js.map +1 -0
- package/dist/im/lark/overview-card.d.ts +101 -0
- package/dist/im/lark/overview-card.d.ts.map +1 -0
- package/dist/im/lark/overview-card.js +475 -0
- package/dist/im/lark/overview-card.js.map +1 -0
- package/dist/im/lark/schedules-card.d.ts +96 -0
- package/dist/im/lark/schedules-card.d.ts.map +1 -0
- package/dist/im/lark/schedules-card.js +892 -0
- package/dist/im/lark/schedules-card.js.map +1 -0
- package/dist/im/lark/sessions-card.d.ts +117 -0
- package/dist/im/lark/sessions-card.d.ts.map +1 -0
- package/dist/im/lark/sessions-card.js +870 -0
- package/dist/im/lark/sessions-card.js.map +1 -0
- package/dist/im/lark/settings-card.d.ts +125 -0
- package/dist/im/lark/settings-card.d.ts.map +1 -0
- package/dist/im/lark/settings-card.js +433 -0
- package/dist/im/lark/settings-card.js.map +1 -0
- package/dist/im/lark/workflows-card.d.ts +102 -0
- package/dist/im/lark/workflows-card.d.ts.map +1 -0
- package/dist/im/lark/workflows-card.js +737 -0
- package/dist/im/lark/workflows-card.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflow card model (PR1) — pure projection of workflow run rows and run
|
|
3
|
+
* snapshots into list / detail DTOs. Self-contained: no imports from
|
|
4
|
+
* `src/workflows/`, only `card-model-types.ts` shared types.
|
|
5
|
+
*
|
|
6
|
+
* v1 scope: cancel / approve / reject. Attempt-level resume is NOT exposed.
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_PAGE_SIZE = 20;
|
|
9
|
+
const MAX_PAGE_SIZE = 100;
|
|
10
|
+
const TERMINAL_STATUSES = new Set(['succeeded', 'failed', 'cancelled']);
|
|
11
|
+
/** Map a RunStatus to its UI dot (tone + pulse + i18n label key). Pure, deterministic. */
|
|
12
|
+
export function statusToDot(status) {
|
|
13
|
+
switch (status) {
|
|
14
|
+
case 'pending':
|
|
15
|
+
return { tone: 'neutral', pulse: false, label: 'workflows.status.pending' };
|
|
16
|
+
case 'running':
|
|
17
|
+
return { tone: 'info', pulse: true, label: 'workflows.status.running' };
|
|
18
|
+
case 'waiting':
|
|
19
|
+
return { tone: 'warning', pulse: true, label: 'workflows.status.waiting' };
|
|
20
|
+
case 'succeeded':
|
|
21
|
+
return { tone: 'success', pulse: false, label: 'workflows.status.succeeded' };
|
|
22
|
+
case 'failed':
|
|
23
|
+
return { tone: 'danger', pulse: false, label: 'workflows.status.failed' };
|
|
24
|
+
case 'cancelled':
|
|
25
|
+
return { tone: 'neutral', pulse: false, label: 'workflows.status.cancelled' };
|
|
26
|
+
default:
|
|
27
|
+
return { tone: 'neutral', pulse: false, label: 'workflows.status.unknown' };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Format an elapsed-ms span into a short label, e.g. '12s' / '3m 4s' / '1h 2m' / '2d 3h'. */
|
|
31
|
+
export function formatElapsedMs(elapsedMs) {
|
|
32
|
+
if (!Number.isFinite(elapsedMs) || elapsedMs <= 0)
|
|
33
|
+
return '0s';
|
|
34
|
+
const sec = Math.floor(elapsedMs / 1000);
|
|
35
|
+
if (sec < 60)
|
|
36
|
+
return `${sec}s`;
|
|
37
|
+
const min = Math.floor(sec / 60);
|
|
38
|
+
const remSec = sec % 60;
|
|
39
|
+
if (min < 60)
|
|
40
|
+
return remSec > 0 ? `${min}m ${remSec}s` : `${min}m`;
|
|
41
|
+
const hour = Math.floor(min / 60);
|
|
42
|
+
const remMin = min % 60;
|
|
43
|
+
if (hour < 24)
|
|
44
|
+
return remMin > 0 ? `${hour}h ${remMin}m` : `${hour}h`;
|
|
45
|
+
const day = Math.floor(hour / 24);
|
|
46
|
+
const remHour = hour % 24;
|
|
47
|
+
return remHour > 0 ? `${day}d ${remHour}h` : `${day}d`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Compute Cancel/Approve/Reject button availability.
|
|
51
|
+
* v1: Approve+Reject only when status==='waiting'; Cancel when non-terminal.
|
|
52
|
+
*/
|
|
53
|
+
export function computeActionAvailability(status) {
|
|
54
|
+
const isTerminal = TERMINAL_STATUSES.has(status);
|
|
55
|
+
const isWaiting = status === 'waiting';
|
|
56
|
+
return {
|
|
57
|
+
cancel: isTerminal
|
|
58
|
+
? { enabled: false, reasonKey: 'workflows.action.cancel.terminal' }
|
|
59
|
+
: { enabled: true },
|
|
60
|
+
approve: isWaiting ? { enabled: true } : { enabled: false, reasonKey: 'workflows.action.approve.notWaiting' },
|
|
61
|
+
reject: isWaiting ? { enabled: true } : { enabled: false, reasonKey: 'workflows.action.reject.notWaiting' },
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function progressLabel(nodesDone, nodesTotal) {
|
|
65
|
+
if (typeof nodesDone === 'number' && Number.isFinite(nodesDone) &&
|
|
66
|
+
typeof nodesTotal === 'number' && Number.isFinite(nodesTotal) && nodesTotal > 0) {
|
|
67
|
+
return `第 ${nodesDone}/${nodesTotal} 步`;
|
|
68
|
+
}
|
|
69
|
+
return '';
|
|
70
|
+
}
|
|
71
|
+
/** Build one list-row DTO from a run input. */
|
|
72
|
+
export function projectRunRowDto(input) {
|
|
73
|
+
return {
|
|
74
|
+
runId: input.runId,
|
|
75
|
+
workflowId: input.workflowId,
|
|
76
|
+
status: input.status,
|
|
77
|
+
dot: statusToDot(input.status),
|
|
78
|
+
progressLabel: progressLabel(input.nodesDone, input.nodesTotal),
|
|
79
|
+
startedAtMs: input.startedAt,
|
|
80
|
+
chatBinding: input.chatBinding,
|
|
81
|
+
actions: computeActionAvailability(input.status),
|
|
82
|
+
raw: input,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
/** Build the detail DTO including elapsedMs and a 1-based NodeProgressItem list. */
|
|
86
|
+
export function projectRunDetailDto(input, ctx) {
|
|
87
|
+
const startedFallback = typeof input.startedAt === 'number' ? input.startedAt : input.updatedAt;
|
|
88
|
+
const elapsedMs = typeof startedFallback === 'number' && startedFallback > 0
|
|
89
|
+
? Math.max(0, ctx.nowMs - startedFallback)
|
|
90
|
+
: 0;
|
|
91
|
+
const nodes = (input.nodes ?? []).map((node, i) => ({
|
|
92
|
+
index: i + 1,
|
|
93
|
+
nodeId: node.nodeId,
|
|
94
|
+
name: node.name,
|
|
95
|
+
status: node.status,
|
|
96
|
+
}));
|
|
97
|
+
return {
|
|
98
|
+
runId: input.runId,
|
|
99
|
+
workflowId: input.workflowId,
|
|
100
|
+
status: input.status,
|
|
101
|
+
dot: statusToDot(input.status),
|
|
102
|
+
startedAtMs: input.startedAt,
|
|
103
|
+
updatedAtMs: input.updatedAt,
|
|
104
|
+
finishedAtMs: input.finishedAt,
|
|
105
|
+
elapsedMs,
|
|
106
|
+
elapsedLabel: formatElapsedMs(elapsedMs),
|
|
107
|
+
progressLabel: progressLabel(input.nodesDone, input.nodesTotal),
|
|
108
|
+
nodes,
|
|
109
|
+
chatBinding: input.chatBinding,
|
|
110
|
+
actions: computeActionAvailability(input.status),
|
|
111
|
+
raw: input,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function computeChipCounts(runs) {
|
|
115
|
+
const counts = {
|
|
116
|
+
all: runs.length,
|
|
117
|
+
pending: 0, running: 0, waiting: 0,
|
|
118
|
+
succeeded: 0, failed: 0, cancelled: 0,
|
|
119
|
+
};
|
|
120
|
+
for (const r of runs) {
|
|
121
|
+
switch (r.status) {
|
|
122
|
+
case 'pending':
|
|
123
|
+
counts.pending += 1;
|
|
124
|
+
break;
|
|
125
|
+
case 'running':
|
|
126
|
+
counts.running += 1;
|
|
127
|
+
break;
|
|
128
|
+
case 'waiting':
|
|
129
|
+
counts.waiting += 1;
|
|
130
|
+
break;
|
|
131
|
+
case 'succeeded':
|
|
132
|
+
counts.succeeded += 1;
|
|
133
|
+
break;
|
|
134
|
+
case 'failed':
|
|
135
|
+
counts.failed += 1;
|
|
136
|
+
break;
|
|
137
|
+
case 'cancelled':
|
|
138
|
+
counts.cancelled += 1;
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return counts;
|
|
143
|
+
}
|
|
144
|
+
function clampPageSize(pageSize) {
|
|
145
|
+
if (typeof pageSize !== 'number' || !Number.isFinite(pageSize) || pageSize < 1)
|
|
146
|
+
return DEFAULT_PAGE_SIZE;
|
|
147
|
+
if (pageSize > MAX_PAGE_SIZE)
|
|
148
|
+
return MAX_PAGE_SIZE;
|
|
149
|
+
return Math.floor(pageSize);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Pipeline: search → chipCounts → status filter → paginate → row mapping.
|
|
153
|
+
*
|
|
154
|
+
* `chipCounts` is computed AFTER the search filter but BEFORE the status
|
|
155
|
+
* chip filter, so users get accurate counts per status under their current
|
|
156
|
+
* search context.
|
|
157
|
+
*/
|
|
158
|
+
export function filterAndPaginateRuns(runs, query) {
|
|
159
|
+
let filtered = runs.slice();
|
|
160
|
+
const search = query.search?.trim().toLowerCase();
|
|
161
|
+
if (search && search.length > 0) {
|
|
162
|
+
filtered = filtered.filter(r => r.runId.toLowerCase().includes(search) ||
|
|
163
|
+
(r.workflowId ?? '').toLowerCase().includes(search));
|
|
164
|
+
}
|
|
165
|
+
const chipCounts = computeChipCounts(filtered);
|
|
166
|
+
let statusFiltered = filtered;
|
|
167
|
+
if (query.status && query.status !== 'all') {
|
|
168
|
+
statusFiltered = filtered.filter(r => r.status === query.status);
|
|
169
|
+
}
|
|
170
|
+
const total = statusFiltered.length;
|
|
171
|
+
const pageSize = clampPageSize(query.pageSize);
|
|
172
|
+
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
173
|
+
let page = typeof query.page === 'number' && Number.isFinite(query.page) ? Math.floor(query.page) : 1;
|
|
174
|
+
if (page < 1)
|
|
175
|
+
page = 1;
|
|
176
|
+
if (page > totalPages)
|
|
177
|
+
page = totalPages;
|
|
178
|
+
const start = (page - 1) * pageSize;
|
|
179
|
+
const pageItems = statusFiltered.slice(start, start + pageSize);
|
|
180
|
+
return {
|
|
181
|
+
rows: pageItems.map(projectRunRowDto),
|
|
182
|
+
meta: { page, pageSize, total, totalPages },
|
|
183
|
+
chipCounts,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=workflow-card-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-card-model.js","sourceRoot":"","sources":["../../src/dashboard/workflow-card-model.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqHH,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,iBAAiB,GAAmC,IAAI,GAAG,CAAC,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC;AAExG,0FAA0F;AAC1F,MAAM,UAAU,WAAW,CAAC,MAAkC;IAC5D,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;QAC9E,KAAK,SAAS;YACZ,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;QAC1E,KAAK,SAAS;YACZ,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;QAC7E,KAAK,WAAW;YACd,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;QAChF,KAAK,QAAQ;YACX,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB,EAAE,CAAC;QAC5E,KAAK,WAAW;YACd,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,4BAA4B,EAAE,CAAC;QAChF;YACE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,0BAA0B,EAAE,CAAC;IAChF,CAAC;AACH,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,eAAe,CAAC,SAAiB;IAC/C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACzC,IAAI,GAAG,GAAG,EAAE;QAAE,OAAO,GAAG,GAAG,GAAG,CAAC;IAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IACxB,IAAI,GAAG,GAAG,EAAE;QAAE,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;IACnE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC;IACxB,IAAI,IAAI,GAAG,EAAE;QAAE,OAAO,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,MAAM,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC;IACtE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;IAC1B,OAAO,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC;AACzD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,MAAyB;IACjE,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,SAAS,GAAG,MAAM,KAAK,SAAS,CAAC;IACvC,OAAO;QACL,MAAM,EAAE,UAAU;YAChB,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,kCAAkC,EAAE;YACnE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE;QACrB,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,qCAAqC,EAAE;QAC7G,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,oCAAoC,EAAE;KAC5G,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,SAA6B,EAAE,UAA8B;IAClF,IACE,OAAO,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3D,OAAO,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,GAAG,CAAC,EAC/E,CAAC;QACD,OAAO,KAAK,SAAS,IAAI,UAAU,IAAI,CAAC;IAC1C,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,+CAA+C;AAC/C,MAAM,UAAU,gBAAgB,CAAC,KAAuB;IACtD,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9B,aAAa,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC;QAC/D,WAAW,EAAE,KAAK,CAAC,SAAS;QAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,yBAAyB,CAAC,KAAK,CAAC,MAAM,CAAC;QAChD,GAAG,EAAE,KAAK;KACX,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,mBAAmB,CAAC,KAA6B,EAAE,GAAkB;IACnF,MAAM,eAAe,GAAG,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;IAChG,MAAM,SAAS,GAAG,OAAO,eAAe,KAAK,QAAQ,IAAI,eAAe,GAAG,CAAC;QAC1E,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,GAAG,eAAe,CAAC;QAC1C,CAAC,CAAC,CAAC,CAAC;IACN,MAAM,KAAK,GAAuB,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACtE,KAAK,EAAE,CAAC,GAAG,CAAC;QACZ,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC,CAAC;IACJ,OAAO;QACL,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC;QAC9B,WAAW,EAAE,KAAK,CAAC,SAAS;QAC5B,WAAW,EAAE,KAAK,CAAC,SAAS;QAC5B,YAAY,EAAE,KAAK,CAAC,UAAU;QAC9B,SAAS;QACT,YAAY,EAAE,eAAe,CAAC,SAAS,CAAC;QACxC,aAAa,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC;QAC/D,KAAK;QACL,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,yBAAyB,CAAC,KAAK,CAAC,MAAM,CAAC;QAChD,GAAG,EAAE,KAAK;KACX,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAqC;IAC9D,MAAM,MAAM,GAAuB;QACjC,GAAG,EAAE,IAAI,CAAC,MAAM;QAChB,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;QAClC,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC;KACtC,CAAC;IACF,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,QAAQ,CAAC,CAAC,MAAM,EAAE,CAAC;YACjB,KAAK,SAAS;gBAAE,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;gBAAC,MAAM;YAC3C,KAAK,SAAS;gBAAE,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;gBAAC,MAAM;YAC3C,KAAK,SAAS;gBAAE,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;gBAAC,MAAM;YAC3C,KAAK,WAAW;gBAAE,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;gBAAC,MAAM;YAC/C,KAAK,QAAQ;gBAAE,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;gBAAC,MAAM;YACzC,KAAK,WAAW;gBAAE,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;gBAAC,MAAM;QACjD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,QAA4B;IACjD,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,iBAAiB,CAAC;IACzG,IAAI,QAAQ,GAAG,aAAa;QAAE,OAAO,aAAa,CAAC;IACnD,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAqC,EACrC,KAA0B;IAE1B,IAAI,QAAQ,GAAuB,IAAI,CAAC,KAAK,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAClD,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC7B,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YACtC,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CACpD,CAAC;IACJ,CAAC;IAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IAE/C,IAAI,cAAc,GAAuB,QAAQ,CAAC;IAClD,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;QAC3C,cAAc,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,MAAM,CAAC;IACpC,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC;IAC5D,IAAI,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACtG,IAAI,IAAI,GAAG,CAAC;QAAE,IAAI,GAAG,CAAC,CAAC;IACvB,IAAI,IAAI,GAAG,UAAU;QAAE,IAAI,GAAG,UAAU,CAAC;IACzC,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;IACpC,MAAM,SAAS,GAAG,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,QAAQ,CAAC,CAAC;IAEhE,OAAO;QACL,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACrC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,EAAE;QAC3C,UAAU;KACX,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflows action helpers — single source of truth for the
|
|
3
|
+
* dashboard workflow-runs routes that used to live inline in
|
|
4
|
+
* `workflow-api.ts`.
|
|
5
|
+
*
|
|
6
|
+
* Each helper returns a `HandlerResult { status, body }` so both
|
|
7
|
+
* - the existing `workflow-api.ts handleWorkflowApi` dispatcher, and
|
|
8
|
+
* - the HMAC-gated `/__daemon/workflows-runs/*` route
|
|
9
|
+
* render identical responses. Response shapes, error codes, terminal-state
|
|
10
|
+
* branches, and unauth-scrub semantics are byte-equivalent to the original
|
|
11
|
+
* inline implementation.
|
|
12
|
+
*
|
|
13
|
+
* Attempt resume is intentionally out of scope (cuts it from v1).
|
|
14
|
+
*/
|
|
15
|
+
import type { HandlerResult } from './groups-action-helpers.js';
|
|
16
|
+
export type { HandlerResult } from './groups-action-helpers.js';
|
|
17
|
+
export interface ListRunsOpts {
|
|
18
|
+
all?: boolean;
|
|
19
|
+
statuses?: Set<string>;
|
|
20
|
+
includeBinding?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export interface RunChatBinding {
|
|
23
|
+
chatId: string;
|
|
24
|
+
larkAppId: string;
|
|
25
|
+
}
|
|
26
|
+
export interface RunHeader {
|
|
27
|
+
status: string;
|
|
28
|
+
}
|
|
29
|
+
export interface RunSnapshotLike {
|
|
30
|
+
run: RunHeader;
|
|
31
|
+
chatBinding?: RunChatBinding;
|
|
32
|
+
updatedAt?: number | string;
|
|
33
|
+
lastSeq?: number;
|
|
34
|
+
/** Arbitrary extra fields (preserved through scrub). */
|
|
35
|
+
[key: string]: unknown;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Snapshot type parameterised so concrete callers can plug in the richer
|
|
39
|
+
* `RunSnapshotDTO` from `ops-projection.ts` without lying about types. The
|
|
40
|
+
* helper only touches the fields declared in `RunSnapshotLike`; callers
|
|
41
|
+
* narrow.
|
|
42
|
+
*/
|
|
43
|
+
export interface WorkflowsActionDeps<TSnap extends RunSnapshotLike = RunSnapshotLike> {
|
|
44
|
+
runsDir: string;
|
|
45
|
+
proxyToDaemon: (larkAppId: string, daemonPath: string, init: RequestInit) => Promise<Response>;
|
|
46
|
+
listRuns: (runsDir: string, opts: ListRunsOpts) => Promise<unknown[]>;
|
|
47
|
+
readRunSnapshot: (runsDir: string, runId: string) => Promise<TSnap | undefined | null>;
|
|
48
|
+
scrubSnapshotForUnauthed: (snap: TSnap) => TSnap;
|
|
49
|
+
/** Set of run statuses considered terminal; mirrors `ops-projection.ts:TERMINAL_RUN_STATUSES`. */
|
|
50
|
+
TERMINAL_RUN_STATUSES: ReadonlySet<string>;
|
|
51
|
+
/** Run-id validator (no `..`, no slashes, etc.) — mirrors `ops-projection.ts:isValidRunId`. */
|
|
52
|
+
isValidRunId: (id: string) => boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build a real production deps object for the workflow-runs helpers — wires up
|
|
56
|
+
* the `ops-projection` imports as the snapshot/list source and the caller's
|
|
57
|
+
* own `proxyToDaemon` for owner routing. Tests should pass their own mocks.
|
|
58
|
+
*/
|
|
59
|
+
export declare function defaultWorkflowsActionDeps<TSnap extends RunSnapshotLike = RunSnapshotLike>(opts: {
|
|
60
|
+
runsDir: string;
|
|
61
|
+
proxyToDaemon: (larkAppId: string, daemonPath: string, init: RequestInit) => Promise<Response>;
|
|
62
|
+
listRuns: (runsDir: string, opts: ListRunsOpts) => Promise<unknown[]>;
|
|
63
|
+
readRunSnapshot: (runsDir: string, runId: string) => Promise<TSnap | undefined | null>;
|
|
64
|
+
scrubSnapshotForUnauthed: (snap: TSnap) => TSnap;
|
|
65
|
+
TERMINAL_RUN_STATUSES: ReadonlySet<string>;
|
|
66
|
+
isValidRunId: (id: string) => boolean;
|
|
67
|
+
}): WorkflowsActionDeps<TSnap>;
|
|
68
|
+
/** GET /api/workflows/runs — list snapshot rows, optionally filtered. */
|
|
69
|
+
export declare function listWorkflowRuns(query: {
|
|
70
|
+
all?: boolean;
|
|
71
|
+
statuses?: Set<string>;
|
|
72
|
+
}, deps: WorkflowsActionDeps<any>): Promise<HandlerResult>;
|
|
73
|
+
/**
|
|
74
|
+
* GET /api/workflows/runs/:id/snapshot — public-read with unauth scrub.
|
|
75
|
+
*
|
|
76
|
+
* `authed=true` returns the full snapshot; `authed=false` strips log bytes
|
|
77
|
+
* via `scrubSnapshotForUnauthed` (terminal.log preview can leak env-var dumps
|
|
78
|
+
* and API key errors). Caller decides `authed` from `decideDashboardAuth`.
|
|
79
|
+
*/
|
|
80
|
+
export declare function getRunSnapshot(runId: string, authed: boolean, deps: WorkflowsActionDeps<any>): Promise<HandlerResult>;
|
|
81
|
+
/**
|
|
82
|
+
* POST /api/workflows/runs/:id/(approve|reject) — proxy to the owning daemon.
|
|
83
|
+
*
|
|
84
|
+
* Behaviour mirrors `workflow-api.ts`:
|
|
85
|
+
* - bad_run_id (400) if `isValidRunId` rejects
|
|
86
|
+
* - bad_json (400) on parse failure
|
|
87
|
+
* - unknown_run (404) if snapshot missing
|
|
88
|
+
* - 200 + alreadyTerminal for terminal runs
|
|
89
|
+
* - 409 + needs_lark_or_cli when no chat-binding owner
|
|
90
|
+
* - else proxy + echo upstream response
|
|
91
|
+
*/
|
|
92
|
+
export declare function runApproveReject(runId: string, action: 'approve' | 'reject', bodyRaw: string, deps: WorkflowsActionDeps<any>): Promise<HandlerResult>;
|
|
93
|
+
/**
|
|
94
|
+
* POST /api/workflows/runs/:id/cancel — proxy to the owning daemon.
|
|
95
|
+
*
|
|
96
|
+
* Behaviour mirrors `workflow-api.ts`:
|
|
97
|
+
* - bad_run_id (400) if `isValidRunId` rejects
|
|
98
|
+
* - bad_json (400) on parse failure
|
|
99
|
+
* - unknown_run (404) if snapshot missing
|
|
100
|
+
* - 200 + alreadyTerminal for terminal runs
|
|
101
|
+
* - 409 + needs_cli_cancel when no chat-binding owner
|
|
102
|
+
* - else proxy + echo upstream response
|
|
103
|
+
*/
|
|
104
|
+
export declare function runCancel(runId: string, bodyRaw: string, deps: WorkflowsActionDeps<any>): Promise<HandlerResult>;
|
|
105
|
+
//# sourceMappingURL=workflows-action-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflows-action-helpers.d.ts","sourceRoot":"","sources":["../../src/dashboard/workflows-action-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflows action helpers — single source of truth for the
|
|
3
|
+
* dashboard workflow-runs routes that used to live inline in
|
|
4
|
+
* `workflow-api.ts`.
|
|
5
|
+
*
|
|
6
|
+
* Each helper returns a `HandlerResult { status, body }` so both
|
|
7
|
+
* - the existing `workflow-api.ts handleWorkflowApi` dispatcher, and
|
|
8
|
+
* - the HMAC-gated `/__daemon/workflows-runs/*` route
|
|
9
|
+
* render identical responses. Response shapes, error codes, terminal-state
|
|
10
|
+
* branches, and unauth-scrub semantics are byte-equivalent to the original
|
|
11
|
+
* inline implementation.
|
|
12
|
+
*
|
|
13
|
+
* Attempt resume is intentionally out of scope (cuts it from v1).
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Build a real production deps object for the workflow-runs helpers — wires up
|
|
17
|
+
* the `ops-projection` imports as the snapshot/list source and the caller's
|
|
18
|
+
* own `proxyToDaemon` for owner routing. Tests should pass their own mocks.
|
|
19
|
+
*/
|
|
20
|
+
export function defaultWorkflowsActionDeps(opts) {
|
|
21
|
+
return {
|
|
22
|
+
runsDir: opts.runsDir,
|
|
23
|
+
proxyToDaemon: opts.proxyToDaemon,
|
|
24
|
+
listRuns: opts.listRuns,
|
|
25
|
+
readRunSnapshot: opts.readRunSnapshot,
|
|
26
|
+
scrubSnapshotForUnauthed: opts.scrubSnapshotForUnauthed,
|
|
27
|
+
TERMINAL_RUN_STATUSES: opts.TERMINAL_RUN_STATUSES,
|
|
28
|
+
isValidRunId: opts.isValidRunId,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function safeParseJson(bodyRaw) {
|
|
32
|
+
if (bodyRaw.length === 0)
|
|
33
|
+
return { ok: true, value: {} };
|
|
34
|
+
try {
|
|
35
|
+
return { ok: true, value: JSON.parse(bodyRaw) };
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return { ok: false };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function parseUpstreamBody(text) {
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(text);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return text;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** GET /api/workflows/runs — list snapshot rows, optionally filtered. */
|
|
50
|
+
export async function listWorkflowRuns(query, deps) {
|
|
51
|
+
try {
|
|
52
|
+
const rows = await deps.listRuns(deps.runsDir, {
|
|
53
|
+
all: !!query.all,
|
|
54
|
+
statuses: query.statuses,
|
|
55
|
+
includeBinding: true,
|
|
56
|
+
});
|
|
57
|
+
return { status: 200, body: { runs: rows } };
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
return { status: 500, body: { error: 'listRuns_failed', message: e?.message ?? String(e) } };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* GET /api/workflows/runs/:id/snapshot — public-read with unauth scrub.
|
|
65
|
+
*
|
|
66
|
+
* `authed=true` returns the full snapshot; `authed=false` strips log bytes
|
|
67
|
+
* via `scrubSnapshotForUnauthed` (terminal.log preview can leak env-var dumps
|
|
68
|
+
* and API key errors). Caller decides `authed` from `decideDashboardAuth`.
|
|
69
|
+
*/
|
|
70
|
+
export async function getRunSnapshot(runId, authed, deps) {
|
|
71
|
+
const snap = await deps.readRunSnapshot(deps.runsDir, runId);
|
|
72
|
+
if (!snap)
|
|
73
|
+
return { status: 404, body: { error: 'unknown_run' } };
|
|
74
|
+
return { status: 200, body: authed ? snap : deps.scrubSnapshotForUnauthed(snap) };
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* POST /api/workflows/runs/:id/(approve|reject) — proxy to the owning daemon.
|
|
78
|
+
*
|
|
79
|
+
* Behaviour mirrors `workflow-api.ts`:
|
|
80
|
+
* - bad_run_id (400) if `isValidRunId` rejects
|
|
81
|
+
* - bad_json (400) on parse failure
|
|
82
|
+
* - unknown_run (404) if snapshot missing
|
|
83
|
+
* - 200 + alreadyTerminal for terminal runs
|
|
84
|
+
* - 409 + needs_lark_or_cli when no chat-binding owner
|
|
85
|
+
* - else proxy + echo upstream response
|
|
86
|
+
*/
|
|
87
|
+
export async function runApproveReject(runId, action, bodyRaw, deps) {
|
|
88
|
+
if (!deps.isValidRunId(runId)) {
|
|
89
|
+
return { status: 400, body: { ok: false, error: 'bad_run_id' } };
|
|
90
|
+
}
|
|
91
|
+
const parsed = safeParseJson(bodyRaw);
|
|
92
|
+
if (!parsed.ok)
|
|
93
|
+
return { status: 400, body: { ok: false, error: 'bad_json' } };
|
|
94
|
+
const body = (parsed.value && typeof parsed.value === 'object'
|
|
95
|
+
? parsed.value
|
|
96
|
+
: {});
|
|
97
|
+
const comment = typeof body.comment === 'string' && body.comment.trim()
|
|
98
|
+
? body.comment.trim()
|
|
99
|
+
: undefined;
|
|
100
|
+
const snap = await deps.readRunSnapshot(deps.runsDir, runId);
|
|
101
|
+
if (!snap)
|
|
102
|
+
return { status: 404, body: { ok: false, error: 'unknown_run' } };
|
|
103
|
+
if (deps.TERMINAL_RUN_STATUSES.has(snap.run.status)) {
|
|
104
|
+
return {
|
|
105
|
+
status: 200,
|
|
106
|
+
body: {
|
|
107
|
+
ok: true,
|
|
108
|
+
runId,
|
|
109
|
+
resolution: action === 'approve' ? 'approved' : 'rejected',
|
|
110
|
+
activityId: '',
|
|
111
|
+
attemptId: '',
|
|
112
|
+
resolvedAt: snap.updatedAt,
|
|
113
|
+
lastSeq: snap.lastSeq,
|
|
114
|
+
alreadyTerminal: true,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const owner = snap.chatBinding?.larkAppId;
|
|
119
|
+
if (!owner) {
|
|
120
|
+
return {
|
|
121
|
+
status: 409,
|
|
122
|
+
body: {
|
|
123
|
+
ok: false,
|
|
124
|
+
error: 'needs_lark_or_cli',
|
|
125
|
+
hint: `This run has no chat-binding owner; dashboard approval requires ` +
|
|
126
|
+
`the owning daemon. Use the Lark approval card for now.`,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
const upstream = await deps.proxyToDaemon(owner, `/api/workflows/runs/${encodeURIComponent(runId)}/${action}`, {
|
|
131
|
+
method: 'POST',
|
|
132
|
+
headers: { 'content-type': 'application/json' },
|
|
133
|
+
body: JSON.stringify({ comment }),
|
|
134
|
+
});
|
|
135
|
+
const text = await upstream.text();
|
|
136
|
+
return { status: upstream.status, body: parseUpstreamBody(text) };
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* POST /api/workflows/runs/:id/cancel — proxy to the owning daemon.
|
|
140
|
+
*
|
|
141
|
+
* Behaviour mirrors `workflow-api.ts`:
|
|
142
|
+
* - bad_run_id (400) if `isValidRunId` rejects
|
|
143
|
+
* - bad_json (400) on parse failure
|
|
144
|
+
* - unknown_run (404) if snapshot missing
|
|
145
|
+
* - 200 + alreadyTerminal for terminal runs
|
|
146
|
+
* - 409 + needs_cli_cancel when no chat-binding owner
|
|
147
|
+
* - else proxy + echo upstream response
|
|
148
|
+
*/
|
|
149
|
+
export async function runCancel(runId, bodyRaw, deps) {
|
|
150
|
+
if (!deps.isValidRunId(runId)) {
|
|
151
|
+
return { status: 400, body: { ok: false, error: 'bad_run_id' } };
|
|
152
|
+
}
|
|
153
|
+
const parsed = safeParseJson(bodyRaw);
|
|
154
|
+
if (!parsed.ok)
|
|
155
|
+
return { status: 400, body: { ok: false, error: 'bad_json' } };
|
|
156
|
+
const body = (parsed.value && typeof parsed.value === 'object'
|
|
157
|
+
? parsed.value
|
|
158
|
+
: {});
|
|
159
|
+
const reason = typeof body.reason === 'string' && body.reason.trim()
|
|
160
|
+
? body.reason.trim()
|
|
161
|
+
: 'cancelled via dashboard';
|
|
162
|
+
const snap = await deps.readRunSnapshot(deps.runsDir, runId);
|
|
163
|
+
if (!snap)
|
|
164
|
+
return { status: 404, body: { ok: false, error: 'unknown_run' } };
|
|
165
|
+
if (deps.TERMINAL_RUN_STATUSES.has(snap.run.status)) {
|
|
166
|
+
return {
|
|
167
|
+
status: 200,
|
|
168
|
+
body: {
|
|
169
|
+
ok: true,
|
|
170
|
+
runId,
|
|
171
|
+
status: snap.run.status,
|
|
172
|
+
alreadyTerminal: true,
|
|
173
|
+
lastSeq: snap.lastSeq,
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
const owner = snap.chatBinding?.larkAppId;
|
|
178
|
+
if (!owner) {
|
|
179
|
+
return {
|
|
180
|
+
status: 409,
|
|
181
|
+
body: {
|
|
182
|
+
ok: false,
|
|
183
|
+
error: 'needs_cli_cancel',
|
|
184
|
+
hint: `This run has no chat-binding owner; use 'botmux workflow cancel ${runId}' instead.`,
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
const upstream = await deps.proxyToDaemon(owner, `/api/workflows/runs/${encodeURIComponent(runId)}/cancel`, {
|
|
189
|
+
method: 'POST',
|
|
190
|
+
headers: { 'content-type': 'application/json' },
|
|
191
|
+
body: JSON.stringify({ reason }),
|
|
192
|
+
});
|
|
193
|
+
const text = await upstream.text();
|
|
194
|
+
return { status: upstream.status, body: parseUpstreamBody(text) };
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=workflows-action-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflows-action-helpers.js","sourceRoot":"","sources":["../../src/dashboard/workflows-action-helpers.ts"],"names":[],"mappings":"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"}
|