@h-rig/cli 0.0.6-alpha.93 → 0.0.6-alpha.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -27
- package/bin/rig.js +16 -0
- package/package.json +14 -40
- package/dist/bin/build-rig-binaries.d.ts +0 -2
- package/dist/bin/build-rig-binaries.js +0 -119
- package/dist/bin/rig.d.ts +0 -72
- package/dist/bin/rig.js +0 -17845
- package/dist/config/rig-default-config.yml +0 -5
- package/dist/src/app/drone-ui.d.ts +0 -34
- package/dist/src/app/drone-ui.js +0 -278
- package/dist/src/commands/_async-ui.d.ts +0 -10
- package/dist/src/commands/_async-ui.js +0 -121
- package/dist/src/commands/_cli-format.d.ts +0 -56
- package/dist/src/commands/_cli-format.js +0 -319
- package/dist/src/commands/_connection-state.d.ts +0 -54
- package/dist/src/commands/_connection-state.js +0 -187
- package/dist/src/commands/_doctor-checks.d.ts +0 -46
- package/dist/src/commands/_doctor-checks.js +0 -352
- package/dist/src/commands/_help-catalog.d.ts +0 -51
- package/dist/src/commands/_help-catalog.js +0 -502
- package/dist/src/commands/_inprocess-services.d.ts +0 -33
- package/dist/src/commands/_inprocess-services.js +0 -102
- package/dist/src/commands/_json-output.d.ts +0 -11
- package/dist/src/commands/_json-output.js +0 -60
- package/dist/src/commands/_lazy-reconcile.d.ts +0 -34
- package/dist/src/commands/_lazy-reconcile.js +0 -102
- package/dist/src/commands/_parsers.d.ts +0 -15
- package/dist/src/commands/_parsers.js +0 -114
- package/dist/src/commands/_paths.d.ts +0 -11
- package/dist/src/commands/_paths.js +0 -50
- package/dist/src/commands/_pi-frontend.d.ts +0 -35
- package/dist/src/commands/_pi-frontend.js +0 -64
- package/dist/src/commands/_pi-install.d.ts +0 -42
- package/dist/src/commands/_pi-install.js +0 -167
- package/dist/src/commands/_policy.d.ts +0 -8
- package/dist/src/commands/_policy.js +0 -127
- package/dist/src/commands/_probes.d.ts +0 -1
- package/dist/src/commands/_probes.js +0 -13
- package/dist/src/commands/_run-bridge.d.ts +0 -114
- package/dist/src/commands/_run-bridge.js +0 -387
- package/dist/src/commands/_run-diagnostics.d.ts +0 -9
- package/dist/src/commands/_run-diagnostics.js +0 -51
- package/dist/src/commands/_run-driver-helpers.d.ts +0 -26
- package/dist/src/commands/_run-driver-helpers.js +0 -138
- package/dist/src/commands/_run-projection.d.ts +0 -50
- package/dist/src/commands/_run-projection.js +0 -349
- package/dist/src/commands/_run-subcommands.d.ts +0 -3
- package/dist/src/commands/_run-subcommands.js +0 -31
- package/dist/src/commands/_spinner.d.ts +0 -25
- package/dist/src/commands/_spinner.js +0 -65
- package/dist/src/commands/agent.d.ts +0 -3
- package/dist/src/commands/agent.js +0 -8837
- package/dist/src/commands/dist.d.ts +0 -28
- package/dist/src/commands/dist.js +0 -417
- package/dist/src/commands/doctor.d.ts +0 -3
- package/dist/src/commands/doctor.js +0 -480
- package/dist/src/commands/github.d.ts +0 -3
- package/dist/src/commands/github.js +0 -342
- package/dist/src/commands/inbox.d.ts +0 -28
- package/dist/src/commands/inbox.js +0 -579
- package/dist/src/commands/init.d.ts +0 -64
- package/dist/src/commands/init.js +0 -1541
- package/dist/src/commands/inspect.d.ts +0 -20
- package/dist/src/commands/inspect.js +0 -764
- package/dist/src/commands/pi.d.ts +0 -3
- package/dist/src/commands/pi.js +0 -177
- package/dist/src/commands/plugin.d.ts +0 -16
- package/dist/src/commands/plugin.js +0 -714
- package/dist/src/commands/profile-and-review.d.ts +0 -4
- package/dist/src/commands/profile-and-review.js +0 -223
- package/dist/src/commands/queue.d.ts +0 -3
- package/dist/src/commands/queue.js +0 -197
- package/dist/src/commands/remote.d.ts +0 -3
- package/dist/src/commands/remote.js +0 -1337
- package/dist/src/commands/repo-git-harness.d.ts +0 -5
- package/dist/src/commands/repo-git-harness.js +0 -271
- package/dist/src/commands/run.d.ts +0 -21
- package/dist/src/commands/run.js +0 -17837
- package/dist/src/commands/server.d.ts +0 -3
- package/dist/src/commands/server.js +0 -249
- package/dist/src/commands/setup.d.ts +0 -16
- package/dist/src/commands/setup.js +0 -644
- package/dist/src/commands/stats.d.ts +0 -15
- package/dist/src/commands/stats.js +0 -979
- package/dist/src/commands/task-run-driver.d.ts +0 -94
- package/dist/src/commands/task-run-driver.js +0 -203
- package/dist/src/commands/task.d.ts +0 -35
- package/dist/src/commands/task.js +0 -818
- package/dist/src/commands/test.d.ts +0 -3
- package/dist/src/commands/test.js +0 -46
- package/dist/src/commands/triage.d.ts +0 -11
- package/dist/src/commands/triage.js +0 -227
- package/dist/src/commands/workspace.d.ts +0 -3
- package/dist/src/commands/workspace.js +0 -130
- package/dist/src/commands.d.ts +0 -13
- package/dist/src/commands.js +0 -17969
- package/dist/src/index.d.ts +0 -4
- package/dist/src/index.js +0 -17981
- package/dist/src/launcher.d.ts +0 -61
- package/dist/src/launcher.js +0 -199
- package/dist/src/operator-cli.d.ts +0 -2
- package/dist/src/operator-cli.js +0 -17837
- package/dist/src/operator-entry.d.ts +0 -1
- package/dist/src/operator-entry.js +0 -3
- package/dist/src/runner.d.ts +0 -47
- package/dist/src/runner.js +0 -267
- package/dist/src/withMutedConsole.d.ts +0 -2
- package/dist/src/withMutedConsole.js +0 -42
|
@@ -1,764 +0,0 @@
|
|
|
1
|
-
// @bun
|
|
2
|
-
// packages/cli/src/commands/inspect.ts
|
|
3
|
-
import { RIG_RUN_LOG_ENTRY } from "@rig/contracts";
|
|
4
|
-
import {
|
|
5
|
-
changedFilesForTask,
|
|
6
|
-
taskArtifactRead,
|
|
7
|
-
taskArtifacts,
|
|
8
|
-
taskDeps
|
|
9
|
-
} from "@rig/runtime/control-plane/native/task-ops";
|
|
10
|
-
|
|
11
|
-
// packages/cli/src/runner.ts
|
|
12
|
-
import { EventBus } from "@rig/runtime/control-plane/runtime/events";
|
|
13
|
-
import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
|
|
14
|
-
import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
|
|
15
|
-
import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
|
|
16
|
-
|
|
17
|
-
class CliError extends RuntimeCliError {
|
|
18
|
-
hint;
|
|
19
|
-
constructor(message, exitCode = 1, options = {}) {
|
|
20
|
-
super(message, exitCode);
|
|
21
|
-
if (options.hint?.trim()) {
|
|
22
|
-
this.hint = options.hint.trim();
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function takeOption(args, option) {
|
|
27
|
-
const rest = [];
|
|
28
|
-
let value;
|
|
29
|
-
for (let index = 0;index < args.length; index += 1) {
|
|
30
|
-
const current = args[index];
|
|
31
|
-
if (current === option) {
|
|
32
|
-
const next = args[index + 1];
|
|
33
|
-
if (!next || next.startsWith("-")) {
|
|
34
|
-
throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
|
|
35
|
-
}
|
|
36
|
-
value = next;
|
|
37
|
-
index += 1;
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
if (current !== undefined) {
|
|
41
|
-
rest.push(current);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return { value, rest };
|
|
45
|
-
}
|
|
46
|
-
function requireNoExtraArgs(args, usage) {
|
|
47
|
-
if (args.length > 0) {
|
|
48
|
-
throw new CliError(`Unexpected arguments: ${args.join(" ")}
|
|
49
|
-
Usage: ${usage}`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function requireTask(taskId, usage) {
|
|
53
|
-
if (!taskId) {
|
|
54
|
-
throw new CliError(`Missing --task option.
|
|
55
|
-
Usage: ${usage}`);
|
|
56
|
-
}
|
|
57
|
-
return taskId;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// packages/cli/src/commands/_cli-format.ts
|
|
61
|
-
import pc from "picocolors";
|
|
62
|
-
var dim = pc.dim;
|
|
63
|
-
var faintBar = pc.dim("\u2502");
|
|
64
|
-
var accent = pc.cyan;
|
|
65
|
-
function truncate(value, width) {
|
|
66
|
-
return value.length <= width ? value : `${value.slice(0, Math.max(0, width - 1))}\u2026`;
|
|
67
|
-
}
|
|
68
|
-
function pad(value, width) {
|
|
69
|
-
return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
|
|
70
|
-
}
|
|
71
|
-
function statusColor(status) {
|
|
72
|
-
const normalized = status.trim().toLowerCase();
|
|
73
|
-
if (["done", "completed", "ready", "healthy", "open", "approved"].includes(normalized))
|
|
74
|
-
return pc.green;
|
|
75
|
-
if (["failed", "error", "blocked", "rejected", "stopped"].includes(normalized))
|
|
76
|
-
return pc.red;
|
|
77
|
-
if (["running", "in_progress", "in-progress", "active", "booting"].includes(normalized))
|
|
78
|
-
return pc.cyan;
|
|
79
|
-
if (["pending", "queued", "created", "local"].includes(normalized))
|
|
80
|
-
return pc.yellow;
|
|
81
|
-
return pc.dim;
|
|
82
|
-
}
|
|
83
|
-
function firstString(record, keys, fallback = "") {
|
|
84
|
-
for (const key of keys) {
|
|
85
|
-
const value = record[key];
|
|
86
|
-
if (typeof value === "string" && value.trim())
|
|
87
|
-
return value;
|
|
88
|
-
}
|
|
89
|
-
return fallback;
|
|
90
|
-
}
|
|
91
|
-
function runIdOf(run) {
|
|
92
|
-
return firstString(run, ["runId", "id"], "(unknown-run)");
|
|
93
|
-
}
|
|
94
|
-
function taskIdOf(run) {
|
|
95
|
-
return firstString(run, ["taskId", "task", "task_id"]);
|
|
96
|
-
}
|
|
97
|
-
function runTitleOf(run) {
|
|
98
|
-
return firstString(run, ["title", "summary", "name"], taskIdOf(run) || "(untitled)");
|
|
99
|
-
}
|
|
100
|
-
function printFormattedOutput(message) {
|
|
101
|
-
console.log(message);
|
|
102
|
-
}
|
|
103
|
-
function formatSection(title, subtitle) {
|
|
104
|
-
return `${pc.bold(accent("\u25C6"))} ${pc.bold(title)}${subtitle ? dim(` \u2014 ${subtitle}`) : ""}`;
|
|
105
|
-
}
|
|
106
|
-
function formatLegacyAutomationSurface() {
|
|
107
|
-
return [];
|
|
108
|
-
}
|
|
109
|
-
function formatRunList(runs, options = {}) {
|
|
110
|
-
if (runs.length === 0) {
|
|
111
|
-
return [
|
|
112
|
-
formatSection("Runs", "none recorded"),
|
|
113
|
-
options.source === "server" ? dim("No runs recorded on the selected server.") : dim("No runs recorded in local state."),
|
|
114
|
-
"",
|
|
115
|
-
...formatLegacyAutomationSurface()
|
|
116
|
-
].join(`
|
|
117
|
-
`);
|
|
118
|
-
}
|
|
119
|
-
const body = runs.map((run) => {
|
|
120
|
-
const row = run;
|
|
121
|
-
const runId = runIdOf(row);
|
|
122
|
-
const status = firstString(row, ["status"], "unknown");
|
|
123
|
-
const runtime = firstString(row, ["runtime", "runtimeAdapter"], "");
|
|
124
|
-
return [
|
|
125
|
-
pc.bold(runId),
|
|
126
|
-
statusColor(status)(pad(truncate(status, 12), 12)),
|
|
127
|
-
`${runTitleOf(row)}${runtime ? dim(` ${runtime}`) : ""}`
|
|
128
|
-
].join(" ");
|
|
129
|
-
});
|
|
130
|
-
return [formatSection("Runs", options.source === "server" ? "selected server" : "local state"), ...body, "", ...formatLegacyAutomationSurface()].join(`
|
|
131
|
-
`);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// packages/cli/src/commands/_run-projection.ts
|
|
135
|
-
import { existsSync as existsSync2, readdirSync as readdirSync2, readFileSync as readFileSync2 } from "fs";
|
|
136
|
-
import { resolve as resolve2 } from "path";
|
|
137
|
-
import {
|
|
138
|
-
foldRunSessionEntries,
|
|
139
|
-
sessionIdFromSessionFile as sessionIdFromSessionFile2
|
|
140
|
-
} from "@rig/contracts";
|
|
141
|
-
import { listAgentRuntimes as listAgentRuntimes2 } from "@rig/runtime/control-plane/runtime/isolation";
|
|
142
|
-
|
|
143
|
-
// packages/cli/src/commands/_run-bridge.ts
|
|
144
|
-
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
145
|
-
import { dirname, resolve } from "path";
|
|
146
|
-
import { CUSTOM_TYPE_FOR, sessionIdFromSessionFile } from "@rig/contracts";
|
|
147
|
-
import { createPluginHost } from "@rig/core";
|
|
148
|
-
import { loadConfig } from "@rig/core/load-config";
|
|
149
|
-
import { resolveOwnerNamespaceKey, resolveRegistryBaseUrl, resolveRegistrySecret, resolveSelectedRemote } from "@rig/runtime/control-plane/remote";
|
|
150
|
-
import { listAgentRuntimes } from "@rig/runtime/control-plane/runtime/isolation";
|
|
151
|
-
import { createRegistryClient } from "@rig/relay-registry";
|
|
152
|
-
import {
|
|
153
|
-
listActiveCollabSessions as ompListActiveCollabSessions
|
|
154
|
-
} from "@oh-my-pi/pi-coding-agent/collab/api";
|
|
155
|
-
function registrySecret(env = process.env) {
|
|
156
|
-
return resolveRegistrySecret(process.cwd(), env) ?? null;
|
|
157
|
-
}
|
|
158
|
-
function registryBaseUrl(env = process.env) {
|
|
159
|
-
return resolveRegistryBaseUrl(process.cwd(), env);
|
|
160
|
-
}
|
|
161
|
-
function collabFromRegistryEntry(entry) {
|
|
162
|
-
return {
|
|
163
|
-
sessionId: entry.roomId,
|
|
164
|
-
sessionPath: "",
|
|
165
|
-
cwd: "",
|
|
166
|
-
title: entry.title,
|
|
167
|
-
joinLink: entry.joinLink,
|
|
168
|
-
webLink: entry.webLink,
|
|
169
|
-
relayUrl: entry.relayUrl,
|
|
170
|
-
owner: entry.owner,
|
|
171
|
-
selectedRepo: entry.repo,
|
|
172
|
-
startedAt: entry.startedAt,
|
|
173
|
-
updatedAt: entry.heartbeatAt,
|
|
174
|
-
...entry.pid === undefined ? {} : { pid: entry.pid },
|
|
175
|
-
stale: entry.stale
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
function isRecord(value) {
|
|
179
|
-
return typeof value === "object" && value !== null;
|
|
180
|
-
}
|
|
181
|
-
function readLocalRunCollab(runtime) {
|
|
182
|
-
if (!runtime.sessionDir || !existsSync(runtime.sessionDir))
|
|
183
|
-
return null;
|
|
184
|
-
let files;
|
|
185
|
-
try {
|
|
186
|
-
files = readdirSync(runtime.sessionDir).filter((f) => f.endsWith(".jsonl")).sort().reverse();
|
|
187
|
-
} catch {
|
|
188
|
-
return null;
|
|
189
|
-
}
|
|
190
|
-
for (const file of files) {
|
|
191
|
-
let lines;
|
|
192
|
-
try {
|
|
193
|
-
lines = readFileSync(resolve(runtime.sessionDir, file), "utf8").split(`
|
|
194
|
-
`);
|
|
195
|
-
} catch {
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
let host = null;
|
|
199
|
-
for (const line of lines) {
|
|
200
|
-
if (!line.includes("collab-host-started"))
|
|
201
|
-
continue;
|
|
202
|
-
let entry;
|
|
203
|
-
try {
|
|
204
|
-
entry = JSON.parse(line);
|
|
205
|
-
} catch {
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
if (!isRecord(entry) || entry.customType !== CUSTOM_TYPE_FOR["timeline-entry"] || !isRecord(entry.data))
|
|
209
|
-
continue;
|
|
210
|
-
const payload = isRecord(entry.data.payload) ? entry.data.payload : entry.data;
|
|
211
|
-
if (payload.type !== "collab-host-started")
|
|
212
|
-
continue;
|
|
213
|
-
host = {
|
|
214
|
-
roomId: typeof payload.roomId === "string" ? payload.roomId : undefined,
|
|
215
|
-
joinLink: typeof payload.joinLink === "string" ? payload.joinLink : undefined,
|
|
216
|
-
webLink: typeof payload.webLink === "string" ? payload.webLink : undefined,
|
|
217
|
-
relayUrl: typeof payload.relayUrl === "string" ? payload.relayUrl : undefined,
|
|
218
|
-
at: typeof entry.data.at === "string" ? entry.data.at : undefined
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
if (!host?.joinLink)
|
|
222
|
-
continue;
|
|
223
|
-
const at = host.at ?? "";
|
|
224
|
-
const sessionId = host.roomId ?? sessionIdFromSessionFile(resolve(runtime.sessionDir, file)) ?? runtime.id;
|
|
225
|
-
return {
|
|
226
|
-
sessionId,
|
|
227
|
-
sessionPath: resolve(runtime.sessionDir, file),
|
|
228
|
-
cwd: runtime.workspaceDir,
|
|
229
|
-
joinLink: host.joinLink,
|
|
230
|
-
webLink: host.webLink ?? "",
|
|
231
|
-
relayUrl: host.relayUrl ?? "",
|
|
232
|
-
title: runtime.taskId ? `[${runtime.taskId}] Rig run ${sessionId}` : `Rig run ${sessionId}`,
|
|
233
|
-
startedAt: at,
|
|
234
|
-
updatedAt: at,
|
|
235
|
-
stale: false
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
return null;
|
|
239
|
-
}
|
|
240
|
-
async function listLocalRunCollabSessions(projectRoot) {
|
|
241
|
-
let runtimes;
|
|
242
|
-
try {
|
|
243
|
-
runtimes = await listAgentRuntimes(projectRoot);
|
|
244
|
-
} catch {
|
|
245
|
-
return [];
|
|
246
|
-
}
|
|
247
|
-
const out = [];
|
|
248
|
-
for (const runtime of runtimes) {
|
|
249
|
-
const collab = readLocalRunCollab(runtime);
|
|
250
|
-
if (collab)
|
|
251
|
-
out.push(collab);
|
|
252
|
-
}
|
|
253
|
-
return out;
|
|
254
|
-
}
|
|
255
|
-
async function listActiveRunCollab(filter) {
|
|
256
|
-
return defaultListActiveCollabSessions(filter);
|
|
257
|
-
}
|
|
258
|
-
async function defaultListActiveCollabSessions(filter) {
|
|
259
|
-
const projectRoot = process.cwd();
|
|
260
|
-
const local = await listLocalRunCollabSessions(projectRoot);
|
|
261
|
-
const namespaceKey = filter.namespaceKey ?? resolveOwnerNamespaceKey(projectRoot);
|
|
262
|
-
const secret = registrySecret();
|
|
263
|
-
const remote = namespaceKey && secret ? (await createRegistryClient({ baseUrl: registryBaseUrl(), namespaceKey, secret }).listRoomsByOwner(filter)).map(collabFromRegistryEntry) : await ompListActiveCollabSessions(filter);
|
|
264
|
-
const seen = new Set(local.map((c) => c.sessionId));
|
|
265
|
-
return [...local, ...remote.filter((c) => !seen.has(c.sessionId))];
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// packages/cli/src/commands/_run-diagnostics.ts
|
|
269
|
-
function normalizeString(value) {
|
|
270
|
-
if (typeof value !== "string")
|
|
271
|
-
return null;
|
|
272
|
-
const normalized = value.replace(/\s+/g, " ").trim();
|
|
273
|
-
return normalized.length > 0 ? normalized : null;
|
|
274
|
-
}
|
|
275
|
-
function isGenericRunFailure(value) {
|
|
276
|
-
const text = normalizeString(value);
|
|
277
|
-
return Boolean(text && /^Task run failed \([^)]*\)$/i.test(text));
|
|
278
|
-
}
|
|
279
|
-
function appendCandidate(candidates, value) {
|
|
280
|
-
const text = normalizeString(value);
|
|
281
|
-
if (text && !candidates.includes(text))
|
|
282
|
-
candidates.push(text);
|
|
283
|
-
}
|
|
284
|
-
function categorizeUsefulRunError(lines) {
|
|
285
|
-
const taskSourceFailure = lines.find((line) => /failed to update task source/i.test(line));
|
|
286
|
-
if (taskSourceFailure)
|
|
287
|
-
return `Task source update failed: ${taskSourceFailure}`;
|
|
288
|
-
const moduleFailure = lines.find((line) => /cannot find module/i.test(line));
|
|
289
|
-
if (moduleFailure)
|
|
290
|
-
return `Runtime module resolution failed: ${moduleFailure}`;
|
|
291
|
-
const providerFailure = lines.find((line) => /no api key found|unauthorized|authentication failed|invalid api key/i.test(line));
|
|
292
|
-
if (providerFailure)
|
|
293
|
-
return `Provider authentication failed: ${providerFailure}`;
|
|
294
|
-
return null;
|
|
295
|
-
}
|
|
296
|
-
function summarizeUsefulRunError(projection) {
|
|
297
|
-
if (projection.status !== "failed")
|
|
298
|
-
return null;
|
|
299
|
-
const candidates = [];
|
|
300
|
-
for (const anomaly of projection.anomalies) {
|
|
301
|
-
appendCandidate(candidates, `Journal anomaly (${anomaly.kind}): ${anomaly.detail}`);
|
|
302
|
-
}
|
|
303
|
-
for (const phase of projection.closeoutPhases) {
|
|
304
|
-
if (phase.outcome === "failed")
|
|
305
|
-
appendCandidate(candidates, phase.detail);
|
|
306
|
-
}
|
|
307
|
-
for (const entry of projection.statusHistory) {
|
|
308
|
-
appendCandidate(candidates, entry.reason);
|
|
309
|
-
}
|
|
310
|
-
appendCandidate(candidates, projection.record.statusDetail);
|
|
311
|
-
appendCandidate(candidates, projection.record.errorText);
|
|
312
|
-
const nonGeneric = candidates.filter((candidate) => !isGenericRunFailure(candidate));
|
|
313
|
-
return categorizeUsefulRunError(nonGeneric) ?? nonGeneric.at(-1) ?? normalizeString(projection.record.errorText);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// packages/cli/src/commands/_run-projection.ts
|
|
317
|
-
var EMPTY_PROJECTION = foldRunSessionEntries([], "");
|
|
318
|
-
function stringOrNull(value) {
|
|
319
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
|
|
320
|
-
}
|
|
321
|
-
function newestSessionFile(sessionDir) {
|
|
322
|
-
if (!sessionDir || !existsSync2(sessionDir))
|
|
323
|
-
return null;
|
|
324
|
-
try {
|
|
325
|
-
const files = readdirSync2(sessionDir).filter((file) => file.endsWith(".jsonl")).sort().reverse();
|
|
326
|
-
return files[0] ? resolve2(sessionDir, files[0]) : null;
|
|
327
|
-
} catch {
|
|
328
|
-
return null;
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
function readSessionRunEntries(sessionPath) {
|
|
332
|
-
if (!sessionPath || !existsSync2(sessionPath))
|
|
333
|
-
return [];
|
|
334
|
-
let raw;
|
|
335
|
-
try {
|
|
336
|
-
raw = readFileSync2(sessionPath, "utf8");
|
|
337
|
-
} catch {
|
|
338
|
-
return [];
|
|
339
|
-
}
|
|
340
|
-
const entries = [];
|
|
341
|
-
for (const line of raw.split(`
|
|
342
|
-
`)) {
|
|
343
|
-
if (!line.trim())
|
|
344
|
-
continue;
|
|
345
|
-
let parsed;
|
|
346
|
-
try {
|
|
347
|
-
parsed = JSON.parse(line);
|
|
348
|
-
} catch {
|
|
349
|
-
continue;
|
|
350
|
-
}
|
|
351
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
352
|
-
continue;
|
|
353
|
-
entries.push({
|
|
354
|
-
type: "type" in parsed && typeof parsed.type === "string" ? parsed.type : "",
|
|
355
|
-
..."customType" in parsed && typeof parsed.customType === "string" ? { customType: parsed.customType } : {},
|
|
356
|
-
..."data" in parsed ? { data: parsed.data } : {}
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
return entries;
|
|
360
|
-
}
|
|
361
|
-
function recordFromProjection(runId, projection, presence) {
|
|
362
|
-
const record = projection.record;
|
|
363
|
-
const status = projection.status ?? (presence.stale ? "stale" : presence.live ? "running" : "unknown");
|
|
364
|
-
const taskId = stringOrNull(record.taskId) ?? presence.fallbackTaskId ?? null;
|
|
365
|
-
const title = stringOrNull(record.title) ?? stringOrNull(presence.title) ?? (taskId ? `Run ${taskId}` : `Rig run ${runId}`);
|
|
366
|
-
return {
|
|
367
|
-
runId,
|
|
368
|
-
taskId,
|
|
369
|
-
title,
|
|
370
|
-
status,
|
|
371
|
-
source: presence.source,
|
|
372
|
-
live: presence.live,
|
|
373
|
-
stale: presence.stale,
|
|
374
|
-
startedAt: stringOrNull(record.startedAt) ?? presence.startedAt ?? null,
|
|
375
|
-
updatedAt: stringOrNull(record.updatedAt) ?? presence.updatedAt ?? projection.lastEventAt ?? null,
|
|
376
|
-
completedAt: stringOrNull(record.completedAt),
|
|
377
|
-
joinLink: presence.joinLink ?? null,
|
|
378
|
-
webLink: presence.webLink ?? null,
|
|
379
|
-
relayUrl: presence.relayUrl ?? null,
|
|
380
|
-
sessionPath: stringOrNull(record.sessionPath) ?? presence.sessionPath ?? null,
|
|
381
|
-
prUrl: stringOrNull(record.prUrl),
|
|
382
|
-
worktreePath: stringOrNull(record.worktreePath),
|
|
383
|
-
pendingApprovals: projection.pendingApprovals.length,
|
|
384
|
-
pendingInputs: projection.pendingUserInputs.length,
|
|
385
|
-
steeringCount: projection.steeringCount,
|
|
386
|
-
stallCount: projection.stallCount,
|
|
387
|
-
errorSummary: summarizeUsefulRunError(projection),
|
|
388
|
-
projection
|
|
389
|
-
};
|
|
390
|
-
}
|
|
391
|
-
function recordFromLiveCollab(collab) {
|
|
392
|
-
const runId = collab.sessionId;
|
|
393
|
-
const sessionPath = stringOrNull(collab.sessionPath);
|
|
394
|
-
const projection = sessionPath ? foldRunSessionEntries(readSessionRunEntries(sessionPath), runId) : EMPTY_PROJECTION;
|
|
395
|
-
return recordFromProjection(runId, projection, {
|
|
396
|
-
source: sessionPath ? "local" : "remote",
|
|
397
|
-
live: !collab.stale,
|
|
398
|
-
stale: Boolean(collab.stale),
|
|
399
|
-
title: collab.title,
|
|
400
|
-
joinLink: stringOrNull(collab.joinLink),
|
|
401
|
-
webLink: stringOrNull(collab.webLink),
|
|
402
|
-
relayUrl: stringOrNull(collab.relayUrl),
|
|
403
|
-
sessionPath,
|
|
404
|
-
startedAt: stringOrNull(collab.startedAt),
|
|
405
|
-
updatedAt: stringOrNull(collab.updatedAt)
|
|
406
|
-
});
|
|
407
|
-
}
|
|
408
|
-
function recordFromRuntime(runtime) {
|
|
409
|
-
const sessionPath = newestSessionFile(runtime.sessionDir ?? "");
|
|
410
|
-
if (!sessionPath)
|
|
411
|
-
return null;
|
|
412
|
-
const projection = foldRunSessionEntries(readSessionRunEntries(sessionPath), runtime.id);
|
|
413
|
-
if (projection.lastSeq === 0)
|
|
414
|
-
return null;
|
|
415
|
-
return recordFromProjection(sessionIdFromSessionFile2(sessionPath) ?? runtime.id, projection, {
|
|
416
|
-
source: "local",
|
|
417
|
-
live: false,
|
|
418
|
-
stale: false,
|
|
419
|
-
sessionPath,
|
|
420
|
-
fallbackTaskId: stringOrNull(runtime.taskId)
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
function sortByRecency(records) {
|
|
424
|
-
return [...records].sort((a, b) => {
|
|
425
|
-
const at = Date.parse(b.updatedAt ?? b.startedAt ?? "") || 0;
|
|
426
|
-
const bt = Date.parse(a.updatedAt ?? a.startedAt ?? "") || 0;
|
|
427
|
-
return at - bt;
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
async function listRunProjections(projectRoot, filter = {}) {
|
|
431
|
-
const byRunId = new Map;
|
|
432
|
-
let live = [];
|
|
433
|
-
try {
|
|
434
|
-
live = await listActiveRunCollab(filter);
|
|
435
|
-
} catch {
|
|
436
|
-
live = [];
|
|
437
|
-
}
|
|
438
|
-
for (const collab of live) {
|
|
439
|
-
const record = recordFromLiveCollab(collab);
|
|
440
|
-
byRunId.set(record.runId, record);
|
|
441
|
-
}
|
|
442
|
-
let runtimes = [];
|
|
443
|
-
try {
|
|
444
|
-
runtimes = await listAgentRuntimes2(projectRoot);
|
|
445
|
-
} catch {
|
|
446
|
-
runtimes = [];
|
|
447
|
-
}
|
|
448
|
-
for (const runtime of runtimes) {
|
|
449
|
-
const record = recordFromRuntime(runtime);
|
|
450
|
-
if (!record)
|
|
451
|
-
continue;
|
|
452
|
-
const sessionId = sessionIdFromSessionFile2(record.sessionPath);
|
|
453
|
-
const liveMatch = sessionId ? byRunId.get(sessionId) : undefined;
|
|
454
|
-
if (liveMatch) {
|
|
455
|
-
if (liveMatch.source === "remote" || !liveMatch.sessionPath) {
|
|
456
|
-
byRunId.set(liveMatch.runId, { ...liveMatch, sessionPath: record.sessionPath, source: "local" });
|
|
457
|
-
}
|
|
458
|
-
continue;
|
|
459
|
-
}
|
|
460
|
-
if (byRunId.has(runtime.id))
|
|
461
|
-
continue;
|
|
462
|
-
byRunId.set(record.runId, record);
|
|
463
|
-
}
|
|
464
|
-
return sortByRecency([...byRunId.values()]);
|
|
465
|
-
}
|
|
466
|
-
async function getRunProjection(projectRoot, runId, filter = {}) {
|
|
467
|
-
const runs = await listRunProjections(projectRoot, filter);
|
|
468
|
-
return runs.find((run) => run.runId === runId) ?? runs.find((run) => run.runId.startsWith(runId)) ?? runs.find((run) => run.taskId === runId) ?? null;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
// packages/cli/src/commands/inspect.ts
|
|
472
|
-
var INSPECT_USAGE = "rig inspect <logs|artifact|artifacts|run-logs|runs|failures|graph|audit|diff>";
|
|
473
|
-
function printInspectHelp() {
|
|
474
|
-
console.log([
|
|
475
|
-
`Usage: ${INSPECT_USAGE}`,
|
|
476
|
-
"",
|
|
477
|
-
"Commands:",
|
|
478
|
-
" logs --task <id> Print log lines from the latest projected run for a task.",
|
|
479
|
-
" artifact --task <id> --file <name>",
|
|
480
|
-
" Preview a single task artifact.",
|
|
481
|
-
" artifacts --task <id> List task artifacts.",
|
|
482
|
-
" run-logs --run <id> Print log lines from a run journal.",
|
|
483
|
-
" runs List all projected runs.",
|
|
484
|
-
" diff --task <id> List files changed by a task.",
|
|
485
|
-
" graph [--task <id>] Print the task dependency graph.",
|
|
486
|
-
" failures --task <id> Summarize failed runs, closeout failures, and journal anomalies.",
|
|
487
|
-
" audit Controlled-command audit is not readable yet in this CLI."
|
|
488
|
-
].join(`
|
|
489
|
-
`));
|
|
490
|
-
}
|
|
491
|
-
function asRecord(value) {
|
|
492
|
-
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
493
|
-
}
|
|
494
|
-
function firstString2(record, keys) {
|
|
495
|
-
for (const key of keys) {
|
|
496
|
-
const value = record[key];
|
|
497
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
498
|
-
return value;
|
|
499
|
-
}
|
|
500
|
-
}
|
|
501
|
-
return null;
|
|
502
|
-
}
|
|
503
|
-
function stringifyLogPayload(value) {
|
|
504
|
-
if (typeof value === "string")
|
|
505
|
-
return value;
|
|
506
|
-
if (typeof value === "number" || typeof value === "boolean")
|
|
507
|
-
return String(value);
|
|
508
|
-
const record = asRecord(value);
|
|
509
|
-
if (!record)
|
|
510
|
-
return null;
|
|
511
|
-
const direct = firstString2(record, ["line", "message", "text", "content", "output", "summary", "detail"]);
|
|
512
|
-
if (direct)
|
|
513
|
-
return direct;
|
|
514
|
-
try {
|
|
515
|
-
return JSON.stringify(record);
|
|
516
|
-
} catch {
|
|
517
|
-
return String(record);
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
function logLineFromValue(value) {
|
|
521
|
-
const record = asRecord(value);
|
|
522
|
-
if (!record)
|
|
523
|
-
return stringifyLogPayload(value);
|
|
524
|
-
const direct = firstString2(record, ["line", "message", "text", "content", "output", "summary", "detail"]);
|
|
525
|
-
if (direct)
|
|
526
|
-
return direct;
|
|
527
|
-
if ("payload" in record)
|
|
528
|
-
return stringifyLogPayload(record.payload);
|
|
529
|
-
if ("data" in record)
|
|
530
|
-
return stringifyLogPayload(record.data);
|
|
531
|
-
return stringifyLogPayload(record);
|
|
532
|
-
}
|
|
533
|
-
function logLineFromSessionEntry(entry) {
|
|
534
|
-
if (entry.type !== "custom" || entry.customType !== RIG_RUN_LOG_ENTRY)
|
|
535
|
-
return null;
|
|
536
|
-
return logLineFromValue(entry.data);
|
|
537
|
-
}
|
|
538
|
-
function logLinesFromProjection(projection) {
|
|
539
|
-
const projected = projection;
|
|
540
|
-
const lines = [];
|
|
541
|
-
for (const key of ["logs", "logEntries", "journalLogs", "runLogs"]) {
|
|
542
|
-
const entries = projected[key];
|
|
543
|
-
if (!Array.isArray(entries))
|
|
544
|
-
continue;
|
|
545
|
-
for (const entry of entries) {
|
|
546
|
-
const line = logLineFromValue(entry);
|
|
547
|
-
if (line !== null)
|
|
548
|
-
lines.push(line);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
return lines;
|
|
552
|
-
}
|
|
553
|
-
function toRunLike(run) {
|
|
554
|
-
return {
|
|
555
|
-
runId: run.runId,
|
|
556
|
-
taskId: run.taskId,
|
|
557
|
-
title: run.title,
|
|
558
|
-
status: run.status,
|
|
559
|
-
source: run.source,
|
|
560
|
-
live: run.live,
|
|
561
|
-
stale: run.stale,
|
|
562
|
-
startedAt: run.startedAt,
|
|
563
|
-
updatedAt: run.updatedAt,
|
|
564
|
-
completedAt: run.completedAt,
|
|
565
|
-
joinLink: run.joinLink,
|
|
566
|
-
prUrl: run.prUrl,
|
|
567
|
-
pendingApprovals: run.pendingApprovals,
|
|
568
|
-
pendingInputs: run.pendingInputs,
|
|
569
|
-
steeringCount: run.steeringCount,
|
|
570
|
-
stallCount: run.stallCount
|
|
571
|
-
};
|
|
572
|
-
}
|
|
573
|
-
function requireRunId(value, usage) {
|
|
574
|
-
if (!value || !value.trim()) {
|
|
575
|
-
throw new CliError(`${usage} requires a run id.`, 2, { hint: "Run `rig inspect runs` to find run ids." });
|
|
576
|
-
}
|
|
577
|
-
return value.trim();
|
|
578
|
-
}
|
|
579
|
-
async function executeLogs(context, args, deps) {
|
|
580
|
-
const taskResult = takeOption(args, "--task");
|
|
581
|
-
requireNoExtraArgs(taskResult.rest, "rig inspect logs --task <id>");
|
|
582
|
-
const taskId = requireTask(taskResult.value, "rig inspect logs --task <id>");
|
|
583
|
-
const projection = await (deps.getRunProjection ?? getRunProjection)(context.projectRoot, taskId);
|
|
584
|
-
if (!projection) {
|
|
585
|
-
throw new CliError(`No projected runs found for task ${taskId}.`, 1, {
|
|
586
|
-
hint: "Run `rig run list` to confirm the run journal is discoverable."
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
const projectedLines = logLinesFromProjection(projection.projection);
|
|
590
|
-
const sessionLines = projectedLines.length > 0 ? [] : (deps.readSessionRunEntries ?? readSessionRunEntries)(projection.sessionPath).map(logLineFromSessionEntry).filter((line) => line !== null);
|
|
591
|
-
const lines = projectedLines.length > 0 ? projectedLines : sessionLines;
|
|
592
|
-
if (context.outputMode === "json") {
|
|
593
|
-
console.log(JSON.stringify({ taskId, runId: projection.runId, lines }, null, 2));
|
|
594
|
-
} else if (lines.length === 0) {
|
|
595
|
-
console.log(`No log entries found for task ${taskId}.`);
|
|
596
|
-
} else {
|
|
597
|
-
for (const line of lines)
|
|
598
|
-
console.log(line);
|
|
599
|
-
}
|
|
600
|
-
return { ok: true, group: "inspect", command: "logs", details: { taskId, runId: projection.runId, count: lines.length } };
|
|
601
|
-
}
|
|
602
|
-
async function executeArtifact(context, args, deps) {
|
|
603
|
-
const taskResult = takeOption(args, "--task");
|
|
604
|
-
const fileResult = takeOption(taskResult.rest, "--file");
|
|
605
|
-
requireNoExtraArgs(fileResult.rest, "rig inspect artifact --task <id> --file <name>");
|
|
606
|
-
const taskId = requireTask(taskResult.value, "rig inspect artifact --task <id> --file <name>");
|
|
607
|
-
const filename = fileResult.value?.trim();
|
|
608
|
-
if (!filename) {
|
|
609
|
-
throw new CliError("rig inspect artifact --task <id> --file <name> requires an artifact file name.", 2);
|
|
610
|
-
}
|
|
611
|
-
const preview = await (deps.taskArtifactRead ?? taskArtifactRead)(context.projectRoot, filename, {
|
|
612
|
-
taskId,
|
|
613
|
-
maxBytes: 64 * 1024
|
|
614
|
-
});
|
|
615
|
-
if (context.outputMode === "json") {
|
|
616
|
-
console.log(JSON.stringify({ taskId, file: filename, ...preview }, null, 2));
|
|
617
|
-
} else {
|
|
618
|
-
console.log(preview.contents);
|
|
619
|
-
if (preview.truncated) {
|
|
620
|
-
console.log(`
|
|
621
|
-
[truncated at ${preview.maxBytes} bytes; artifact is ${preview.sizeBytes} bytes]`);
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
return {
|
|
625
|
-
ok: true,
|
|
626
|
-
group: "inspect",
|
|
627
|
-
command: "artifact",
|
|
628
|
-
details: { taskId, file: filename, ...preview }
|
|
629
|
-
};
|
|
630
|
-
}
|
|
631
|
-
async function executeRunLogs(context, args, deps) {
|
|
632
|
-
const runResult = takeOption(args, "--run");
|
|
633
|
-
requireNoExtraArgs(runResult.rest, "rig inspect run-logs --run <id>");
|
|
634
|
-
const runId = requireRunId(runResult.value, "rig inspect run-logs --run <id>");
|
|
635
|
-
const projection = await (deps.getRunProjection ?? getRunProjection)(context.projectRoot, runId);
|
|
636
|
-
if (!projection) {
|
|
637
|
-
throw new CliError(`Run not found: ${runId}`, 2, { hint: "Run `rig inspect runs` to see runs." });
|
|
638
|
-
}
|
|
639
|
-
const sessionLines = (deps.readSessionRunEntries ?? readSessionRunEntries)(projection.sessionPath).map(logLineFromSessionEntry).filter((line) => line !== null);
|
|
640
|
-
const lines = sessionLines.length > 0 ? sessionLines : logLinesFromProjection(projection.projection);
|
|
641
|
-
if (context.outputMode === "json") {
|
|
642
|
-
console.log(JSON.stringify({ runId: projection.runId, taskId: projection.taskId, lines }, null, 2));
|
|
643
|
-
} else if (lines.length === 0) {
|
|
644
|
-
console.log(`No log entries found for run ${projection.runId}.`);
|
|
645
|
-
} else {
|
|
646
|
-
for (const line of lines)
|
|
647
|
-
console.log(line);
|
|
648
|
-
}
|
|
649
|
-
return { ok: true, group: "inspect", command: "run-logs", details: { runId: projection.runId, taskId: projection.taskId, count: lines.length } };
|
|
650
|
-
}
|
|
651
|
-
async function executeRuns(context, args, deps) {
|
|
652
|
-
requireNoExtraArgs(args, "rig inspect runs");
|
|
653
|
-
const runs = await (deps.listRunProjections ?? listRunProjections)(context.projectRoot);
|
|
654
|
-
const formatted = runs.map(toRunLike);
|
|
655
|
-
if (context.outputMode === "text") {
|
|
656
|
-
printFormattedOutput(formatRunList(formatted));
|
|
657
|
-
}
|
|
658
|
-
return { ok: true, group: "inspect", command: "runs", details: { runs: formatted } };
|
|
659
|
-
}
|
|
660
|
-
async function executeArtifacts(context, args, deps) {
|
|
661
|
-
const taskResult = takeOption(args, "--task");
|
|
662
|
-
requireNoExtraArgs(taskResult.rest, "rig inspect artifacts --task <id>");
|
|
663
|
-
const taskId = requireTask(taskResult.value, "rig inspect artifacts --task <id>");
|
|
664
|
-
await (deps.taskArtifacts ?? taskArtifacts)(context.projectRoot, taskId);
|
|
665
|
-
return { ok: true, group: "inspect", command: "artifacts", details: { taskId } };
|
|
666
|
-
}
|
|
667
|
-
async function executeDiff(context, args, deps) {
|
|
668
|
-
const taskResult = takeOption(args, "--task");
|
|
669
|
-
requireNoExtraArgs(taskResult.rest, "rig inspect diff --task <id>");
|
|
670
|
-
const taskId = requireTask(taskResult.value, "rig inspect diff --task <id>");
|
|
671
|
-
const files = (deps.changedFilesForTask ?? changedFilesForTask)(context.projectRoot, taskId, true);
|
|
672
|
-
if (context.outputMode === "json") {
|
|
673
|
-
console.log(JSON.stringify({ taskId, files }, null, 2));
|
|
674
|
-
} else {
|
|
675
|
-
for (const file of files)
|
|
676
|
-
console.log(file);
|
|
677
|
-
}
|
|
678
|
-
return { ok: true, group: "inspect", command: "diff", details: { taskId, files } };
|
|
679
|
-
}
|
|
680
|
-
async function executeGraph(context, args, deps) {
|
|
681
|
-
const taskResult = takeOption(args, "--task");
|
|
682
|
-
requireNoExtraArgs(taskResult.rest, "rig inspect graph [--task <id>]");
|
|
683
|
-
await (deps.taskDeps ?? taskDeps)(context.projectRoot, taskResult.value);
|
|
684
|
-
return { ok: true, group: "inspect", command: "graph", details: { taskId: taskResult.value ?? null } };
|
|
685
|
-
}
|
|
686
|
-
function summarizeProjectionFailures(run) {
|
|
687
|
-
const failures = [];
|
|
688
|
-
const projection = run.projection;
|
|
689
|
-
if (run.status === "failed" || projection.status === "failed") {
|
|
690
|
-
failures.push(`${run.runId}: run status failed`);
|
|
691
|
-
}
|
|
692
|
-
for (const phase of projection.closeoutPhases) {
|
|
693
|
-
if (phase.outcome === "failed") {
|
|
694
|
-
failures.push(`${run.runId}: closeout ${phase.phase} failed${phase.detail ? ` \u2014 ${phase.detail}` : ""}`);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
for (const anomaly of projection.anomalies) {
|
|
698
|
-
failures.push(`${run.runId}: anomaly ${anomaly.kind}${anomaly.detail ? ` \u2014 ${anomaly.detail}` : ""}`);
|
|
699
|
-
}
|
|
700
|
-
return failures;
|
|
701
|
-
}
|
|
702
|
-
async function runsForTask(context, taskId, deps) {
|
|
703
|
-
const listRuns = deps.listRunProjections ?? listRunProjections;
|
|
704
|
-
try {
|
|
705
|
-
const runs = await listRuns(context.projectRoot);
|
|
706
|
-
const filtered = runs.filter((run2) => run2.taskId === taskId || run2.runId === taskId);
|
|
707
|
-
if (filtered.length > 0)
|
|
708
|
-
return filtered;
|
|
709
|
-
} catch {}
|
|
710
|
-
const run = await (deps.getRunProjection ?? getRunProjection)(context.projectRoot, taskId);
|
|
711
|
-
return run ? [run] : [];
|
|
712
|
-
}
|
|
713
|
-
async function executeFailures(context, args, deps) {
|
|
714
|
-
const taskResult = takeOption(args, "--task");
|
|
715
|
-
requireNoExtraArgs(taskResult.rest, "rig inspect failures --task <id>");
|
|
716
|
-
const taskId = requireTask(taskResult.value, "rig inspect failures --task <id>");
|
|
717
|
-
const runs = await runsForTask(context, taskId, deps);
|
|
718
|
-
const failures = runs.flatMap(summarizeProjectionFailures);
|
|
719
|
-
if (context.outputMode === "json") {
|
|
720
|
-
console.log(JSON.stringify({ taskId, failures }, null, 2));
|
|
721
|
-
} else if (failures.length === 0) {
|
|
722
|
-
console.log(`No failures recorded for task ${taskId}.`);
|
|
723
|
-
} else {
|
|
724
|
-
for (const failure of failures)
|
|
725
|
-
console.log(failure);
|
|
726
|
-
}
|
|
727
|
-
return { ok: true, group: "inspect", command: "failures", details: { taskId, count: failures.length } };
|
|
728
|
-
}
|
|
729
|
-
function executeAudit(args) {
|
|
730
|
-
requireNoExtraArgs(args, "rig inspect audit");
|
|
731
|
-
throw new CliError("rig inspect audit cannot read the controlled-command audit trail yet: current code only writes audit JSONL and exposes no supported reader API.", 2, { hint: "Use the OMP session history for operator audit context until a controlled-bash audit reader is added." });
|
|
732
|
-
}
|
|
733
|
-
async function executeInspect(context, args, deps = {}) {
|
|
734
|
-
const [command = "failures", ...rest] = args;
|
|
735
|
-
if (command === "--help" || command === "-h" || command === "help") {
|
|
736
|
-
printInspectHelp();
|
|
737
|
-
return { ok: true, group: "inspect", command: "help" };
|
|
738
|
-
}
|
|
739
|
-
switch (command) {
|
|
740
|
-
case "logs":
|
|
741
|
-
return executeLogs(context, rest, deps);
|
|
742
|
-
case "artifact":
|
|
743
|
-
return executeArtifact(context, rest, deps);
|
|
744
|
-
case "artifacts":
|
|
745
|
-
return executeArtifacts(context, rest, deps);
|
|
746
|
-
case "run-logs":
|
|
747
|
-
return executeRunLogs(context, rest, deps);
|
|
748
|
-
case "runs":
|
|
749
|
-
return executeRuns(context, rest, deps);
|
|
750
|
-
case "diff":
|
|
751
|
-
return executeDiff(context, rest, deps);
|
|
752
|
-
case "graph":
|
|
753
|
-
return executeGraph(context, rest, deps);
|
|
754
|
-
case "failures":
|
|
755
|
-
return executeFailures(context, rest, deps);
|
|
756
|
-
case "audit":
|
|
757
|
-
return executeAudit(rest);
|
|
758
|
-
default:
|
|
759
|
-
throw new CliError(`Unknown inspect command: ${command}`, 1, { hint: "Run `rig inspect --help` to list inspect commands." });
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
export {
|
|
763
|
-
executeInspect
|
|
764
|
-
};
|