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.
Files changed (178) hide show
  1. package/dist/bot-registry.d.ts +2 -0
  2. package/dist/bot-registry.d.ts.map +1 -1
  3. package/dist/bot-registry.js +4 -0
  4. package/dist/bot-registry.js.map +1 -1
  5. package/dist/cli/dashboard-endpoint.d.ts.map +1 -1
  6. package/dist/cli/dashboard-endpoint.js +9 -3
  7. package/dist/cli/dashboard-endpoint.js.map +1 -1
  8. package/dist/cli.d.ts.map +1 -1
  9. package/dist/cli.js +11 -3
  10. package/dist/cli.js.map +1 -1
  11. package/dist/core/command-handler.d.ts.map +1 -1
  12. package/dist/core/command-handler.js +9 -1
  13. package/dist/core/command-handler.js.map +1 -1
  14. package/dist/core/dashboard-command/groups.d.ts +20 -0
  15. package/dist/core/dashboard-command/groups.d.ts.map +1 -0
  16. package/dist/core/dashboard-command/groups.js +52 -0
  17. package/dist/core/dashboard-command/groups.js.map +1 -0
  18. package/dist/core/dashboard-command/index.d.ts +30 -0
  19. package/dist/core/dashboard-command/index.d.ts.map +1 -0
  20. package/dist/core/dashboard-command/index.js +81 -0
  21. package/dist/core/dashboard-command/index.js.map +1 -0
  22. package/dist/core/dashboard-command/overview.d.ts +29 -0
  23. package/dist/core/dashboard-command/overview.d.ts.map +1 -0
  24. package/dist/core/dashboard-command/overview.js +61 -0
  25. package/dist/core/dashboard-command/overview.js.map +1 -0
  26. package/dist/core/dashboard-command/owner-gate.d.ts +41 -0
  27. package/dist/core/dashboard-command/owner-gate.d.ts.map +1 -0
  28. package/dist/core/dashboard-command/owner-gate.js +40 -0
  29. package/dist/core/dashboard-command/owner-gate.js.map +1 -0
  30. package/dist/core/dashboard-command/schedules.d.ts +20 -0
  31. package/dist/core/dashboard-command/schedules.d.ts.map +1 -0
  32. package/dist/core/dashboard-command/schedules.js +47 -0
  33. package/dist/core/dashboard-command/schedules.js.map +1 -0
  34. package/dist/core/dashboard-command/sessions.d.ts +22 -0
  35. package/dist/core/dashboard-command/sessions.d.ts.map +1 -0
  36. package/dist/core/dashboard-command/sessions.js +43 -0
  37. package/dist/core/dashboard-command/sessions.js.map +1 -0
  38. package/dist/core/dashboard-command/settings.d.ts +21 -0
  39. package/dist/core/dashboard-command/settings.d.ts.map +1 -0
  40. package/dist/core/dashboard-command/settings.js +55 -0
  41. package/dist/core/dashboard-command/settings.js.map +1 -0
  42. package/dist/core/dashboard-command/stub.d.ts +16 -0
  43. package/dist/core/dashboard-command/stub.d.ts.map +1 -0
  44. package/dist/core/dashboard-command/stub.js +28 -0
  45. package/dist/core/dashboard-command/stub.js.map +1 -0
  46. package/dist/core/dashboard-command/workflows.d.ts +20 -0
  47. package/dist/core/dashboard-command/workflows.d.ts.map +1 -0
  48. package/dist/core/dashboard-command/workflows.js +45 -0
  49. package/dist/core/dashboard-command/workflows.js.map +1 -0
  50. package/dist/core/passthrough-commands.d.ts.map +1 -1
  51. package/dist/core/passthrough-commands.js +1 -1
  52. package/dist/core/passthrough-commands.js.map +1 -1
  53. package/dist/core/session-create.d.ts +0 -1
  54. package/dist/core/session-create.d.ts.map +1 -1
  55. package/dist/core/session-create.js +0 -3
  56. package/dist/core/session-create.js.map +1 -1
  57. package/dist/core/session-manager.d.ts.map +1 -1
  58. package/dist/core/session-manager.js +3 -2
  59. package/dist/core/session-manager.js.map +1 -1
  60. package/dist/daemon-internal-client-wrapper.d.ts +41 -0
  61. package/dist/daemon-internal-client-wrapper.d.ts.map +1 -0
  62. package/dist/daemon-internal-client-wrapper.js +65 -0
  63. package/dist/daemon-internal-client-wrapper.js.map +1 -0
  64. package/dist/dashboard/aggregator.d.ts +12 -0
  65. package/dist/dashboard/aggregator.d.ts.map +1 -1
  66. package/dist/dashboard/aggregator.js +16 -0
  67. package/dist/dashboard/aggregator.js.map +1 -1
  68. package/dist/dashboard/auth.d.ts +7 -0
  69. package/dist/dashboard/auth.d.ts.map +1 -1
  70. package/dist/dashboard/auth.js +21 -0
  71. package/dist/dashboard/auth.js.map +1 -1
  72. package/dist/dashboard/card-model-types.d.ts +50 -0
  73. package/dist/dashboard/card-model-types.d.ts.map +1 -0
  74. package/dist/dashboard/card-model-types.js +9 -0
  75. package/dist/dashboard/card-model-types.js.map +1 -0
  76. package/dist/dashboard/daemon-internal-api.d.ts +90 -0
  77. package/dist/dashboard/daemon-internal-api.d.ts.map +1 -0
  78. package/dist/dashboard/daemon-internal-api.js +534 -0
  79. package/dist/dashboard/daemon-internal-api.js.map +1 -0
  80. package/dist/dashboard/daemon-internal-auth.d.ts +124 -0
  81. package/dist/dashboard/daemon-internal-auth.d.ts.map +1 -0
  82. package/dist/dashboard/daemon-internal-auth.js +188 -0
  83. package/dist/dashboard/daemon-internal-auth.js.map +1 -0
  84. package/dist/dashboard/daemon-internal-client.d.ts +67 -0
  85. package/dist/dashboard/daemon-internal-client.d.ts.map +1 -0
  86. package/dist/dashboard/daemon-internal-client.js +157 -0
  87. package/dist/dashboard/daemon-internal-client.js.map +1 -0
  88. package/dist/dashboard/dashboard-admins.d.ts +8 -0
  89. package/dist/dashboard/dashboard-admins.d.ts.map +1 -0
  90. package/dist/dashboard/dashboard-admins.js +15 -0
  91. package/dist/dashboard/dashboard-admins.js.map +1 -0
  92. package/dist/dashboard/federation-spoke-api.d.ts +3 -0
  93. package/dist/dashboard/federation-spoke-api.d.ts.map +1 -1
  94. package/dist/dashboard/federation-spoke-api.js +11 -8
  95. package/dist/dashboard/federation-spoke-api.js.map +1 -1
  96. package/dist/dashboard/groups-action-helpers.d.ts +69 -0
  97. package/dist/dashboard/groups-action-helpers.d.ts.map +1 -0
  98. package/dist/dashboard/groups-action-helpers.js +141 -0
  99. package/dist/dashboard/groups-action-helpers.js.map +1 -0
  100. package/dist/dashboard/groups-card-model.d.ts +120 -0
  101. package/dist/dashboard/groups-card-model.d.ts.map +1 -0
  102. package/dist/dashboard/groups-card-model.js +175 -0
  103. package/dist/dashboard/groups-card-model.js.map +1 -0
  104. package/dist/dashboard/schedule-card-model.d.ts +172 -0
  105. package/dist/dashboard/schedule-card-model.d.ts.map +1 -0
  106. package/dist/dashboard/schedule-card-model.js +290 -0
  107. package/dist/dashboard/schedule-card-model.js.map +1 -0
  108. package/dist/dashboard/session-card-model.d.ts +83 -0
  109. package/dist/dashboard/session-card-model.d.ts.map +1 -0
  110. package/dist/dashboard/session-card-model.js +196 -0
  111. package/dist/dashboard/session-card-model.js.map +1 -0
  112. package/dist/dashboard/settings-card-model.d.ts +73 -0
  113. package/dist/dashboard/settings-card-model.d.ts.map +1 -0
  114. package/dist/dashboard/settings-card-model.js +94 -0
  115. package/dist/dashboard/settings-card-model.js.map +1 -0
  116. package/dist/dashboard/settings-owner-resolver.d.ts +32 -0
  117. package/dist/dashboard/settings-owner-resolver.d.ts.map +1 -0
  118. package/dist/dashboard/settings-owner-resolver.js +43 -0
  119. package/dist/dashboard/settings-owner-resolver.js.map +1 -0
  120. package/dist/dashboard/settings-write-applier.d.ts +84 -0
  121. package/dist/dashboard/settings-write-applier.d.ts.map +1 -0
  122. package/dist/dashboard/settings-write-applier.js +119 -0
  123. package/dist/dashboard/settings-write-applier.js.map +1 -0
  124. package/dist/dashboard/workflow-api.d.ts.map +1 -1
  125. package/dist/dashboard/workflow-api.js +38 -119
  126. package/dist/dashboard/workflow-api.js.map +1 -1
  127. package/dist/dashboard/workflow-card-model.d.ts +127 -0
  128. package/dist/dashboard/workflow-card-model.d.ts.map +1 -0
  129. package/dist/dashboard/workflow-card-model.js +186 -0
  130. package/dist/dashboard/workflow-card-model.js.map +1 -0
  131. package/dist/dashboard/workflows-action-helpers.d.ts +105 -0
  132. package/dist/dashboard/workflows-action-helpers.d.ts.map +1 -0
  133. package/dist/dashboard/workflows-action-helpers.js +196 -0
  134. package/dist/dashboard/workflows-action-helpers.js.map +1 -0
  135. package/dist/dashboard.js +196 -271
  136. package/dist/dashboard.js.map +1 -1
  137. package/dist/i18n/en.d.ts.map +1 -1
  138. package/dist/i18n/en.js +266 -0
  139. package/dist/i18n/en.js.map +1 -1
  140. package/dist/i18n/zh.d.ts.map +1 -1
  141. package/dist/i18n/zh.js +266 -0
  142. package/dist/i18n/zh.js.map +1 -1
  143. package/dist/im/lark/card-builder.d.ts +2 -0
  144. package/dist/im/lark/card-builder.d.ts.map +1 -1
  145. package/dist/im/lark/card-builder.js +2 -1
  146. package/dist/im/lark/card-builder.js.map +1 -1
  147. package/dist/im/lark/card-handler.d.ts +54 -2
  148. package/dist/im/lark/card-handler.d.ts.map +1 -1
  149. package/dist/im/lark/card-handler.js +127 -1
  150. package/dist/im/lark/card-handler.js.map +1 -1
  151. package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
  152. package/dist/im/lark/event-dispatcher.js +22 -0
  153. package/dist/im/lark/event-dispatcher.js.map +1 -1
  154. package/dist/im/lark/groups-card.d.ts +90 -0
  155. package/dist/im/lark/groups-card.d.ts.map +1 -0
  156. package/dist/im/lark/groups-card.js +832 -0
  157. package/dist/im/lark/groups-card.js.map +1 -0
  158. package/dist/im/lark/overview-card.d.ts +101 -0
  159. package/dist/im/lark/overview-card.d.ts.map +1 -0
  160. package/dist/im/lark/overview-card.js +475 -0
  161. package/dist/im/lark/overview-card.js.map +1 -0
  162. package/dist/im/lark/schedules-card.d.ts +96 -0
  163. package/dist/im/lark/schedules-card.d.ts.map +1 -0
  164. package/dist/im/lark/schedules-card.js +892 -0
  165. package/dist/im/lark/schedules-card.js.map +1 -0
  166. package/dist/im/lark/sessions-card.d.ts +117 -0
  167. package/dist/im/lark/sessions-card.d.ts.map +1 -0
  168. package/dist/im/lark/sessions-card.js +870 -0
  169. package/dist/im/lark/sessions-card.js.map +1 -0
  170. package/dist/im/lark/settings-card.d.ts +125 -0
  171. package/dist/im/lark/settings-card.d.ts.map +1 -0
  172. package/dist/im/lark/settings-card.js +433 -0
  173. package/dist/im/lark/settings-card.js.map +1 -0
  174. package/dist/im/lark/workflows-card.d.ts +102 -0
  175. package/dist/im/lark/workflows-card.d.ts.map +1 -0
  176. package/dist/im/lark/workflows-card.js +737 -0
  177. package/dist/im/lark/workflows-card.js.map +1 -0
  178. 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":"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"}
@@ -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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"}