@h-rig/cli 0.0.6-alpha.67 → 0.0.6-alpha.69
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/bin/rig.js +266 -75
- package/dist/src/commands/_async-ui.js +152 -0
- package/dist/src/commands/_doctor-checks.js +29 -0
- package/dist/src/commands/_operator-view.js +154 -4
- package/dist/src/commands/_pi-frontend.js +24 -1
- package/dist/src/commands/_preflight.js +18 -0
- package/dist/src/commands/_server-client.js +46 -0
- package/dist/src/commands/_snapshot-upload.js +18 -0
- package/dist/src/commands/_spinner.js +4 -2
- package/dist/src/commands/agent.js +11 -0
- package/dist/src/commands/doctor.js +156 -1
- package/dist/src/commands/github.js +148 -3
- package/dist/src/commands/inbox.js +150 -6
- package/dist/src/commands/init.js +29 -0
- package/dist/src/commands/inspect.js +158 -8
- package/dist/src/commands/queue.js +11 -0
- package/dist/src/commands/run.js +207 -35
- package/dist/src/commands/server.js +18 -0
- package/dist/src/commands/setup.js +161 -6
- package/dist/src/commands/stats.js +167 -22
- package/dist/src/commands/task-run-driver.js +18 -0
- package/dist/src/commands/task.js +197 -47
- package/dist/src/commands.js +266 -75
- package/dist/src/index.js +266 -75
- package/package.json +8 -8
|
@@ -213,6 +213,15 @@ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
|
213
213
|
import { resolve as resolve2 } from "path";
|
|
214
214
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
215
215
|
var scopedGitHubBearerTokens = new Map;
|
|
216
|
+
var serverPhaseListener = null;
|
|
217
|
+
function setServerPhaseListener(listener) {
|
|
218
|
+
const previous = serverPhaseListener;
|
|
219
|
+
serverPhaseListener = listener;
|
|
220
|
+
return previous;
|
|
221
|
+
}
|
|
222
|
+
function reportServerPhase(label) {
|
|
223
|
+
serverPhaseListener?.(label);
|
|
224
|
+
}
|
|
216
225
|
function cleanToken(value) {
|
|
217
226
|
const trimmed = value?.trim();
|
|
218
227
|
return trimmed ? trimmed : null;
|
|
@@ -255,6 +264,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
255
264
|
try {
|
|
256
265
|
const selected = resolveSelectedConnection(projectRoot);
|
|
257
266
|
if (selected?.connection.kind === "remote") {
|
|
267
|
+
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
258
268
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
259
269
|
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
260
270
|
return {
|
|
@@ -264,6 +274,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
264
274
|
serverProjectRoot
|
|
265
275
|
};
|
|
266
276
|
}
|
|
277
|
+
reportServerPhase("Starting local Rig server\u2026");
|
|
267
278
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
268
279
|
return {
|
|
269
280
|
baseUrl: connection.baseUrl,
|
|
@@ -380,6 +391,7 @@ async function requestServerJson(context, pathname, init = {}) {
|
|
|
380
391
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
381
392
|
if (server.serverProjectRoot)
|
|
382
393
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
394
|
+
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
383
395
|
let response;
|
|
384
396
|
try {
|
|
385
397
|
response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
@@ -459,6 +471,17 @@ async function getRunTimelineViaServer(context, runId, options = {}) {
|
|
|
459
471
|
const payload = await requestServerJson(context, `${url.pathname}${url.search}`);
|
|
460
472
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : { entries: [] };
|
|
461
473
|
}
|
|
474
|
+
var RESUMABLE_RUN_STATUSES = new Set([
|
|
475
|
+
"created",
|
|
476
|
+
"preparing",
|
|
477
|
+
"running",
|
|
478
|
+
"validating",
|
|
479
|
+
"reviewing",
|
|
480
|
+
"stopped",
|
|
481
|
+
"failed",
|
|
482
|
+
"needs-attention",
|
|
483
|
+
"needs_attention"
|
|
484
|
+
]);
|
|
462
485
|
async function stopRunViaServer(context, runId) {
|
|
463
486
|
const payload = await requestServerJson(context, "/api/runs/stop", {
|
|
464
487
|
method: "POST",
|
|
@@ -1025,6 +1048,127 @@ async function selectTaskWithTextPicker(tasks, io = {}) {
|
|
|
1025
1048
|
return Number.isFinite(index) ? tasks[index] ?? null : null;
|
|
1026
1049
|
}
|
|
1027
1050
|
|
|
1051
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
1052
|
+
import pc from "picocolors";
|
|
1053
|
+
|
|
1054
|
+
// packages/cli/src/commands/_spinner.ts
|
|
1055
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1056
|
+
function createTtySpinner(input) {
|
|
1057
|
+
const output = input.output ?? process.stdout;
|
|
1058
|
+
const isTty = output.isTTY === true;
|
|
1059
|
+
const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
|
|
1060
|
+
let label = input.label;
|
|
1061
|
+
let frame = 0;
|
|
1062
|
+
let paused = false;
|
|
1063
|
+
let stopped = false;
|
|
1064
|
+
let lastPrintedLabel = "";
|
|
1065
|
+
const render = () => {
|
|
1066
|
+
if (stopped || paused)
|
|
1067
|
+
return;
|
|
1068
|
+
if (!isTty) {
|
|
1069
|
+
if (label !== lastPrintedLabel) {
|
|
1070
|
+
output.write(`${label}
|
|
1071
|
+
`);
|
|
1072
|
+
lastPrintedLabel = label;
|
|
1073
|
+
}
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
frame = (frame + 1) % frames.length;
|
|
1077
|
+
const glyph = frames[frame] ?? frames[0] ?? "";
|
|
1078
|
+
output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
|
|
1079
|
+
};
|
|
1080
|
+
const clearLine = () => {
|
|
1081
|
+
if (isTty)
|
|
1082
|
+
output.write("\r\x1B[2K");
|
|
1083
|
+
};
|
|
1084
|
+
render();
|
|
1085
|
+
const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
|
|
1086
|
+
return {
|
|
1087
|
+
setLabel(next) {
|
|
1088
|
+
label = next;
|
|
1089
|
+
render();
|
|
1090
|
+
},
|
|
1091
|
+
pause() {
|
|
1092
|
+
paused = true;
|
|
1093
|
+
clearLine();
|
|
1094
|
+
},
|
|
1095
|
+
resume() {
|
|
1096
|
+
if (stopped)
|
|
1097
|
+
return;
|
|
1098
|
+
paused = false;
|
|
1099
|
+
render();
|
|
1100
|
+
},
|
|
1101
|
+
stop(finalLine) {
|
|
1102
|
+
if (stopped)
|
|
1103
|
+
return;
|
|
1104
|
+
stopped = true;
|
|
1105
|
+
if (timer)
|
|
1106
|
+
clearInterval(timer);
|
|
1107
|
+
clearLine();
|
|
1108
|
+
if (finalLine)
|
|
1109
|
+
output.write(`${finalLine}
|
|
1110
|
+
`);
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
1116
|
+
var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
|
|
1117
|
+
var DONE_SYMBOL = pc.green("\u25C7");
|
|
1118
|
+
var FAIL_SYMBOL = pc.red("\u25A0");
|
|
1119
|
+
var activeUpdate = null;
|
|
1120
|
+
async function withSpinner(label, work, options = {}) {
|
|
1121
|
+
if (options.outputMode === "json") {
|
|
1122
|
+
return work(() => {});
|
|
1123
|
+
}
|
|
1124
|
+
if (activeUpdate) {
|
|
1125
|
+
const outer = activeUpdate;
|
|
1126
|
+
outer(label);
|
|
1127
|
+
return work(outer);
|
|
1128
|
+
}
|
|
1129
|
+
const output = options.output ?? process.stderr;
|
|
1130
|
+
const isTty = output.isTTY === true;
|
|
1131
|
+
let lastLabel = label;
|
|
1132
|
+
if (!isTty) {
|
|
1133
|
+
output.write(`${label}
|
|
1134
|
+
`);
|
|
1135
|
+
const update2 = (next) => {
|
|
1136
|
+
lastLabel = next;
|
|
1137
|
+
};
|
|
1138
|
+
activeUpdate = update2;
|
|
1139
|
+
const previousListener2 = setServerPhaseListener(update2);
|
|
1140
|
+
try {
|
|
1141
|
+
return await work(update2);
|
|
1142
|
+
} finally {
|
|
1143
|
+
activeUpdate = null;
|
|
1144
|
+
setServerPhaseListener(previousListener2);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
const spinner = createTtySpinner({
|
|
1148
|
+
label,
|
|
1149
|
+
output,
|
|
1150
|
+
frames: CLACK_SPINNER_FRAMES,
|
|
1151
|
+
styleFrame: (frame) => pc.magenta(frame)
|
|
1152
|
+
});
|
|
1153
|
+
const update = (next) => {
|
|
1154
|
+
lastLabel = next;
|
|
1155
|
+
spinner.setLabel(next);
|
|
1156
|
+
};
|
|
1157
|
+
activeUpdate = update;
|
|
1158
|
+
const previousListener = setServerPhaseListener(update);
|
|
1159
|
+
try {
|
|
1160
|
+
const result = await work(update);
|
|
1161
|
+
spinner.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
|
|
1162
|
+
return result;
|
|
1163
|
+
} catch (error) {
|
|
1164
|
+
spinner.stop(`${FAIL_SYMBOL} ${lastLabel}`);
|
|
1165
|
+
throw error;
|
|
1166
|
+
} finally {
|
|
1167
|
+
activeUpdate = null;
|
|
1168
|
+
setServerPhaseListener(previousListener);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1028
1172
|
// packages/cli/src/commands/_pi-frontend.ts
|
|
1029
1173
|
import { mkdtempSync, rmSync } from "fs";
|
|
1030
1174
|
import { tmpdir } from "os";
|
|
@@ -1072,7 +1216,12 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
1072
1216
|
};
|
|
1073
1217
|
let detached = false;
|
|
1074
1218
|
try {
|
|
1075
|
-
await runPiMain([
|
|
1219
|
+
await runPiMain([
|
|
1220
|
+
"--no-extensions",
|
|
1221
|
+
"--no-skills",
|
|
1222
|
+
"--no-prompt-templates",
|
|
1223
|
+
"--no-context-files"
|
|
1224
|
+
], {
|
|
1076
1225
|
extensionFactories: [piRigExtensionFactory]
|
|
1077
1226
|
});
|
|
1078
1227
|
detached = true;
|
|
@@ -1137,8 +1286,9 @@ async function readOperatorSnapshot(context, runId, options = {}) {
|
|
|
1137
1286
|
}
|
|
1138
1287
|
async function attachRunOperatorView(context, input) {
|
|
1139
1288
|
let steered = false;
|
|
1140
|
-
|
|
1141
|
-
|
|
1289
|
+
const attachMessage = input.message?.trim();
|
|
1290
|
+
if (attachMessage) {
|
|
1291
|
+
await withSpinner("Queueing steering message\u2026", () => sendRunPiPromptViaServer(context, input.runId, attachMessage, "steer").catch(() => steerRunViaServer(context, input.runId, attachMessage)), { outputMode: context.outputMode });
|
|
1142
1292
|
steered = true;
|
|
1143
1293
|
}
|
|
1144
1294
|
if (input.follow && !input.once && input.interactive !== false && context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
@@ -1148,7 +1298,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
1148
1298
|
});
|
|
1149
1299
|
}
|
|
1150
1300
|
const surface = createOperatorSurface({ interactive: input.interactive !== false });
|
|
1151
|
-
let snapshot = await readOperatorSnapshot(context, input.runId);
|
|
1301
|
+
let snapshot = await withSpinner(`Connecting to run ${input.runId}\u2026`, () => readOperatorSnapshot(context, input.runId), { outputMode: context.outputMode });
|
|
1152
1302
|
if (context.outputMode === "text") {
|
|
1153
1303
|
surface.renderSnapshot(snapshot);
|
|
1154
1304
|
surface.renderTimeline(snapshot.timeline);
|
|
@@ -1188,7 +1338,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
1188
1338
|
|
|
1189
1339
|
// packages/cli/src/commands/_cli-format.ts
|
|
1190
1340
|
import { log, note } from "@clack/prompts";
|
|
1191
|
-
import
|
|
1341
|
+
import pc2 from "picocolors";
|
|
1192
1342
|
function stringField(record, key, fallback = "") {
|
|
1193
1343
|
const value = record[key];
|
|
1194
1344
|
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
@@ -1218,14 +1368,14 @@ function pad(value, width) {
|
|
|
1218
1368
|
function statusColor(status) {
|
|
1219
1369
|
const normalized = status.toLowerCase();
|
|
1220
1370
|
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
|
|
1221
|
-
return
|
|
1371
|
+
return pc2.green;
|
|
1222
1372
|
if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
|
|
1223
|
-
return
|
|
1373
|
+
return pc2.red;
|
|
1224
1374
|
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
1225
|
-
return
|
|
1375
|
+
return pc2.cyan;
|
|
1226
1376
|
if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
|
|
1227
|
-
return
|
|
1228
|
-
return
|
|
1377
|
+
return pc2.yellow;
|
|
1378
|
+
return pc2.dim;
|
|
1229
1379
|
}
|
|
1230
1380
|
function compactValue(value) {
|
|
1231
1381
|
if (value === null || value === undefined)
|
|
@@ -1256,17 +1406,17 @@ function formatStatusPill(status) {
|
|
|
1256
1406
|
return statusColor(label)(`\u25CF ${label}`);
|
|
1257
1407
|
}
|
|
1258
1408
|
function formatSection(title, subtitle) {
|
|
1259
|
-
return `${
|
|
1409
|
+
return `${pc2.bold(pc2.cyan("\u25C6"))} ${pc2.bold(title)}${subtitle ? pc2.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
1260
1410
|
}
|
|
1261
1411
|
function formatSuccessCard(title, rows = []) {
|
|
1262
|
-
const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${
|
|
1412
|
+
const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${pc2.dim("\u2502")} ${pc2.dim(key.padEnd(12))} ${value}`);
|
|
1263
1413
|
return [formatSection(title), ...body].join(`
|
|
1264
1414
|
`);
|
|
1265
1415
|
}
|
|
1266
1416
|
function formatNextSteps(steps) {
|
|
1267
1417
|
if (steps.length === 0)
|
|
1268
1418
|
return [];
|
|
1269
|
-
return [
|
|
1419
|
+
return [pc2.bold("Next"), ...steps.map((step) => `${pc2.dim("\u203A")} ${step}`)];
|
|
1270
1420
|
}
|
|
1271
1421
|
function formatTaskList(tasks, options = {}) {
|
|
1272
1422
|
if (options.raw)
|
|
@@ -1286,12 +1436,12 @@ function formatTaskList(tasks, options = {}) {
|
|
|
1286
1436
|
});
|
|
1287
1437
|
const idWidth = Math.min(18, Math.max(4, ...rows.map((row) => row.id.length)));
|
|
1288
1438
|
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
1289
|
-
const header = `${
|
|
1439
|
+
const header = `${pc2.bold(pad("TASK", idWidth))} ${pc2.bold(pad("STATUS", statusWidth))} ${pc2.bold("TITLE")}`;
|
|
1290
1440
|
const body = rows.map((row) => {
|
|
1291
|
-
const labels = row.labels.length > 0 ?
|
|
1292
|
-
const source = row.source ?
|
|
1441
|
+
const labels = row.labels.length > 0 ? pc2.dim(` ${row.labels.slice(0, 4).map((label) => `#${label}`).join(" ")}`) : "";
|
|
1442
|
+
const source = row.source ? pc2.dim(` ${row.source}`) : "";
|
|
1293
1443
|
return [
|
|
1294
|
-
|
|
1444
|
+
pc2.bold(pad(truncate(row.id, idWidth), idWidth)),
|
|
1295
1445
|
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
1296
1446
|
`${row.title}${labels}${source}`
|
|
1297
1447
|
].join(" ");
|
|
@@ -1312,7 +1462,7 @@ function formatTaskCard(task, options = {}) {
|
|
|
1312
1462
|
const readiness = compactValue(task.readiness ?? raw.readiness);
|
|
1313
1463
|
const validators = compactValue(task.validators ?? raw.validators ?? task.validation ?? raw.validation);
|
|
1314
1464
|
const rows = [
|
|
1315
|
-
["task",
|
|
1465
|
+
["task", pc2.bold(id)],
|
|
1316
1466
|
["status", formatStatusPill(status)],
|
|
1317
1467
|
["title", title],
|
|
1318
1468
|
["source", source],
|
|
@@ -1334,12 +1484,12 @@ function formatTaskDetails(task) {
|
|
|
1334
1484
|
return formatTaskCard(task, { title: "Task details" });
|
|
1335
1485
|
}
|
|
1336
1486
|
function formatSubmittedRun(input) {
|
|
1337
|
-
const rows = [["run",
|
|
1487
|
+
const rows = [["run", pc2.bold(input.runId)]];
|
|
1338
1488
|
if (input.task) {
|
|
1339
1489
|
const id = stringField(input.task, "id", "<unknown>");
|
|
1340
1490
|
const status = stringField(input.task, "status", "unknown");
|
|
1341
1491
|
const title = stringField(input.task, "title", "Untitled task");
|
|
1342
|
-
rows.push(["task", `${
|
|
1492
|
+
rows.push(["task", `${pc2.bold(id)} ${formatStatusPill(status)} ${title}`]);
|
|
1343
1493
|
}
|
|
1344
1494
|
const runtime = [input.runtimeAdapter || "pi", input.runtimeMode || "full-access", input.interactionMode || "default"].filter(Boolean).join(" \xB7 ");
|
|
1345
1495
|
rows.push(["runtime", runtime]);
|
|
@@ -1395,7 +1545,7 @@ async function printPendingInboxFooter(context) {
|
|
|
1395
1545
|
|
|
1396
1546
|
// packages/cli/src/commands/_help-catalog.ts
|
|
1397
1547
|
import { intro, log as log2, note as note2, outro } from "@clack/prompts";
|
|
1398
|
-
import
|
|
1548
|
+
import pc3 from "picocolors";
|
|
1399
1549
|
var TOP_LEVEL_SECTIONS = [
|
|
1400
1550
|
{
|
|
1401
1551
|
title: "Start here",
|
|
@@ -1677,13 +1827,13 @@ var ADVANCED_GROUPS = [
|
|
|
1677
1827
|
];
|
|
1678
1828
|
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
1679
1829
|
function heading(title) {
|
|
1680
|
-
return
|
|
1830
|
+
return pc3.bold(pc3.cyan(title));
|
|
1681
1831
|
}
|
|
1682
1832
|
function renderRigBanner(version) {
|
|
1683
|
-
const m = (s) =>
|
|
1684
|
-
const c = (s) =>
|
|
1685
|
-
const y = (s) =>
|
|
1686
|
-
const d = (s) =>
|
|
1833
|
+
const m = (s) => pc3.bold(pc3.magenta(s));
|
|
1834
|
+
const c = (s) => pc3.bold(pc3.cyan(s));
|
|
1835
|
+
const y = (s) => pc3.yellow(s);
|
|
1836
|
+
const d = (s) => pc3.dim(s);
|
|
1687
1837
|
const lines = [
|
|
1688
1838
|
m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
|
|
1689
1839
|
m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
|
|
@@ -1692,7 +1842,7 @@ function renderRigBanner(version) {
|
|
|
1692
1842
|
y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
|
|
1693
1843
|
y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
|
|
1694
1844
|
"",
|
|
1695
|
-
` ${c("\u25E2\u25E4")} ${
|
|
1845
|
+
` ${c("\u25E2\u25E4")} ${pc3.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
|
|
1696
1846
|
version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
|
|
1697
1847
|
];
|
|
1698
1848
|
return lines.join(`
|
|
@@ -1700,7 +1850,7 @@ function renderRigBanner(version) {
|
|
|
1700
1850
|
}
|
|
1701
1851
|
function commandLine(command, description) {
|
|
1702
1852
|
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
1703
|
-
return `${
|
|
1853
|
+
return `${pc3.dim("\u2502")} ${pc3.bold(commandColumn)} ${description}`;
|
|
1704
1854
|
}
|
|
1705
1855
|
function renderCommandBlock(commands) {
|
|
1706
1856
|
return commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
@@ -1710,37 +1860,37 @@ function renderGroup(group) {
|
|
|
1710
1860
|
const lines = [
|
|
1711
1861
|
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
1712
1862
|
"",
|
|
1713
|
-
|
|
1863
|
+
pc3.bold("Usage"),
|
|
1714
1864
|
...group.usage.map((line) => ` ${line}`),
|
|
1715
1865
|
"",
|
|
1716
|
-
|
|
1866
|
+
pc3.bold("Commands"),
|
|
1717
1867
|
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
1718
1868
|
];
|
|
1719
1869
|
if (group.examples?.length) {
|
|
1720
|
-
lines.push("",
|
|
1870
|
+
lines.push("", pc3.bold("Examples"), ...group.examples.map((line) => ` ${pc3.dim("$")} ${line}`));
|
|
1721
1871
|
}
|
|
1722
1872
|
if (group.next?.length) {
|
|
1723
|
-
lines.push("",
|
|
1873
|
+
lines.push("", pc3.bold("Next steps"), ...group.next.map((line) => ` ${pc3.dim("\u203A")} ${line}`));
|
|
1724
1874
|
}
|
|
1725
1875
|
if (group.advanced?.length) {
|
|
1726
|
-
lines.push("",
|
|
1876
|
+
lines.push("", pc3.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc3.dim("\u203A")} ${line}`));
|
|
1727
1877
|
}
|
|
1728
1878
|
return lines.join(`
|
|
1729
1879
|
`);
|
|
1730
1880
|
}
|
|
1731
1881
|
function renderTopLevelHelp() {
|
|
1732
1882
|
return [
|
|
1733
|
-
`${heading("rig")} ${
|
|
1734
|
-
|
|
1883
|
+
`${heading("rig")} ${pc3.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
1884
|
+
pc3.dim("Current path: select a server, choose a task, submit a run, attach with native Pi, clear inbox gates."),
|
|
1735
1885
|
"",
|
|
1736
1886
|
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
1737
|
-
`${
|
|
1887
|
+
`${pc3.bold(pc3.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc3.dim(section.subtitle)}`,
|
|
1738
1888
|
renderCommandBlock(section.commands),
|
|
1739
1889
|
""
|
|
1740
1890
|
]),
|
|
1741
|
-
|
|
1891
|
+
pc3.dim("More: `rig help --advanced` for dev/compatibility commands; `rig <group> --help` for rich per-group help; `rig --version` for the installed version."),
|
|
1742
1892
|
"",
|
|
1743
|
-
|
|
1893
|
+
pc3.bold("Global options"),
|
|
1744
1894
|
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
1745
1895
|
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
1746
1896
|
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
@@ -1979,7 +2129,7 @@ async function executeTask(context, args, options) {
|
|
|
1979
2129
|
pending = rawResult.rest;
|
|
1980
2130
|
const { filters, rest: remaining } = parseTaskFilters(pending);
|
|
1981
2131
|
requireNoExtraArgs(remaining, "rig task list [--raw] [--assignee <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
1982
|
-
const tasks = await listWorkspaceTasksViaServer(context, filters);
|
|
2132
|
+
const tasks = await withSpinner("Reading tasks from server\u2026", () => listWorkspaceTasksViaServer(context, filters), { outputMode: context.outputMode });
|
|
1983
2133
|
if (context.outputMode === "text") {
|
|
1984
2134
|
const renderedTasks = rawResult.value ? tasks.map((task) => summarizeTask(task, { raw: true })) : tasks.map((task) => summarizeTask(task));
|
|
1985
2135
|
printFormattedOutput(formatTaskList(renderedTasks, { raw: rawResult.value }));
|
|
@@ -2003,7 +2153,7 @@ async function executeTask(context, args, options) {
|
|
|
2003
2153
|
const taskId3 = normalizeTaskRunTaskId(taskOption.value ?? positional);
|
|
2004
2154
|
if (!taskId3)
|
|
2005
2155
|
throw new CliError("task show requires a task id.", 2, { hint: "Run `rig task list` to find ids, then `rig task show <id>`." });
|
|
2006
|
-
const task = await getWorkspaceTaskViaServer(context, taskId3);
|
|
2156
|
+
const task = await withSpinner(`Reading task ${taskId3} from server\u2026`, () => getWorkspaceTaskViaServer(context, taskId3), { outputMode: context.outputMode });
|
|
2007
2157
|
if (!task)
|
|
2008
2158
|
throw new CliError(`Task not found: ${taskId3}`, 3, { hint: "Run `rig task list` to see available tasks." });
|
|
2009
2159
|
const summary = summarizeTask(task, { raw: true });
|
|
@@ -2015,7 +2165,7 @@ async function executeTask(context, args, options) {
|
|
|
2015
2165
|
case "next": {
|
|
2016
2166
|
const { filters, rest: remaining } = parseTaskFilters(rest);
|
|
2017
2167
|
requireNoExtraArgs(remaining, "rig task next [--assignee <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
2018
|
-
const selected = await selectNextWorkspaceTaskViaServer(context, filters);
|
|
2168
|
+
const selected = await withSpinner("Selecting next ready task\u2026", () => selectNextWorkspaceTaskViaServer(context, filters), { outputMode: context.outputMode });
|
|
2019
2169
|
if (context.outputMode === "text") {
|
|
2020
2170
|
if (selected.task) {
|
|
2021
2171
|
printFormattedOutput(formatTaskCard(summarizeTask(selected.task, { raw: true }), { title: "Selected task", selected: true }));
|
|
@@ -2165,7 +2315,7 @@ async function executeTask(context, args, options) {
|
|
|
2165
2315
|
let selectedTask = null;
|
|
2166
2316
|
let selectedTaskId = normalizeTaskRunTaskId(taskResult.value) ?? positionalTaskId;
|
|
2167
2317
|
if (nextResult.value) {
|
|
2168
|
-
const selected = await selectNextWorkspaceTaskViaServer(context, filterResult.filters);
|
|
2318
|
+
const selected = await withSpinner("Selecting next ready task\u2026", () => selectNextWorkspaceTaskViaServer(context, filterResult.filters), { outputMode: context.outputMode });
|
|
2169
2319
|
selectedTask = selected.task;
|
|
2170
2320
|
selectedTaskId = selected.task ? readTaskId(selected.task) : null;
|
|
2171
2321
|
if (!selectedTaskId) {
|
|
@@ -2176,7 +2326,7 @@ async function executeTask(context, args, options) {
|
|
|
2176
2326
|
if (context.outputMode !== "text" || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
2177
2327
|
throw new CliError("task run requires an interactive terminal to pick a task; pass --next, --task <id>, or --initial-prompt/--title for an ad hoc run.", 2);
|
|
2178
2328
|
}
|
|
2179
|
-
const tasks = await listWorkspaceTasksViaServer(context, filterResult.filters);
|
|
2329
|
+
const tasks = await withSpinner("Reading tasks from server\u2026", () => listWorkspaceTasksViaServer(context, filterResult.filters), { outputMode: context.outputMode });
|
|
2180
2330
|
selectedTask = await selectTaskWithTextPicker(tasks);
|
|
2181
2331
|
selectedTaskId = selectedTask ? readTaskId(selectedTask) : null;
|
|
2182
2332
|
if (!selectedTaskId) {
|
|
@@ -2186,13 +2336,13 @@ async function executeTask(context, args, options) {
|
|
|
2186
2336
|
await runProjectMainSyncPreflight(context, { disabled: skipProjectSyncResult.value });
|
|
2187
2337
|
const projectDefaults = await loadTaskRunProjectDefaults(context.projectRoot);
|
|
2188
2338
|
const runtimeAdapter = normalizeRuntimeAdapter(runtimeAdapterResult.value ?? projectDefaults.runtimeAdapter);
|
|
2189
|
-
await runFastTaskRunPreflight(context, {
|
|
2339
|
+
await withSpinner("Running task-run preflight\u2026", () => runFastTaskRunPreflight(context, {
|
|
2190
2340
|
taskId: selectedTaskId,
|
|
2191
2341
|
runtimeAdapter
|
|
2192
|
-
});
|
|
2342
|
+
}), { outputMode: context.outputMode });
|
|
2193
2343
|
const dirtyBaseline = await resolveDirtyBaselineForTaskRun(context, dirtyBaselineResult.value);
|
|
2194
2344
|
const prMode = noPrResult.value ? "off" : normalizePrMode(prResult.value) ?? projectDefaults.prMode;
|
|
2195
|
-
const submitted = await submitTaskRunViaServer(context, {
|
|
2345
|
+
const submitted = await withSpinner("Dispatching run\u2026", () => submitTaskRunViaServer(context, {
|
|
2196
2346
|
runId: context.runId,
|
|
2197
2347
|
taskId: selectedTaskId ?? undefined,
|
|
2198
2348
|
title: titleResult.value ?? undefined,
|
|
@@ -2203,7 +2353,7 @@ async function executeTask(context, args, options) {
|
|
|
2203
2353
|
initialPrompt: initialPromptResult.value ?? undefined,
|
|
2204
2354
|
baselineMode: dirtyBaseline.mode,
|
|
2205
2355
|
prMode
|
|
2206
|
-
});
|
|
2356
|
+
}), { outputMode: context.outputMode });
|
|
2207
2357
|
let attachDetails = null;
|
|
2208
2358
|
if (!detachResult.value && context.outputMode === "text") {
|
|
2209
2359
|
printFormattedOutput(formatSubmittedRun({
|