@h-rig/run-worker 0.0.6-alpha.156 → 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
|
@@ -15,7 +15,335 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
17
|
|
|
18
|
-
// packages/run-worker/src/
|
|
18
|
+
// packages/run-worker/src/read-model-backend/run-status.ts
|
|
19
|
+
import { OPERATOR_INACTIVE_RUN_STATUSES } from "@rig/contracts";
|
|
20
|
+
function normalizeRunStatusToken(status) {
|
|
21
|
+
return String(status ?? "").trim().toLowerCase().replace(/[\s_]+/g, "-");
|
|
22
|
+
}
|
|
23
|
+
function canonicalStatusToken(status) {
|
|
24
|
+
const normalized = normalizeRunStatusToken(status);
|
|
25
|
+
if (normalized === "waiting-input")
|
|
26
|
+
return "waiting-user-input";
|
|
27
|
+
return normalized;
|
|
28
|
+
}
|
|
29
|
+
function asRunStatus(status) {
|
|
30
|
+
return KNOWN_RUN_STATUS[status] ? status : null;
|
|
31
|
+
}
|
|
32
|
+
function isNeedsAttention(run) {
|
|
33
|
+
return canonicalStatusToken(run.status) === "needs-attention" || run.pendingApprovals + run.pendingInputs > 0 || run.stallCount > 0;
|
|
34
|
+
}
|
|
35
|
+
var TERMINAL_RUN_STATUSES, ACTIVE_RUN_STATUSES, KNOWN_RUN_STATUS;
|
|
36
|
+
var init_run_status = __esm(() => {
|
|
37
|
+
TERMINAL_RUN_STATUSES = ["completed", "failed", "stopped"];
|
|
38
|
+
ACTIVE_RUN_STATUSES = [
|
|
39
|
+
"created",
|
|
40
|
+
"queued",
|
|
41
|
+
"preparing",
|
|
42
|
+
"running",
|
|
43
|
+
"waiting-approval",
|
|
44
|
+
"waiting-user-input",
|
|
45
|
+
"paused",
|
|
46
|
+
"validating",
|
|
47
|
+
"reviewing",
|
|
48
|
+
"closing-out",
|
|
49
|
+
"needs-attention"
|
|
50
|
+
];
|
|
51
|
+
KNOWN_RUN_STATUS = Object.fromEntries([...ACTIVE_RUN_STATUSES, ...TERMINAL_RUN_STATUSES].map((status) => [status, true]));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// packages/run-worker/src/session-journal.ts
|
|
55
|
+
import { Schema } from "effect";
|
|
56
|
+
import {
|
|
57
|
+
CUSTOM_TYPE_FOR,
|
|
58
|
+
RIG_CONTROL_SENTINEL_END,
|
|
59
|
+
RIG_INBOX_RESOLUTION_SENTINEL,
|
|
60
|
+
RIG_PAUSE_SENTINEL,
|
|
61
|
+
RIG_RESUME_SENTINEL,
|
|
62
|
+
RIG_STOP_SENTINEL,
|
|
63
|
+
RIG_STOP_SENTINEL_END,
|
|
64
|
+
RIG_WORKFLOW_STATUS_CHANGED,
|
|
65
|
+
RunJournalEvent,
|
|
66
|
+
TYPE_FOR_CUSTOM
|
|
67
|
+
} from "@rig/contracts";
|
|
68
|
+
function isTerminalRunStatus(status) {
|
|
69
|
+
return TERMINAL_RUN_STATUSES2.includes(status);
|
|
70
|
+
}
|
|
71
|
+
function canTransitionRunStatus(from, to) {
|
|
72
|
+
if (from === null)
|
|
73
|
+
return true;
|
|
74
|
+
if (from === to)
|
|
75
|
+
return true;
|
|
76
|
+
return RUN_STATUS_TRANSITIONS[from].includes(to);
|
|
77
|
+
}
|
|
78
|
+
function assertRunStatusTransition(from, to) {
|
|
79
|
+
if (!canTransitionRunStatus(from, to)) {
|
|
80
|
+
throw new Error(`Illegal run status transition: ${from ?? "(none)"} -> ${to}. ` + `Allowed from ${from ?? "(none)"}: ${from ? RUN_STATUS_TRANSITIONS[from].join(", ") : "(any)"}.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function reduceRunJournal(events, runId = null) {
|
|
84
|
+
let record = {};
|
|
85
|
+
let status = null;
|
|
86
|
+
const statusHistory = [];
|
|
87
|
+
const pendingApprovals = new Map;
|
|
88
|
+
const resolvedApprovals = [];
|
|
89
|
+
const pendingUserInputs = new Map;
|
|
90
|
+
const resolvedUserInputs = [];
|
|
91
|
+
const closeoutPhases = [];
|
|
92
|
+
let resolvedPipeline = null;
|
|
93
|
+
const stageOutcomes = [];
|
|
94
|
+
const anomalies = [];
|
|
95
|
+
let steeringCount = 0;
|
|
96
|
+
let stallCount = 0;
|
|
97
|
+
let lastSeq = 0;
|
|
98
|
+
let lastEventAt = null;
|
|
99
|
+
const projectedRunId = runId ?? events[0]?.runId ?? null;
|
|
100
|
+
for (const event of events) {
|
|
101
|
+
lastSeq = event.seq;
|
|
102
|
+
lastEventAt = event.at;
|
|
103
|
+
switch (event.type) {
|
|
104
|
+
case "status-changed": {
|
|
105
|
+
if (!canTransitionRunStatus(status, event.to)) {
|
|
106
|
+
anomalies.push({ seq: event.seq, kind: "illegal-transition", detail: `${status ?? "(none)"} -> ${event.to}` });
|
|
107
|
+
}
|
|
108
|
+
statusHistory.push({ seq: event.seq, at: event.at, from: status, to: event.to, reason: event.reason ?? null });
|
|
109
|
+
const wasTerminal = status !== null && isTerminalRunStatus(status);
|
|
110
|
+
status = event.to;
|
|
111
|
+
record = { ...record, updatedAt: event.at };
|
|
112
|
+
if (isTerminalRunStatus(event.to) && !record.completedAt)
|
|
113
|
+
record = { ...record, completedAt: event.at };
|
|
114
|
+
if (!isTerminalRunStatus(event.to) && wasTerminal)
|
|
115
|
+
record = { ...record, completedAt: null };
|
|
116
|
+
if (event.to === "running" && !record.startedAt)
|
|
117
|
+
record = { ...record, startedAt: event.at };
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
case "record-patch": {
|
|
121
|
+
const next = { ...record };
|
|
122
|
+
for (const [key, value] of Object.entries(event.patch)) {
|
|
123
|
+
if (value !== undefined)
|
|
124
|
+
next[key] = value;
|
|
125
|
+
}
|
|
126
|
+
next.updatedAt = event.patch.updatedAt ?? event.at;
|
|
127
|
+
record = next;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
case "approval-requested": {
|
|
131
|
+
pendingApprovals.set(event.requestId, {
|
|
132
|
+
requestId: event.requestId,
|
|
133
|
+
requestKind: event.requestKind,
|
|
134
|
+
actionId: event.actionId ?? null,
|
|
135
|
+
payload: event.payload,
|
|
136
|
+
requestedAt: event.at
|
|
137
|
+
});
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case "approval-resolved": {
|
|
141
|
+
const pending = pendingApprovals.get(event.requestId);
|
|
142
|
+
if (!pending) {
|
|
143
|
+
const alreadyResolved = resolvedApprovals.some((entry) => entry.requestId === event.requestId);
|
|
144
|
+
anomalies.push({ seq: event.seq, kind: alreadyResolved ? "duplicate-resolution" : "unknown-request", detail: `approval ${event.requestId}` });
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
pendingApprovals.delete(event.requestId);
|
|
148
|
+
resolvedApprovals.push({ ...pending, decision: event.decision, note: event.note ?? null, actor: event.actor, resolvedAt: event.at });
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
case "input-requested": {
|
|
152
|
+
pendingUserInputs.set(event.requestId, {
|
|
153
|
+
requestId: event.requestId,
|
|
154
|
+
requestKind: "user-input",
|
|
155
|
+
actionId: null,
|
|
156
|
+
payload: event.payload,
|
|
157
|
+
requestedAt: event.at
|
|
158
|
+
});
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
case "input-resolved": {
|
|
162
|
+
const pending = pendingUserInputs.get(event.requestId);
|
|
163
|
+
if (!pending) {
|
|
164
|
+
const alreadyResolved = resolvedUserInputs.some((entry) => entry.requestId === event.requestId);
|
|
165
|
+
anomalies.push({ seq: event.seq, kind: alreadyResolved ? "duplicate-resolution" : "unknown-request", detail: `user-input ${event.requestId}` });
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
pendingUserInputs.delete(event.requestId);
|
|
169
|
+
resolvedUserInputs.push({ ...pending, answers: event.answers, actor: event.actor, resolvedAt: event.at });
|
|
170
|
+
break;
|
|
171
|
+
}
|
|
172
|
+
case "steering":
|
|
173
|
+
steeringCount += 1;
|
|
174
|
+
break;
|
|
175
|
+
case "adopted":
|
|
176
|
+
record = { ...record, pid: event.pid, updatedAt: event.at };
|
|
177
|
+
break;
|
|
178
|
+
case "stall-detected":
|
|
179
|
+
stallCount += 1;
|
|
180
|
+
break;
|
|
181
|
+
case "closeout-phase":
|
|
182
|
+
closeoutPhases.push({ seq: event.seq, at: event.at, phase: event.phase, outcome: event.outcome, detail: event.detail ?? null });
|
|
183
|
+
break;
|
|
184
|
+
case "pipeline-resolved":
|
|
185
|
+
resolvedPipeline = event.pipeline;
|
|
186
|
+
break;
|
|
187
|
+
case "stage-outcome":
|
|
188
|
+
stageOutcomes.push({ seq: event.seq, at: event.at, outcome: event.outcome });
|
|
189
|
+
break;
|
|
190
|
+
case "timeline-entry":
|
|
191
|
+
case "log-entry":
|
|
192
|
+
break;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return {
|
|
196
|
+
runId: projectedRunId,
|
|
197
|
+
record,
|
|
198
|
+
status,
|
|
199
|
+
statusHistory,
|
|
200
|
+
pendingApprovals: [...pendingApprovals.values()],
|
|
201
|
+
resolvedApprovals,
|
|
202
|
+
pendingUserInputs: [...pendingUserInputs.values()],
|
|
203
|
+
resolvedUserInputs,
|
|
204
|
+
steeringCount,
|
|
205
|
+
stallCount,
|
|
206
|
+
closeoutPhases,
|
|
207
|
+
resolvedPipeline,
|
|
208
|
+
stageOutcomes,
|
|
209
|
+
lastSeq,
|
|
210
|
+
lastEventAt,
|
|
211
|
+
anomalies
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function isRunSessionCustomType(customType) {
|
|
215
|
+
return customType !== undefined && Object.hasOwn(TYPE_FOR_CUSTOM, customType);
|
|
216
|
+
}
|
|
217
|
+
function foldRunSessionEntries(entries, runId) {
|
|
218
|
+
const events = [];
|
|
219
|
+
entries.forEach((entry, index) => {
|
|
220
|
+
if (entry.type !== "custom" || !isRunSessionCustomType(entry.customType))
|
|
221
|
+
return;
|
|
222
|
+
const data = entry.data !== null && typeof entry.data === "object" ? entry.data : {};
|
|
223
|
+
const stamped = {
|
|
224
|
+
v: 1,
|
|
225
|
+
seq: index + 1,
|
|
226
|
+
at: typeof data.at === "string" ? data.at : new Date(0).toISOString(),
|
|
227
|
+
runId,
|
|
228
|
+
...data,
|
|
229
|
+
type: TYPE_FOR_CUSTOM[entry.customType]
|
|
230
|
+
};
|
|
231
|
+
try {
|
|
232
|
+
events.push(decodeRunJournalEvent(stamped));
|
|
233
|
+
} catch {}
|
|
234
|
+
});
|
|
235
|
+
return reduceRunJournal(events, runId);
|
|
236
|
+
}
|
|
237
|
+
function isRecord(value) {
|
|
238
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
239
|
+
}
|
|
240
|
+
function timelineEntryFromCustomEntry(entry) {
|
|
241
|
+
if (entry.customType !== CUSTOM_TYPE_FOR["timeline-entry"] || !isRecord(entry.data))
|
|
242
|
+
return null;
|
|
243
|
+
const payload = isRecord(entry.data.payload) ? entry.data.payload : entry.data;
|
|
244
|
+
const type = typeof payload.type === "string" ? payload.type : "timeline";
|
|
245
|
+
const stage = typeof payload.stage === "string" ? payload.stage : typeof payload.name === "string" ? payload.name : null;
|
|
246
|
+
const status = typeof payload.status === "string" ? payload.status : typeof payload.outcome === "string" ? payload.outcome : null;
|
|
247
|
+
const detail = typeof payload.detail === "string" ? payload.detail : typeof payload.message === "string" ? payload.message : null;
|
|
248
|
+
const at = typeof entry.data.at === "string" ? entry.data.at : typeof payload.at === "string" ? payload.at : null;
|
|
249
|
+
return { at, type, stage, status, detail };
|
|
250
|
+
}
|
|
251
|
+
function timelineEntriesFromCustomEntries(entries) {
|
|
252
|
+
return entries.flatMap((entry) => {
|
|
253
|
+
const timelineEntry = timelineEntryFromCustomEntry(entry);
|
|
254
|
+
return timelineEntry ? [timelineEntry] : [];
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
function asCustomEntries(entries) {
|
|
258
|
+
return entries.filter((entry) => entry.type === "custom");
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
class RunSessionJournal {
|
|
262
|
+
sm;
|
|
263
|
+
runId;
|
|
264
|
+
constructor(sm, runId) {
|
|
265
|
+
this.sm = sm;
|
|
266
|
+
this.runId = runId;
|
|
267
|
+
}
|
|
268
|
+
#append(init) {
|
|
269
|
+
this.sm.appendCustomEntry(CUSTOM_TYPE_FOR[init.type], { ...init, at: new Date().toISOString() });
|
|
270
|
+
}
|
|
271
|
+
appendStatus(to, opts = {}) {
|
|
272
|
+
const from = foldRunSessionEntries(asCustomEntries(this.sm.getEntries()), this.runId).status;
|
|
273
|
+
if (!opts.force)
|
|
274
|
+
assertRunStatusTransition(from, to);
|
|
275
|
+
if (opts.errorText !== undefined)
|
|
276
|
+
this.#append({ type: "record-patch", patch: { errorText: opts.errorText } });
|
|
277
|
+
this.#append({
|
|
278
|
+
type: "status-changed",
|
|
279
|
+
from,
|
|
280
|
+
to,
|
|
281
|
+
...opts.reason !== undefined ? { reason: opts.reason } : {},
|
|
282
|
+
...opts.actor !== undefined ? { actor: opts.actor } : {}
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
appendTimeline(payload) {
|
|
286
|
+
this.#append({ type: "timeline-entry", payload });
|
|
287
|
+
}
|
|
288
|
+
appendCloseoutPhase(input) {
|
|
289
|
+
this.#append({
|
|
290
|
+
type: "closeout-phase",
|
|
291
|
+
phase: input.phase,
|
|
292
|
+
outcome: input.outcome,
|
|
293
|
+
...input.detail !== undefined ? { detail: input.detail } : {}
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
appendApprovalResolved(input) {
|
|
297
|
+
this.#append({
|
|
298
|
+
type: "approval-resolved",
|
|
299
|
+
requestId: input.requestId,
|
|
300
|
+
decision: input.decision,
|
|
301
|
+
actor: input.actor,
|
|
302
|
+
...input.note !== undefined ? { note: input.note } : {}
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
appendInputResolved(input) {
|
|
306
|
+
this.#append({ type: "input-resolved", requestId: input.requestId, answers: input.answers, actor: input.actor });
|
|
307
|
+
}
|
|
308
|
+
appendStall(input) {
|
|
309
|
+
this.#append({ type: "stall-detected", detail: input.detail });
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
var decodeRunJournalEvent, RUN_STATUS_TRANSITIONS, TERMINAL_RUN_STATUSES2;
|
|
313
|
+
var init_session_journal = __esm(() => {
|
|
314
|
+
decodeRunJournalEvent = Schema.decodeUnknownSync(RunJournalEvent);
|
|
315
|
+
RUN_STATUS_TRANSITIONS = {
|
|
316
|
+
created: ["queued", "preparing", "running", "failed", "stopped"],
|
|
317
|
+
queued: ["preparing", "running", "failed", "stopped"],
|
|
318
|
+
preparing: ["queued", "running", "needs-attention", "failed", "stopped"],
|
|
319
|
+
running: [
|
|
320
|
+
"queued",
|
|
321
|
+
"waiting-approval",
|
|
322
|
+
"waiting-user-input",
|
|
323
|
+
"paused",
|
|
324
|
+
"validating",
|
|
325
|
+
"reviewing",
|
|
326
|
+
"closing-out",
|
|
327
|
+
"needs-attention",
|
|
328
|
+
"completed",
|
|
329
|
+
"failed",
|
|
330
|
+
"stopped"
|
|
331
|
+
],
|
|
332
|
+
"waiting-approval": ["running", "needs-attention", "failed", "stopped"],
|
|
333
|
+
"waiting-user-input": ["running", "needs-attention", "failed", "stopped"],
|
|
334
|
+
paused: ["running", "failed", "stopped"],
|
|
335
|
+
validating: ["running", "reviewing", "closing-out", "needs-attention", "completed", "failed", "stopped"],
|
|
336
|
+
reviewing: ["running", "validating", "closing-out", "needs-attention", "completed", "failed", "stopped"],
|
|
337
|
+
"closing-out": ["running", "needs-attention", "completed", "failed", "stopped"],
|
|
338
|
+
"needs-attention": ["queued", "preparing", "running", "closing-out", "completed", "failed", "stopped"],
|
|
339
|
+
completed: [],
|
|
340
|
+
failed: ["queued", "preparing", "running", "closing-out"],
|
|
341
|
+
stopped: ["queued", "preparing", "running", "closing-out"]
|
|
342
|
+
};
|
|
343
|
+
TERMINAL_RUN_STATUSES2 = ["completed", "failed", "stopped"];
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// packages/run-worker/src/read-model-backend/diagnostics.ts
|
|
19
347
|
function normalizeString(value) {
|
|
20
348
|
if (typeof value !== "string")
|
|
21
349
|
return null;
|
|
@@ -62,13 +390,12 @@ function summarizeRunError(projection) {
|
|
|
62
390
|
const nonGeneric = candidates.filter((candidate) => !isGenericRunFailure(candidate));
|
|
63
391
|
return categorizeUsefulRunError(nonGeneric) ?? nonGeneric.at(-1) ?? normalizeString(projection.record.errorText);
|
|
64
392
|
}
|
|
65
|
-
var init_diagnostics = () => {};
|
|
66
393
|
|
|
67
|
-
// packages/run-worker/src/
|
|
394
|
+
// packages/run-worker/src/read-model-backend/projection.ts
|
|
68
395
|
var exports_projection = {};
|
|
69
396
|
__export(exports_projection, {
|
|
70
397
|
selectRunProjection: () => selectRunProjection,
|
|
71
|
-
|
|
398
|
+
runRecordsFromCollab: () => runRecordsFromCollab,
|
|
72
399
|
runRecordFromRegistryEntry: () => runRecordFromRegistryEntry,
|
|
73
400
|
resolveRunJoinTarget: () => resolveRunJoinTarget,
|
|
74
401
|
resolveJoinTarget: () => resolveJoinTarget,
|
|
@@ -81,13 +408,28 @@ __export(exports_projection, {
|
|
|
81
408
|
});
|
|
82
409
|
import { existsSync, readFileSync } from "fs";
|
|
83
410
|
import { isAbsolute, relative, resolve } from "path";
|
|
84
|
-
import {
|
|
85
|
-
import {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
411
|
+
import { RUN_DISCOVERY } from "@rig/contracts";
|
|
412
|
+
import { loadCapabilityForRoot } from "@rig/core/capability-loaders";
|
|
413
|
+
import { defineCapability } from "@rig/core/capability";
|
|
414
|
+
function registryEntryFromCollab(collab) {
|
|
415
|
+
const record = collab;
|
|
416
|
+
return {
|
|
417
|
+
roomId: collab.sessionId,
|
|
418
|
+
title: collab.title,
|
|
419
|
+
status: record.registryStatus ?? (collab.stale ? "stale" : "running"),
|
|
420
|
+
startedAt: collab.startedAt ?? null,
|
|
421
|
+
heartbeatAt: collab.updatedAt ?? null,
|
|
422
|
+
sessionPath: collab.sessionPath ?? null,
|
|
423
|
+
cwd: collab.cwd ?? null,
|
|
424
|
+
joinLink: collab.joinLink ?? null,
|
|
425
|
+
webLink: collab.webLink ?? null,
|
|
426
|
+
relayUrl: collab.relayUrl ?? null,
|
|
427
|
+
stale: collab.stale,
|
|
428
|
+
repo: collab.selectedRepo ?? null,
|
|
429
|
+
...collab.pid === undefined ? {} : { pid: collab.pid },
|
|
430
|
+
projection: record.registryProjection ?? null
|
|
431
|
+
};
|
|
432
|
+
}
|
|
91
433
|
function readSessionRunEntries(sessionPath) {
|
|
92
434
|
if (!sessionPath || !existsSync(sessionPath))
|
|
93
435
|
return [];
|
|
@@ -132,22 +474,7 @@ function registryStatusAsRunStatus(status) {
|
|
|
132
474
|
return "waiting-user-input";
|
|
133
475
|
if (status === "starting")
|
|
134
476
|
return "preparing";
|
|
135
|
-
return typeof status === "string"
|
|
136
|
-
"created",
|
|
137
|
-
"queued",
|
|
138
|
-
"preparing",
|
|
139
|
-
"running",
|
|
140
|
-
"waiting-approval",
|
|
141
|
-
"waiting-user-input",
|
|
142
|
-
"paused",
|
|
143
|
-
"validating",
|
|
144
|
-
"reviewing",
|
|
145
|
-
"closing-out",
|
|
146
|
-
"needs-attention",
|
|
147
|
-
"completed",
|
|
148
|
-
"failed",
|
|
149
|
-
"stopped"
|
|
150
|
-
].includes(status) ? status : null;
|
|
477
|
+
return typeof status === "string" ? asRunStatus(status) : null;
|
|
151
478
|
}
|
|
152
479
|
function payloadString(payload, keys) {
|
|
153
480
|
if (!payload || typeof payload !== "object")
|
|
@@ -170,12 +497,14 @@ function payloadOptions(payload) {
|
|
|
170
497
|
}
|
|
171
498
|
function inboxRequest(request, kind) {
|
|
172
499
|
const fallback = kind === "approval" ? "Approval requested" : "Input requested";
|
|
500
|
+
const body = payloadString(request.payload, ["body", "description", "detail", "details"]);
|
|
501
|
+
const options = payloadOptions(request.payload);
|
|
173
502
|
return {
|
|
174
503
|
requestId: request.requestId,
|
|
175
504
|
kind,
|
|
176
505
|
title: payloadString(request.payload, ["title", "message", "reason", "prompt", "summary"]) ?? fallback,
|
|
177
|
-
body
|
|
178
|
-
...
|
|
506
|
+
...body !== undefined ? { body } : {},
|
|
507
|
+
...options ? { options } : {},
|
|
179
508
|
requestedAt: request.requestedAt ?? null,
|
|
180
509
|
source: "run"
|
|
181
510
|
};
|
|
@@ -253,7 +582,7 @@ function runRecordFromRegistryEntry(projectRoot, entry) {
|
|
|
253
582
|
const runId = stringOrNull(projection.runId) ?? entry.roomId;
|
|
254
583
|
const folded = emptyFoldedProjection(runId, projection);
|
|
255
584
|
const pushedStatus = registryStatusAsRunStatus(projection.status) ?? folded.status ?? registryStatusAsRunStatus(entry.status);
|
|
256
|
-
const status = entry.stale ? pushedStatus &&
|
|
585
|
+
const status = entry.stale ? pushedStatus && isTerminalRunStatus(pushedStatus) ? pushedStatus : "stale" : pushedStatus ?? "running";
|
|
257
586
|
const sessionPath = stringOrNull(projection.sessionPath) ?? stringOrNull(entry.sessionPath) ?? null;
|
|
258
587
|
const collabCwd = stringOrNull(projection.collabCwd) ?? stringOrNull(projection.cwd) ?? stringOrNull(entry.cwd) ?? stringOrNull(projection.worktreePath);
|
|
259
588
|
return {
|
|
@@ -284,8 +613,8 @@ function runRecordFromRegistryEntry(projectRoot, entry) {
|
|
|
284
613
|
projection: folded
|
|
285
614
|
};
|
|
286
615
|
}
|
|
287
|
-
function
|
|
288
|
-
return sortByRecency(
|
|
616
|
+
function runRecordsFromCollab(projectRoot, collabs) {
|
|
617
|
+
return sortByRecency(collabs.map((collab) => runRecordFromRegistryEntry(projectRoot, registryEntryFromCollab(collab))).filter((record) => record !== null));
|
|
289
618
|
}
|
|
290
619
|
function sortByRecency(records) {
|
|
291
620
|
return [...records].sort((a, b) => {
|
|
@@ -333,8 +662,11 @@ function discoveryDiagnosticRunRecord(projectRoot, error) {
|
|
|
333
662
|
}
|
|
334
663
|
async function listRunProjections(projectRoot, filter = {}) {
|
|
335
664
|
try {
|
|
336
|
-
const
|
|
337
|
-
|
|
665
|
+
const discovery = await loadCapabilityForRoot(projectRoot, RunDiscoveryCap);
|
|
666
|
+
if (!discovery)
|
|
667
|
+
return [discoveryDiagnosticRunRecord(projectRoot, "run discovery capability unavailable")];
|
|
668
|
+
const collabs = await discovery.listActiveRunCollab(projectRoot, filter);
|
|
669
|
+
return runRecordsFromCollab(projectRoot, collabs);
|
|
338
670
|
} catch (error) {
|
|
339
671
|
return [discoveryDiagnosticRunRecord(projectRoot, error)];
|
|
340
672
|
}
|
|
@@ -365,35 +697,20 @@ async function resolveRunJoinTarget(projectRoot, runId, filter = {}) {
|
|
|
365
697
|
return null;
|
|
366
698
|
return { runId: run.runId, taskId: run.taskId, joinLink: run.joinLink, cwd: run.collabCwd ?? run.sessionPath, stale: run.stale };
|
|
367
699
|
}
|
|
368
|
-
var EMPTY_PROJECTION, DISCOVERY_DIAGNOSTIC_RUN_ID = "__registry_discovery_error__", listRuns, getRun, resolveJoinTarget;
|
|
700
|
+
var RunDiscoveryCap, EMPTY_PROJECTION, DISCOVERY_DIAGNOSTIC_RUN_ID = "__registry_discovery_error__", listRuns, getRun, resolveJoinTarget;
|
|
369
701
|
var init_projection = __esm(() => {
|
|
370
|
-
|
|
702
|
+
init_session_journal();
|
|
703
|
+
init_run_status();
|
|
704
|
+
RunDiscoveryCap = defineCapability(RUN_DISCOVERY);
|
|
371
705
|
EMPTY_PROJECTION = foldRunSessionEntries([], "");
|
|
372
706
|
listRuns = listRunProjections;
|
|
373
707
|
getRun = getRunProjection;
|
|
374
708
|
resolveJoinTarget = resolveRunJoinTarget;
|
|
375
709
|
});
|
|
376
710
|
|
|
377
|
-
// packages/run-worker/src/
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
TERMINAL_RUN_STATUSES,
|
|
381
|
-
isActiveRunStatus,
|
|
382
|
-
isTerminalRunStatus,
|
|
383
|
-
normalizeRunStatusToken
|
|
384
|
-
} from "@rig/contracts";
|
|
385
|
-
var KNOWN_RUN_STATUS = Object.fromEntries([...ACTIVE_RUN_STATUSES, ...TERMINAL_RUN_STATUSES].map((status) => [status, true]));
|
|
386
|
-
function canonicalStatusToken(status) {
|
|
387
|
-
const normalized = normalizeRunStatusToken(status);
|
|
388
|
-
if (normalized === "waiting-input")
|
|
389
|
-
return "waiting-user-input";
|
|
390
|
-
return normalized;
|
|
391
|
-
}
|
|
392
|
-
function isNeedsAttention(run) {
|
|
393
|
-
return canonicalStatusToken(run.status) === "needs-attention" || run.pendingApprovals + run.pendingInputs > 0 || run.stallCount > 0;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// packages/run-worker/src/runs/stats.ts
|
|
711
|
+
// packages/run-worker/src/read-model-backend/stats.ts
|
|
712
|
+
init_run_status();
|
|
713
|
+
init_run_status();
|
|
397
714
|
function parseTimestamp(value) {
|
|
398
715
|
if (!value)
|
|
399
716
|
return null;
|
|
@@ -473,13 +790,11 @@ async function computeStats(projectRootOrRuns, options = {}) {
|
|
|
473
790
|
approvalsPending
|
|
474
791
|
};
|
|
475
792
|
}
|
|
476
|
-
var computeRigStats = computeStats;
|
|
477
793
|
export {
|
|
478
794
|
rate,
|
|
479
795
|
parseTimestamp,
|
|
480
796
|
median,
|
|
481
797
|
isNeedsAttention,
|
|
482
798
|
computeStats,
|
|
483
|
-
computeRigStats,
|
|
484
799
|
completedDuration
|
|
485
800
|
};
|