@h-rig/run-worker 0.0.6-alpha.157 → 0.0.6-alpha.158
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/src/autohost.d.ts +8 -10
- package/dist/src/autohost.js +683 -95
- package/dist/src/constants.d.ts +0 -1
- package/dist/src/constants.js +0 -2
- package/dist/src/extension.js +683 -95
- package/dist/src/host-kernel.d.ts +22 -0
- package/dist/src/host-kernel.js +78 -0
- package/dist/src/host.d.ts +2 -0
- package/dist/src/host.js +419 -0
- package/dist/src/index.d.ts +0 -6
- package/dist/src/index.js +1913 -133
- package/dist/src/local-run-changes.d.ts +3 -0
- package/dist/src/local-run-changes.js +65 -0
- package/dist/src/notifications.js +13 -5
- package/dist/src/notify-cap.d.ts +11 -0
- package/dist/src/notify-cap.js +13 -0
- package/dist/src/panel-plugin.js +3 -7
- package/dist/src/plugin.d.ts +0 -11
- package/dist/src/plugin.js +1910 -101
- package/dist/src/{runs → read-model-backend}/control.d.ts +0 -1
- package/dist/src/{runs → read-model-backend}/control.js +361 -38
- package/dist/src/{runs → read-model-backend}/diagnostics.d.ts +0 -1
- package/dist/src/{runs → read-model-backend}/diagnostics.js +1 -3
- package/dist/src/{runs → read-model-backend}/guard.js +2 -3
- package/dist/src/{runs → read-model-backend}/inbox.js +366 -36
- package/dist/src/{runs → read-model-backend}/index.js +552 -223
- package/dist/src/{runs → read-model-backend}/inspect.d.ts +0 -1
- package/dist/src/{runs → read-model-backend}/inspect.js +350 -34
- package/dist/src/{runs → read-model-backend}/projection.d.ts +21 -7
- package/dist/src/{runs → read-model-backend}/projection.js +349 -31
- package/dist/src/{runs → read-model-backend}/run-status.d.ts +6 -3
- package/dist/src/{runs → read-model-backend}/run-status.js +53 -33
- package/dist/src/{runs → read-model-backend}/stats.d.ts +0 -1
- package/dist/src/{runs → read-model-backend}/stats.js +373 -58
- package/dist/src/read-model-service.d.ts +2 -0
- package/dist/src/read-model-service.js +1433 -0
- package/dist/src/session-journal.d.ts +60 -0
- package/dist/src/session-journal.js +471 -0
- package/dist/src/stall.d.ts +8 -3
- package/dist/src/stall.js +0 -1
- package/dist/src/utils.js +282 -3
- package/package.json +9 -12
- package/dist/src/journal.d.ts +0 -33
- package/dist/src/journal.js +0 -31
- /package/dist/src/{runs → read-model-backend}/guard.d.ts +0 -0
- /package/dist/src/{runs → read-model-backend}/inbox.d.ts +0 -0
- /package/dist/src/{runs → read-model-backend}/index.d.ts +0 -0
|
@@ -16,7 +16,488 @@ var __export = (target, all) => {
|
|
|
16
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
17
|
var __require = import.meta.require;
|
|
18
18
|
|
|
19
|
-
// packages/run-worker/src/
|
|
19
|
+
// packages/run-worker/src/session-journal.ts
|
|
20
|
+
import { Schema } from "effect";
|
|
21
|
+
import {
|
|
22
|
+
CUSTOM_TYPE_FOR,
|
|
23
|
+
RIG_CONTROL_SENTINEL_END,
|
|
24
|
+
RIG_INBOX_RESOLUTION_SENTINEL,
|
|
25
|
+
RIG_PAUSE_SENTINEL,
|
|
26
|
+
RIG_RESUME_SENTINEL,
|
|
27
|
+
RIG_STOP_SENTINEL,
|
|
28
|
+
RIG_STOP_SENTINEL_END,
|
|
29
|
+
RIG_WORKFLOW_STATUS_CHANGED,
|
|
30
|
+
RunJournalEvent,
|
|
31
|
+
TYPE_FOR_CUSTOM
|
|
32
|
+
} from "@rig/contracts";
|
|
33
|
+
function isTerminalRunStatus(status) {
|
|
34
|
+
return TERMINAL_RUN_STATUSES.includes(status);
|
|
35
|
+
}
|
|
36
|
+
function canTransitionRunStatus(from, to) {
|
|
37
|
+
if (from === null)
|
|
38
|
+
return true;
|
|
39
|
+
if (from === to)
|
|
40
|
+
return true;
|
|
41
|
+
return RUN_STATUS_TRANSITIONS[from].includes(to);
|
|
42
|
+
}
|
|
43
|
+
function assertRunStatusTransition(from, to) {
|
|
44
|
+
if (!canTransitionRunStatus(from, to)) {
|
|
45
|
+
throw new Error(`Illegal run status transition: ${from ?? "(none)"} -> ${to}. ` + `Allowed from ${from ?? "(none)"}: ${from ? RUN_STATUS_TRANSITIONS[from].join(", ") : "(any)"}.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function reduceRunJournal(events, runId = null) {
|
|
49
|
+
let record = {};
|
|
50
|
+
let status = null;
|
|
51
|
+
const statusHistory = [];
|
|
52
|
+
const pendingApprovals = new Map;
|
|
53
|
+
const resolvedApprovals = [];
|
|
54
|
+
const pendingUserInputs = new Map;
|
|
55
|
+
const resolvedUserInputs = [];
|
|
56
|
+
const closeoutPhases = [];
|
|
57
|
+
let resolvedPipeline = null;
|
|
58
|
+
const stageOutcomes = [];
|
|
59
|
+
const anomalies = [];
|
|
60
|
+
let steeringCount = 0;
|
|
61
|
+
let stallCount = 0;
|
|
62
|
+
let lastSeq = 0;
|
|
63
|
+
let lastEventAt = null;
|
|
64
|
+
const projectedRunId = runId ?? events[0]?.runId ?? null;
|
|
65
|
+
for (const event of events) {
|
|
66
|
+
lastSeq = event.seq;
|
|
67
|
+
lastEventAt = event.at;
|
|
68
|
+
switch (event.type) {
|
|
69
|
+
case "status-changed": {
|
|
70
|
+
if (!canTransitionRunStatus(status, event.to)) {
|
|
71
|
+
anomalies.push({ seq: event.seq, kind: "illegal-transition", detail: `${status ?? "(none)"} -> ${event.to}` });
|
|
72
|
+
}
|
|
73
|
+
statusHistory.push({ seq: event.seq, at: event.at, from: status, to: event.to, reason: event.reason ?? null });
|
|
74
|
+
const wasTerminal = status !== null && isTerminalRunStatus(status);
|
|
75
|
+
status = event.to;
|
|
76
|
+
record = { ...record, updatedAt: event.at };
|
|
77
|
+
if (isTerminalRunStatus(event.to) && !record.completedAt)
|
|
78
|
+
record = { ...record, completedAt: event.at };
|
|
79
|
+
if (!isTerminalRunStatus(event.to) && wasTerminal)
|
|
80
|
+
record = { ...record, completedAt: null };
|
|
81
|
+
if (event.to === "running" && !record.startedAt)
|
|
82
|
+
record = { ...record, startedAt: event.at };
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
case "record-patch": {
|
|
86
|
+
const next = { ...record };
|
|
87
|
+
for (const [key, value] of Object.entries(event.patch)) {
|
|
88
|
+
if (value !== undefined)
|
|
89
|
+
next[key] = value;
|
|
90
|
+
}
|
|
91
|
+
next.updatedAt = event.patch.updatedAt ?? event.at;
|
|
92
|
+
record = next;
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
case "approval-requested": {
|
|
96
|
+
pendingApprovals.set(event.requestId, {
|
|
97
|
+
requestId: event.requestId,
|
|
98
|
+
requestKind: event.requestKind,
|
|
99
|
+
actionId: event.actionId ?? null,
|
|
100
|
+
payload: event.payload,
|
|
101
|
+
requestedAt: event.at
|
|
102
|
+
});
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case "approval-resolved": {
|
|
106
|
+
const pending = pendingApprovals.get(event.requestId);
|
|
107
|
+
if (!pending) {
|
|
108
|
+
const alreadyResolved = resolvedApprovals.some((entry) => entry.requestId === event.requestId);
|
|
109
|
+
anomalies.push({ seq: event.seq, kind: alreadyResolved ? "duplicate-resolution" : "unknown-request", detail: `approval ${event.requestId}` });
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
pendingApprovals.delete(event.requestId);
|
|
113
|
+
resolvedApprovals.push({ ...pending, decision: event.decision, note: event.note ?? null, actor: event.actor, resolvedAt: event.at });
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
case "input-requested": {
|
|
117
|
+
pendingUserInputs.set(event.requestId, {
|
|
118
|
+
requestId: event.requestId,
|
|
119
|
+
requestKind: "user-input",
|
|
120
|
+
actionId: null,
|
|
121
|
+
payload: event.payload,
|
|
122
|
+
requestedAt: event.at
|
|
123
|
+
});
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
case "input-resolved": {
|
|
127
|
+
const pending = pendingUserInputs.get(event.requestId);
|
|
128
|
+
if (!pending) {
|
|
129
|
+
const alreadyResolved = resolvedUserInputs.some((entry) => entry.requestId === event.requestId);
|
|
130
|
+
anomalies.push({ seq: event.seq, kind: alreadyResolved ? "duplicate-resolution" : "unknown-request", detail: `user-input ${event.requestId}` });
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
pendingUserInputs.delete(event.requestId);
|
|
134
|
+
resolvedUserInputs.push({ ...pending, answers: event.answers, actor: event.actor, resolvedAt: event.at });
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
case "steering":
|
|
138
|
+
steeringCount += 1;
|
|
139
|
+
break;
|
|
140
|
+
case "adopted":
|
|
141
|
+
record = { ...record, pid: event.pid, updatedAt: event.at };
|
|
142
|
+
break;
|
|
143
|
+
case "stall-detected":
|
|
144
|
+
stallCount += 1;
|
|
145
|
+
break;
|
|
146
|
+
case "closeout-phase":
|
|
147
|
+
closeoutPhases.push({ seq: event.seq, at: event.at, phase: event.phase, outcome: event.outcome, detail: event.detail ?? null });
|
|
148
|
+
break;
|
|
149
|
+
case "pipeline-resolved":
|
|
150
|
+
resolvedPipeline = event.pipeline;
|
|
151
|
+
break;
|
|
152
|
+
case "stage-outcome":
|
|
153
|
+
stageOutcomes.push({ seq: event.seq, at: event.at, outcome: event.outcome });
|
|
154
|
+
break;
|
|
155
|
+
case "timeline-entry":
|
|
156
|
+
case "log-entry":
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
runId: projectedRunId,
|
|
162
|
+
record,
|
|
163
|
+
status,
|
|
164
|
+
statusHistory,
|
|
165
|
+
pendingApprovals: [...pendingApprovals.values()],
|
|
166
|
+
resolvedApprovals,
|
|
167
|
+
pendingUserInputs: [...pendingUserInputs.values()],
|
|
168
|
+
resolvedUserInputs,
|
|
169
|
+
steeringCount,
|
|
170
|
+
stallCount,
|
|
171
|
+
closeoutPhases,
|
|
172
|
+
resolvedPipeline,
|
|
173
|
+
stageOutcomes,
|
|
174
|
+
lastSeq,
|
|
175
|
+
lastEventAt,
|
|
176
|
+
anomalies
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function isRunSessionCustomType(customType) {
|
|
180
|
+
return customType !== undefined && Object.hasOwn(TYPE_FOR_CUSTOM, customType);
|
|
181
|
+
}
|
|
182
|
+
function foldRunSessionEntries(entries, runId) {
|
|
183
|
+
const events = [];
|
|
184
|
+
entries.forEach((entry, index) => {
|
|
185
|
+
if (entry.type !== "custom" || !isRunSessionCustomType(entry.customType))
|
|
186
|
+
return;
|
|
187
|
+
const data = entry.data !== null && typeof entry.data === "object" ? entry.data : {};
|
|
188
|
+
const stamped = {
|
|
189
|
+
v: 1,
|
|
190
|
+
seq: index + 1,
|
|
191
|
+
at: typeof data.at === "string" ? data.at : new Date(0).toISOString(),
|
|
192
|
+
runId,
|
|
193
|
+
...data,
|
|
194
|
+
type: TYPE_FOR_CUSTOM[entry.customType]
|
|
195
|
+
};
|
|
196
|
+
try {
|
|
197
|
+
events.push(decodeRunJournalEvent(stamped));
|
|
198
|
+
} catch {}
|
|
199
|
+
});
|
|
200
|
+
return reduceRunJournal(events, runId);
|
|
201
|
+
}
|
|
202
|
+
function isRecord(value) {
|
|
203
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
204
|
+
}
|
|
205
|
+
function timelineEntryFromCustomEntry(entry) {
|
|
206
|
+
if (entry.customType !== CUSTOM_TYPE_FOR["timeline-entry"] || !isRecord(entry.data))
|
|
207
|
+
return null;
|
|
208
|
+
const payload = isRecord(entry.data.payload) ? entry.data.payload : entry.data;
|
|
209
|
+
const type = typeof payload.type === "string" ? payload.type : "timeline";
|
|
210
|
+
const stage = typeof payload.stage === "string" ? payload.stage : typeof payload.name === "string" ? payload.name : null;
|
|
211
|
+
const status = typeof payload.status === "string" ? payload.status : typeof payload.outcome === "string" ? payload.outcome : null;
|
|
212
|
+
const detail = typeof payload.detail === "string" ? payload.detail : typeof payload.message === "string" ? payload.message : null;
|
|
213
|
+
const at = typeof entry.data.at === "string" ? entry.data.at : typeof payload.at === "string" ? payload.at : null;
|
|
214
|
+
return { at, type, stage, status, detail };
|
|
215
|
+
}
|
|
216
|
+
function timelineEntriesFromCustomEntries(entries) {
|
|
217
|
+
return entries.flatMap((entry) => {
|
|
218
|
+
const timelineEntry = timelineEntryFromCustomEntry(entry);
|
|
219
|
+
return timelineEntry ? [timelineEntry] : [];
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
function asCustomEntries(entries) {
|
|
223
|
+
return entries.filter((entry) => entry.type === "custom");
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
class RunSessionJournal {
|
|
227
|
+
sm;
|
|
228
|
+
runId;
|
|
229
|
+
constructor(sm, runId) {
|
|
230
|
+
this.sm = sm;
|
|
231
|
+
this.runId = runId;
|
|
232
|
+
}
|
|
233
|
+
#append(init) {
|
|
234
|
+
this.sm.appendCustomEntry(CUSTOM_TYPE_FOR[init.type], { ...init, at: new Date().toISOString() });
|
|
235
|
+
}
|
|
236
|
+
appendStatus(to, opts = {}) {
|
|
237
|
+
const from = foldRunSessionEntries(asCustomEntries(this.sm.getEntries()), this.runId).status;
|
|
238
|
+
if (!opts.force)
|
|
239
|
+
assertRunStatusTransition(from, to);
|
|
240
|
+
if (opts.errorText !== undefined)
|
|
241
|
+
this.#append({ type: "record-patch", patch: { errorText: opts.errorText } });
|
|
242
|
+
this.#append({
|
|
243
|
+
type: "status-changed",
|
|
244
|
+
from,
|
|
245
|
+
to,
|
|
246
|
+
...opts.reason !== undefined ? { reason: opts.reason } : {},
|
|
247
|
+
...opts.actor !== undefined ? { actor: opts.actor } : {}
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
appendTimeline(payload) {
|
|
251
|
+
this.#append({ type: "timeline-entry", payload });
|
|
252
|
+
}
|
|
253
|
+
appendCloseoutPhase(input) {
|
|
254
|
+
this.#append({
|
|
255
|
+
type: "closeout-phase",
|
|
256
|
+
phase: input.phase,
|
|
257
|
+
outcome: input.outcome,
|
|
258
|
+
...input.detail !== undefined ? { detail: input.detail } : {}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
appendApprovalResolved(input) {
|
|
262
|
+
this.#append({
|
|
263
|
+
type: "approval-resolved",
|
|
264
|
+
requestId: input.requestId,
|
|
265
|
+
decision: input.decision,
|
|
266
|
+
actor: input.actor,
|
|
267
|
+
...input.note !== undefined ? { note: input.note } : {}
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
appendInputResolved(input) {
|
|
271
|
+
this.#append({ type: "input-resolved", requestId: input.requestId, answers: input.answers, actor: input.actor });
|
|
272
|
+
}
|
|
273
|
+
appendStall(input) {
|
|
274
|
+
this.#append({ type: "stall-detected", detail: input.detail });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
var decodeRunJournalEvent, RUN_STATUS_TRANSITIONS, TERMINAL_RUN_STATUSES;
|
|
278
|
+
var init_session_journal = __esm(() => {
|
|
279
|
+
decodeRunJournalEvent = Schema.decodeUnknownSync(RunJournalEvent);
|
|
280
|
+
RUN_STATUS_TRANSITIONS = {
|
|
281
|
+
created: ["queued", "preparing", "running", "failed", "stopped"],
|
|
282
|
+
queued: ["preparing", "running", "failed", "stopped"],
|
|
283
|
+
preparing: ["queued", "running", "needs-attention", "failed", "stopped"],
|
|
284
|
+
running: [
|
|
285
|
+
"queued",
|
|
286
|
+
"waiting-approval",
|
|
287
|
+
"waiting-user-input",
|
|
288
|
+
"paused",
|
|
289
|
+
"validating",
|
|
290
|
+
"reviewing",
|
|
291
|
+
"closing-out",
|
|
292
|
+
"needs-attention",
|
|
293
|
+
"completed",
|
|
294
|
+
"failed",
|
|
295
|
+
"stopped"
|
|
296
|
+
],
|
|
297
|
+
"waiting-approval": ["running", "needs-attention", "failed", "stopped"],
|
|
298
|
+
"waiting-user-input": ["running", "needs-attention", "failed", "stopped"],
|
|
299
|
+
paused: ["running", "failed", "stopped"],
|
|
300
|
+
validating: ["running", "reviewing", "closing-out", "needs-attention", "completed", "failed", "stopped"],
|
|
301
|
+
reviewing: ["running", "validating", "closing-out", "needs-attention", "completed", "failed", "stopped"],
|
|
302
|
+
"closing-out": ["running", "needs-attention", "completed", "failed", "stopped"],
|
|
303
|
+
"needs-attention": ["queued", "preparing", "running", "closing-out", "completed", "failed", "stopped"],
|
|
304
|
+
completed: [],
|
|
305
|
+
failed: ["queued", "preparing", "running", "closing-out"],
|
|
306
|
+
stopped: ["queued", "preparing", "running", "closing-out"]
|
|
307
|
+
};
|
|
308
|
+
TERMINAL_RUN_STATUSES = ["completed", "failed", "stopped"];
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
// packages/run-worker/src/read-model-backend/run-status.ts
|
|
312
|
+
import { OPERATOR_INACTIVE_RUN_STATUSES } from "@rig/contracts";
|
|
313
|
+
function isTerminalRunStatus2(status) {
|
|
314
|
+
return TERMINAL_RUN_STATUSES2.includes(status);
|
|
315
|
+
}
|
|
316
|
+
function isActiveRunStatus(status) {
|
|
317
|
+
return !isTerminalRunStatus2(status);
|
|
318
|
+
}
|
|
319
|
+
function normalizeRunStatusToken(status) {
|
|
320
|
+
return String(status ?? "").trim().toLowerCase().replace(/[\s_]+/g, "-");
|
|
321
|
+
}
|
|
322
|
+
function isOperatorActiveRunStatus(status) {
|
|
323
|
+
const normalized = normalizeRunStatusToken(status);
|
|
324
|
+
if (!normalized)
|
|
325
|
+
return false;
|
|
326
|
+
return !OPERATOR_INACTIVE_RUN_STATUSES.has(normalized);
|
|
327
|
+
}
|
|
328
|
+
function canonicalStatusToken(status) {
|
|
329
|
+
const normalized = normalizeRunStatusToken(status);
|
|
330
|
+
if (normalized === "waiting-input")
|
|
331
|
+
return "waiting-user-input";
|
|
332
|
+
return normalized;
|
|
333
|
+
}
|
|
334
|
+
function asRunStatus(status) {
|
|
335
|
+
return KNOWN_RUN_STATUS[status] ? status : null;
|
|
336
|
+
}
|
|
337
|
+
function statusColorRole(status) {
|
|
338
|
+
switch (canonicalStatusToken(status)) {
|
|
339
|
+
case "done":
|
|
340
|
+
case "completed":
|
|
341
|
+
case "ready":
|
|
342
|
+
case "healthy":
|
|
343
|
+
case "approved":
|
|
344
|
+
case "merged":
|
|
345
|
+
return "success";
|
|
346
|
+
case "needs-attention":
|
|
347
|
+
case "waiting-approval":
|
|
348
|
+
case "waiting-user-input":
|
|
349
|
+
case "blocked":
|
|
350
|
+
case "paused":
|
|
351
|
+
return "action-yellow";
|
|
352
|
+
case "running":
|
|
353
|
+
case "adopted":
|
|
354
|
+
case "preparing":
|
|
355
|
+
case "created":
|
|
356
|
+
case "queued":
|
|
357
|
+
case "starting":
|
|
358
|
+
case "pending":
|
|
359
|
+
case "in-progress":
|
|
360
|
+
case "active":
|
|
361
|
+
case "booting":
|
|
362
|
+
case "validating":
|
|
363
|
+
case "reviewing":
|
|
364
|
+
case "closing-out":
|
|
365
|
+
return "active-cyan";
|
|
366
|
+
case "failed":
|
|
367
|
+
case "error":
|
|
368
|
+
case "rejected":
|
|
369
|
+
return "failure";
|
|
370
|
+
case "stopped":
|
|
371
|
+
case "cancelled":
|
|
372
|
+
case "canceled":
|
|
373
|
+
case "stale":
|
|
374
|
+
return "muted";
|
|
375
|
+
default:
|
|
376
|
+
return "neutral";
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
function isNeedsAttention(run) {
|
|
380
|
+
return canonicalStatusToken(run.status) === "needs-attention" || run.pendingApprovals + run.pendingInputs > 0 || run.stallCount > 0;
|
|
381
|
+
}
|
|
382
|
+
function phaseForStatus(status, runStatus, needsAttention) {
|
|
383
|
+
if (runStatus && isTerminalRunStatus2(runStatus))
|
|
384
|
+
return runStatus === "completed" || runStatus === "failed" || runStatus === "stopped" ? runStatus : "stopped";
|
|
385
|
+
if (needsAttention)
|
|
386
|
+
return "needs-attention";
|
|
387
|
+
switch (status) {
|
|
388
|
+
case "created":
|
|
389
|
+
case "queued":
|
|
390
|
+
case "preparing":
|
|
391
|
+
case "starting":
|
|
392
|
+
case "booting":
|
|
393
|
+
return "starting";
|
|
394
|
+
case "waiting-approval":
|
|
395
|
+
case "waiting-user-input":
|
|
396
|
+
return "waiting";
|
|
397
|
+
case "paused":
|
|
398
|
+
return "paused";
|
|
399
|
+
case "running":
|
|
400
|
+
case "validating":
|
|
401
|
+
case "reviewing":
|
|
402
|
+
case "closing-out":
|
|
403
|
+
return "active";
|
|
404
|
+
default:
|
|
405
|
+
return runStatus && isActiveRunStatus(runStatus) ? "active" : "unknown";
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
function classifyRun(run) {
|
|
409
|
+
const status = canonicalStatusToken(run.status) || (run.live && !run.stale ? "starting" : "unknown");
|
|
410
|
+
const runStatus = asRunStatus(status);
|
|
411
|
+
const isTerminal = runStatus ? isTerminalRunStatus2(runStatus) : false;
|
|
412
|
+
const isNeedsAttentionValue = isNeedsAttention(run);
|
|
413
|
+
return {
|
|
414
|
+
status,
|
|
415
|
+
phase: phaseForStatus(status, runStatus, isNeedsAttentionValue),
|
|
416
|
+
isActive: runStatus ? isActiveRunStatus(runStatus) : !isTerminal && status !== "unknown",
|
|
417
|
+
isTerminal,
|
|
418
|
+
isNeedsAttention: isNeedsAttentionValue
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function runStatusText(run) {
|
|
422
|
+
return classifyRun(run).status;
|
|
423
|
+
}
|
|
424
|
+
function runStatusColorRole(run) {
|
|
425
|
+
const classification = classifyRun(run);
|
|
426
|
+
return classification.isNeedsAttention && !classification.isTerminal ? "action-yellow" : statusColorRole(classification.status);
|
|
427
|
+
}
|
|
428
|
+
function statusRank(run) {
|
|
429
|
+
const classification = classifyRun(run);
|
|
430
|
+
if (classification.isNeedsAttention)
|
|
431
|
+
return 0;
|
|
432
|
+
switch (classification.phase) {
|
|
433
|
+
case "needs-attention":
|
|
434
|
+
return 0;
|
|
435
|
+
case "active":
|
|
436
|
+
case "waiting":
|
|
437
|
+
case "paused":
|
|
438
|
+
return 1;
|
|
439
|
+
case "starting":
|
|
440
|
+
return 2;
|
|
441
|
+
case "completed":
|
|
442
|
+
return 3;
|
|
443
|
+
case "failed":
|
|
444
|
+
return 4;
|
|
445
|
+
case "stopped":
|
|
446
|
+
return 5;
|
|
447
|
+
case "unknown":
|
|
448
|
+
return 6;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
function isSteerableStatus(status) {
|
|
452
|
+
switch (status) {
|
|
453
|
+
case "needs-attention":
|
|
454
|
+
case "waiting-approval":
|
|
455
|
+
case "waiting-user-input":
|
|
456
|
+
case "paused":
|
|
457
|
+
return false;
|
|
458
|
+
default: {
|
|
459
|
+
const runStatus = asRunStatus(status);
|
|
460
|
+
return runStatus ? isActiveRunStatus(runStatus) : false;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
function canSteer(run) {
|
|
465
|
+
const classification = classifyRun(run);
|
|
466
|
+
if (classification.phase === "active" || classification.phase === "starting")
|
|
467
|
+
return true;
|
|
468
|
+
return classification.isNeedsAttention && isSteerableStatus(classification.status);
|
|
469
|
+
}
|
|
470
|
+
function canStop(run) {
|
|
471
|
+
const classification = classifyRun(run);
|
|
472
|
+
return classification.isActive && !classification.isTerminal;
|
|
473
|
+
}
|
|
474
|
+
function canPause(run) {
|
|
475
|
+
const phase = classifyRun(run).phase;
|
|
476
|
+
return phase === "active" || phase === "starting";
|
|
477
|
+
}
|
|
478
|
+
function canResume(run) {
|
|
479
|
+
return classifyRun(run).phase === "paused";
|
|
480
|
+
}
|
|
481
|
+
var TERMINAL_RUN_STATUSES2, ACTIVE_RUN_STATUSES, KNOWN_RUN_STATUS;
|
|
482
|
+
var init_run_status = __esm(() => {
|
|
483
|
+
TERMINAL_RUN_STATUSES2 = ["completed", "failed", "stopped"];
|
|
484
|
+
ACTIVE_RUN_STATUSES = [
|
|
485
|
+
"created",
|
|
486
|
+
"queued",
|
|
487
|
+
"preparing",
|
|
488
|
+
"running",
|
|
489
|
+
"waiting-approval",
|
|
490
|
+
"waiting-user-input",
|
|
491
|
+
"paused",
|
|
492
|
+
"validating",
|
|
493
|
+
"reviewing",
|
|
494
|
+
"closing-out",
|
|
495
|
+
"needs-attention"
|
|
496
|
+
];
|
|
497
|
+
KNOWN_RUN_STATUS = Object.fromEntries([...ACTIVE_RUN_STATUSES, ...TERMINAL_RUN_STATUSES2].map((status) => [status, true]));
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
// packages/run-worker/src/read-model-backend/diagnostics.ts
|
|
20
501
|
function normalizeString(value) {
|
|
21
502
|
if (typeof value !== "string")
|
|
22
503
|
return null;
|
|
@@ -63,13 +544,12 @@ function summarizeRunError(projection) {
|
|
|
63
544
|
const nonGeneric = candidates.filter((candidate) => !isGenericRunFailure(candidate));
|
|
64
545
|
return categorizeUsefulRunError(nonGeneric) ?? nonGeneric.at(-1) ?? normalizeString(projection.record.errorText);
|
|
65
546
|
}
|
|
66
|
-
var init_diagnostics = () => {};
|
|
67
547
|
|
|
68
|
-
// packages/run-worker/src/
|
|
548
|
+
// packages/run-worker/src/read-model-backend/projection.ts
|
|
69
549
|
var exports_projection = {};
|
|
70
550
|
__export(exports_projection, {
|
|
71
551
|
selectRunProjection: () => selectRunProjection,
|
|
72
|
-
|
|
552
|
+
runRecordsFromCollab: () => runRecordsFromCollab,
|
|
73
553
|
runRecordFromRegistryEntry: () => runRecordFromRegistryEntry,
|
|
74
554
|
resolveRunJoinTarget: () => resolveRunJoinTarget,
|
|
75
555
|
resolveJoinTarget: () => resolveJoinTarget,
|
|
@@ -82,13 +562,28 @@ __export(exports_projection, {
|
|
|
82
562
|
});
|
|
83
563
|
import { existsSync, readFileSync } from "fs";
|
|
84
564
|
import { isAbsolute, relative, resolve } from "path";
|
|
85
|
-
import {
|
|
86
|
-
import {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
565
|
+
import { RUN_DISCOVERY } from "@rig/contracts";
|
|
566
|
+
import { loadCapabilityForRoot } from "@rig/core/capability-loaders";
|
|
567
|
+
import { defineCapability } from "@rig/core/capability";
|
|
568
|
+
function registryEntryFromCollab(collab) {
|
|
569
|
+
const record = collab;
|
|
570
|
+
return {
|
|
571
|
+
roomId: collab.sessionId,
|
|
572
|
+
title: collab.title,
|
|
573
|
+
status: record.registryStatus ?? (collab.stale ? "stale" : "running"),
|
|
574
|
+
startedAt: collab.startedAt ?? null,
|
|
575
|
+
heartbeatAt: collab.updatedAt ?? null,
|
|
576
|
+
sessionPath: collab.sessionPath ?? null,
|
|
577
|
+
cwd: collab.cwd ?? null,
|
|
578
|
+
joinLink: collab.joinLink ?? null,
|
|
579
|
+
webLink: collab.webLink ?? null,
|
|
580
|
+
relayUrl: collab.relayUrl ?? null,
|
|
581
|
+
stale: collab.stale,
|
|
582
|
+
repo: collab.selectedRepo ?? null,
|
|
583
|
+
...collab.pid === undefined ? {} : { pid: collab.pid },
|
|
584
|
+
projection: record.registryProjection ?? null
|
|
585
|
+
};
|
|
586
|
+
}
|
|
92
587
|
function readSessionRunEntries(sessionPath) {
|
|
93
588
|
if (!sessionPath || !existsSync(sessionPath))
|
|
94
589
|
return [];
|
|
@@ -133,22 +628,7 @@ function registryStatusAsRunStatus(status) {
|
|
|
133
628
|
return "waiting-user-input";
|
|
134
629
|
if (status === "starting")
|
|
135
630
|
return "preparing";
|
|
136
|
-
return typeof status === "string"
|
|
137
|
-
"created",
|
|
138
|
-
"queued",
|
|
139
|
-
"preparing",
|
|
140
|
-
"running",
|
|
141
|
-
"waiting-approval",
|
|
142
|
-
"waiting-user-input",
|
|
143
|
-
"paused",
|
|
144
|
-
"validating",
|
|
145
|
-
"reviewing",
|
|
146
|
-
"closing-out",
|
|
147
|
-
"needs-attention",
|
|
148
|
-
"completed",
|
|
149
|
-
"failed",
|
|
150
|
-
"stopped"
|
|
151
|
-
].includes(status) ? status : null;
|
|
631
|
+
return typeof status === "string" ? asRunStatus(status) : null;
|
|
152
632
|
}
|
|
153
633
|
function payloadString(payload, keys) {
|
|
154
634
|
if (!payload || typeof payload !== "object")
|
|
@@ -171,12 +651,14 @@ function payloadOptions(payload) {
|
|
|
171
651
|
}
|
|
172
652
|
function inboxRequest(request, kind) {
|
|
173
653
|
const fallback = kind === "approval" ? "Approval requested" : "Input requested";
|
|
654
|
+
const body = payloadString(request.payload, ["body", "description", "detail", "details"]);
|
|
655
|
+
const options = payloadOptions(request.payload);
|
|
174
656
|
return {
|
|
175
657
|
requestId: request.requestId,
|
|
176
658
|
kind,
|
|
177
659
|
title: payloadString(request.payload, ["title", "message", "reason", "prompt", "summary"]) ?? fallback,
|
|
178
|
-
body
|
|
179
|
-
...
|
|
660
|
+
...body !== undefined ? { body } : {},
|
|
661
|
+
...options ? { options } : {},
|
|
180
662
|
requestedAt: request.requestedAt ?? null,
|
|
181
663
|
source: "run"
|
|
182
664
|
};
|
|
@@ -285,8 +767,8 @@ function runRecordFromRegistryEntry(projectRoot, entry) {
|
|
|
285
767
|
projection: folded
|
|
286
768
|
};
|
|
287
769
|
}
|
|
288
|
-
function
|
|
289
|
-
return sortByRecency(
|
|
770
|
+
function runRecordsFromCollab(projectRoot, collabs) {
|
|
771
|
+
return sortByRecency(collabs.map((collab) => runRecordFromRegistryEntry(projectRoot, registryEntryFromCollab(collab))).filter((record) => record !== null));
|
|
290
772
|
}
|
|
291
773
|
function sortByRecency(records) {
|
|
292
774
|
return [...records].sort((a, b) => {
|
|
@@ -334,8 +816,11 @@ function discoveryDiagnosticRunRecord(projectRoot, error) {
|
|
|
334
816
|
}
|
|
335
817
|
async function listRunProjections(projectRoot, filter = {}) {
|
|
336
818
|
try {
|
|
337
|
-
const
|
|
338
|
-
|
|
819
|
+
const discovery = await loadCapabilityForRoot(projectRoot, RunDiscoveryCap);
|
|
820
|
+
if (!discovery)
|
|
821
|
+
return [discoveryDiagnosticRunRecord(projectRoot, "run discovery capability unavailable")];
|
|
822
|
+
const collabs = await discovery.listActiveRunCollab(projectRoot, filter);
|
|
823
|
+
return runRecordsFromCollab(projectRoot, collabs);
|
|
339
824
|
} catch (error) {
|
|
340
825
|
return [discoveryDiagnosticRunRecord(projectRoot, error)];
|
|
341
826
|
}
|
|
@@ -366,18 +851,29 @@ async function resolveRunJoinTarget(projectRoot, runId, filter = {}) {
|
|
|
366
851
|
return null;
|
|
367
852
|
return { runId: run.runId, taskId: run.taskId, joinLink: run.joinLink, cwd: run.collabCwd ?? run.sessionPath, stale: run.stale };
|
|
368
853
|
}
|
|
369
|
-
var EMPTY_PROJECTION, DISCOVERY_DIAGNOSTIC_RUN_ID = "__registry_discovery_error__", listRuns, getRun, resolveJoinTarget;
|
|
854
|
+
var RunDiscoveryCap, EMPTY_PROJECTION, DISCOVERY_DIAGNOSTIC_RUN_ID = "__registry_discovery_error__", listRuns, getRun, resolveJoinTarget;
|
|
370
855
|
var init_projection = __esm(() => {
|
|
371
|
-
|
|
856
|
+
init_session_journal();
|
|
857
|
+
init_run_status();
|
|
858
|
+
RunDiscoveryCap = defineCapability(RUN_DISCOVERY);
|
|
372
859
|
EMPTY_PROJECTION = foldRunSessionEntries([], "");
|
|
373
860
|
listRuns = listRunProjections;
|
|
374
861
|
getRun = getRunProjection;
|
|
375
862
|
resolveJoinTarget = resolveRunJoinTarget;
|
|
376
863
|
});
|
|
377
864
|
|
|
378
|
-
// packages/run-worker/src/
|
|
865
|
+
// packages/run-worker/src/read-model-backend/control.ts
|
|
379
866
|
init_projection();
|
|
380
|
-
import {
|
|
867
|
+
import { RIG_CONTROL_SENTINEL_END as RIG_CONTROL_SENTINEL_END2, RIG_PAUSE_SENTINEL as RIG_PAUSE_SENTINEL2, RIG_RESUME_SENTINEL as RIG_RESUME_SENTINEL2, RIG_STOP_SENTINEL as RIG_STOP_SENTINEL2, RIG_STOP_SENTINEL_END as RIG_STOP_SENTINEL_END2 } from "@rig/contracts";
|
|
868
|
+
function buildPauseSentinel(runId) {
|
|
869
|
+
return `${RIG_PAUSE_SENTINEL2} runId=${runId} requestedBy=operator ${RIG_CONTROL_SENTINEL_END2}`;
|
|
870
|
+
}
|
|
871
|
+
function buildResumeSentinel(runId) {
|
|
872
|
+
return `${RIG_RESUME_SENTINEL2} runId=${runId} requestedBy=operator ${RIG_CONTROL_SENTINEL_END2}`;
|
|
873
|
+
}
|
|
874
|
+
function buildStopSentinel(runId, reason) {
|
|
875
|
+
return `${RIG_STOP_SENTINEL2} runId=${runId} reason=${reason} ${RIG_STOP_SENTINEL_END2}`;
|
|
876
|
+
}
|
|
381
877
|
async function loadCollabControlDeps() {
|
|
382
878
|
const [{ importRoomKey, seal }, { COLLAB_PROTO, packEnvelope, parseCollabLink }] = await Promise.all([
|
|
383
879
|
import("@oh-my-pi/pi-coding-agent/collab/crypto"),
|
|
@@ -406,9 +902,6 @@ Stop this run and do not continue after the interruption settles.` },
|
|
|
406
902
|
];
|
|
407
903
|
}
|
|
408
904
|
}
|
|
409
|
-
function collabControlFrame(runId, control) {
|
|
410
|
-
return collabControlFrames(runId, control)[0];
|
|
411
|
-
}
|
|
412
905
|
async function sendSealedCollabFrames(joinLink, frames, deps = {}) {
|
|
413
906
|
const { importRoomKey, seal, COLLAB_PROTO, packEnvelope, parseCollabLink } = await loadCollabControlDeps();
|
|
414
907
|
const parsed = parseCollabLink(joinLink);
|
|
@@ -459,9 +952,8 @@ async function deliverRunControl(projectRoot, target, control, deps = {}) {
|
|
|
459
952
|
throw new Error(`Could not ${control.kind} run ${record.runId}. ${detail}`);
|
|
460
953
|
}
|
|
461
954
|
}
|
|
462
|
-
// packages/run-worker/src/
|
|
463
|
-
|
|
464
|
-
var TERMINAL = new Set(TERMINAL_RUN_STATUSES);
|
|
955
|
+
// packages/run-worker/src/read-model-backend/guard.ts
|
|
956
|
+
var TERMINAL = new Set(["completed", "failed", "stopped"]);
|
|
465
957
|
function runBlocksNewRunForTask(run) {
|
|
466
958
|
return run.live && !run.stale && !TERMINAL.has(run.status) && run.status !== "needs-attention" && run.status !== "needs_attention";
|
|
467
959
|
}
|
|
@@ -479,9 +971,12 @@ async function assertNoActiveRunForTask(listRuns2, projectRoot, taskId) {
|
|
|
479
971
|
throw new Error(`Task ${taskId} already has an active run: ${existing}. Attach instead: rig run attach ${existing} \u2014 or re-dispatch anyway with --force.`);
|
|
480
972
|
}
|
|
481
973
|
}
|
|
482
|
-
// packages/run-worker/src/
|
|
483
|
-
import {
|
|
974
|
+
// packages/run-worker/src/read-model-backend/inbox.ts
|
|
975
|
+
import { RIG_CONTROL_SENTINEL_END as RIG_CONTROL_SENTINEL_END3, RIG_INBOX_RESOLUTION_SENTINEL as RIG_INBOX_RESOLUTION_SENTINEL2 } from "@rig/contracts";
|
|
484
976
|
init_projection();
|
|
977
|
+
function buildInboxResolutionSentinel(runId, payload) {
|
|
978
|
+
return `${RIG_INBOX_RESOLUTION_SENTINEL2} runId=${runId} data=${encodeURIComponent(JSON.stringify(payload))} requestedBy=operator ${RIG_CONTROL_SENTINEL_END3}`;
|
|
979
|
+
}
|
|
485
980
|
function promptFromPayload(payload, fallback) {
|
|
486
981
|
if (payload && typeof payload === "object") {
|
|
487
982
|
const record = payload;
|
|
@@ -578,9 +1073,8 @@ function decisionText(runId, requestId, decision) {
|
|
|
578
1073
|
async function resolveInboxRequest(projectRoot, runId, requestId, decision, deps = {}) {
|
|
579
1074
|
await (deps.deliverRunControl ?? deliverRunControl)(projectRoot, runId, { kind: "steer", message: decisionText(runId, requestId, decision) });
|
|
580
1075
|
}
|
|
581
|
-
// packages/run-worker/src/
|
|
1076
|
+
// packages/run-worker/src/read-model-backend/inspect.ts
|
|
582
1077
|
init_projection();
|
|
583
|
-
init_diagnostics();
|
|
584
1078
|
import { RIG_RUN_LOG_ENTRY } from "@rig/contracts";
|
|
585
1079
|
function asRecord(value) {
|
|
586
1080
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
@@ -665,7 +1159,6 @@ function summarizeRunFailures(run) {
|
|
|
665
1159
|
}
|
|
666
1160
|
return failures;
|
|
667
1161
|
}
|
|
668
|
-
var summarizeProjectionFailures = summarizeRunFailures;
|
|
669
1162
|
async function runsForTask(projectRoot, taskId, deps = {}) {
|
|
670
1163
|
const list = deps.listRuns ?? listRuns;
|
|
671
1164
|
try {
|
|
@@ -689,175 +1182,13 @@ function runInspectSummaryRows(runs, options = {}) {
|
|
|
689
1182
|
{ id: "inspect:audit", label: "AUDIT", currentValue: "unavailable", heading: true, description: "CLI inspect audit has no cockpit equivalent; use rig inspect audit" }
|
|
690
1183
|
];
|
|
691
1184
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
} from "@rig/contracts";
|
|
700
|
-
var KNOWN_RUN_STATUS = Object.fromEntries([...ACTIVE_RUN_STATUSES, ...TERMINAL_RUN_STATUSES2].map((status) => [status, true]));
|
|
701
|
-
function canonicalStatusToken(status) {
|
|
702
|
-
const normalized = normalizeRunStatusToken(status);
|
|
703
|
-
if (normalized === "waiting-input")
|
|
704
|
-
return "waiting-user-input";
|
|
705
|
-
return normalized;
|
|
706
|
-
}
|
|
707
|
-
function asRunStatus(status) {
|
|
708
|
-
return KNOWN_RUN_STATUS[status] ? status : null;
|
|
709
|
-
}
|
|
710
|
-
function statusColorRole(status) {
|
|
711
|
-
switch (canonicalStatusToken(status)) {
|
|
712
|
-
case "done":
|
|
713
|
-
case "completed":
|
|
714
|
-
case "ready":
|
|
715
|
-
case "healthy":
|
|
716
|
-
case "approved":
|
|
717
|
-
case "merged":
|
|
718
|
-
return "success";
|
|
719
|
-
case "needs-attention":
|
|
720
|
-
case "needs_attention":
|
|
721
|
-
case "waiting-approval":
|
|
722
|
-
case "waiting-user-input":
|
|
723
|
-
case "waiting-input":
|
|
724
|
-
case "waiting_input":
|
|
725
|
-
case "blocked":
|
|
726
|
-
case "paused":
|
|
727
|
-
return "action-yellow";
|
|
728
|
-
case "running":
|
|
729
|
-
case "adopted":
|
|
730
|
-
case "preparing":
|
|
731
|
-
case "created":
|
|
732
|
-
case "queued":
|
|
733
|
-
case "starting":
|
|
734
|
-
case "pending":
|
|
735
|
-
case "in_progress":
|
|
736
|
-
case "in-progress":
|
|
737
|
-
case "active":
|
|
738
|
-
case "booting":
|
|
739
|
-
case "validating":
|
|
740
|
-
case "reviewing":
|
|
741
|
-
case "closing-out":
|
|
742
|
-
case "closing_out":
|
|
743
|
-
return "active-cyan";
|
|
744
|
-
case "failed":
|
|
745
|
-
case "error":
|
|
746
|
-
case "rejected":
|
|
747
|
-
return "failure";
|
|
748
|
-
case "stopped":
|
|
749
|
-
case "cancelled":
|
|
750
|
-
case "canceled":
|
|
751
|
-
case "stale":
|
|
752
|
-
return "muted";
|
|
753
|
-
default:
|
|
754
|
-
return "neutral";
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
function runStatusColorRole(run) {
|
|
758
|
-
const classification = classifyRun(run);
|
|
759
|
-
return classification.isNeedsAttention && !classification.isTerminal ? "action-yellow" : statusColorRole(classification.status);
|
|
760
|
-
}
|
|
761
|
-
function isSteerableStatus(status) {
|
|
762
|
-
switch (status) {
|
|
763
|
-
case "needs-attention":
|
|
764
|
-
case "waiting-approval":
|
|
765
|
-
case "waiting-user-input":
|
|
766
|
-
case "paused":
|
|
767
|
-
return false;
|
|
768
|
-
default: {
|
|
769
|
-
const runStatus = asRunStatus(status);
|
|
770
|
-
return runStatus ? isActiveRunStatus(runStatus) : false;
|
|
771
|
-
}
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
function isNeedsAttention(run) {
|
|
775
|
-
return canonicalStatusToken(run.status) === "needs-attention" || run.pendingApprovals + run.pendingInputs > 0 || run.stallCount > 0;
|
|
776
|
-
}
|
|
777
|
-
function phaseForStatus(status, runStatus, needsAttention) {
|
|
778
|
-
if (runStatus && isTerminalRunStatus2(runStatus))
|
|
779
|
-
return runStatus === "completed" || runStatus === "failed" || runStatus === "stopped" ? runStatus : "stopped";
|
|
780
|
-
if (needsAttention)
|
|
781
|
-
return "needs-attention";
|
|
782
|
-
switch (status) {
|
|
783
|
-
case "created":
|
|
784
|
-
case "queued":
|
|
785
|
-
case "preparing":
|
|
786
|
-
case "starting":
|
|
787
|
-
case "booting":
|
|
788
|
-
return "starting";
|
|
789
|
-
case "waiting-approval":
|
|
790
|
-
case "waiting-user-input":
|
|
791
|
-
return "waiting";
|
|
792
|
-
case "paused":
|
|
793
|
-
return "paused";
|
|
794
|
-
case "running":
|
|
795
|
-
case "validating":
|
|
796
|
-
case "reviewing":
|
|
797
|
-
case "closing-out":
|
|
798
|
-
return "active";
|
|
799
|
-
default:
|
|
800
|
-
return runStatus && isActiveRunStatus(runStatus) ? "active" : "unknown";
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
function classifyRun(run) {
|
|
804
|
-
const status = canonicalStatusToken(run.status) || (run.live && !run.stale ? "starting" : "unknown");
|
|
805
|
-
const runStatus = asRunStatus(status);
|
|
806
|
-
const isTerminal = runStatus ? isTerminalRunStatus2(runStatus) : false;
|
|
807
|
-
const isNeedsAttentionValue = isNeedsAttention(run);
|
|
808
|
-
const phase = phaseForStatus(status, runStatus, isNeedsAttentionValue);
|
|
809
|
-
return {
|
|
810
|
-
status,
|
|
811
|
-
phase,
|
|
812
|
-
isActive: runStatus ? isActiveRunStatus(runStatus) : !isTerminal && status !== "unknown",
|
|
813
|
-
isTerminal,
|
|
814
|
-
isNeedsAttention: isNeedsAttentionValue
|
|
815
|
-
};
|
|
816
|
-
}
|
|
817
|
-
function runStatusText(run) {
|
|
818
|
-
return classifyRun(run).status;
|
|
819
|
-
}
|
|
820
|
-
function statusRank(run) {
|
|
821
|
-
const classification = classifyRun(run);
|
|
822
|
-
if (classification.isNeedsAttention)
|
|
823
|
-
return 0;
|
|
824
|
-
switch (classification.phase) {
|
|
825
|
-
case "needs-attention":
|
|
826
|
-
return 0;
|
|
827
|
-
case "active":
|
|
828
|
-
case "waiting":
|
|
829
|
-
case "paused":
|
|
830
|
-
return 1;
|
|
831
|
-
case "starting":
|
|
832
|
-
return 2;
|
|
833
|
-
case "completed":
|
|
834
|
-
return 3;
|
|
835
|
-
case "failed":
|
|
836
|
-
return 4;
|
|
837
|
-
case "stopped":
|
|
838
|
-
return 5;
|
|
839
|
-
case "unknown":
|
|
840
|
-
return 6;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
function canSteer(run) {
|
|
844
|
-
const classification = classifyRun(run);
|
|
845
|
-
if (classification.phase === "active" || classification.phase === "starting")
|
|
846
|
-
return true;
|
|
847
|
-
return classification.isNeedsAttention && isSteerableStatus(classification.status);
|
|
848
|
-
}
|
|
849
|
-
function canStop(run) {
|
|
850
|
-
const classification = classifyRun(run);
|
|
851
|
-
return classification.isActive && !classification.isTerminal;
|
|
852
|
-
}
|
|
853
|
-
function canPause(run) {
|
|
854
|
-
const phase = classifyRun(run).phase;
|
|
855
|
-
return phase === "active" || phase === "starting";
|
|
856
|
-
}
|
|
857
|
-
function canResume(run) {
|
|
858
|
-
return classifyRun(run).phase === "paused";
|
|
859
|
-
}
|
|
860
|
-
// packages/run-worker/src/runs/stats.ts
|
|
1185
|
+
|
|
1186
|
+
// packages/run-worker/src/read-model-backend/index.ts
|
|
1187
|
+
init_run_status();
|
|
1188
|
+
|
|
1189
|
+
// packages/run-worker/src/read-model-backend/stats.ts
|
|
1190
|
+
init_run_status();
|
|
1191
|
+
init_run_status();
|
|
861
1192
|
function parseTimestamp(value) {
|
|
862
1193
|
if (!value)
|
|
863
1194
|
return null;
|
|
@@ -937,15 +1268,12 @@ async function computeStats(projectRootOrRuns, options = {}) {
|
|
|
937
1268
|
approvalsPending
|
|
938
1269
|
};
|
|
939
1270
|
}
|
|
940
|
-
var computeRigStats = computeStats;
|
|
941
1271
|
|
|
942
|
-
// packages/run-worker/src/
|
|
1272
|
+
// packages/run-worker/src/read-model-backend/index.ts
|
|
943
1273
|
init_projection();
|
|
944
|
-
init_diagnostics();
|
|
945
1274
|
export {
|
|
946
1275
|
summarizeRunFailures,
|
|
947
1276
|
summarizeRunError,
|
|
948
|
-
summarizeProjectionFailures,
|
|
949
1277
|
stringifyLogPayload,
|
|
950
1278
|
statusRank,
|
|
951
1279
|
statusColorRole,
|
|
@@ -963,6 +1291,7 @@ export {
|
|
|
963
1291
|
readInboxCounts,
|
|
964
1292
|
rate,
|
|
965
1293
|
parseTimestamp,
|
|
1294
|
+
normalizeRunStatusToken,
|
|
966
1295
|
median,
|
|
967
1296
|
logLinesFromProjection,
|
|
968
1297
|
logLineFromValue,
|
|
@@ -970,21 +1299,21 @@ export {
|
|
|
970
1299
|
listRuns,
|
|
971
1300
|
listInboxRecords,
|
|
972
1301
|
listInbox,
|
|
1302
|
+
isOperatorActiveRunStatus,
|
|
973
1303
|
isNeedsAttention,
|
|
974
1304
|
getRun,
|
|
975
1305
|
extractRunLogs,
|
|
976
1306
|
deliverRunControl,
|
|
977
1307
|
deliverRemoteRunControl,
|
|
978
1308
|
computeStats,
|
|
979
|
-
computeRigStats,
|
|
980
1309
|
completedDuration,
|
|
981
1310
|
collabControlFrames,
|
|
982
|
-
collabControlFrame,
|
|
983
1311
|
classifyRun,
|
|
984
1312
|
canStop,
|
|
985
1313
|
canSteer,
|
|
986
1314
|
canResume,
|
|
987
1315
|
canPause,
|
|
988
1316
|
assertNoActiveRunForTask,
|
|
1317
|
+
asRunStatus,
|
|
989
1318
|
activeRunByTaskId
|
|
990
1319
|
};
|