@h-rig/cli 0.0.6-alpha.67 → 0.0.6-alpha.68
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 +232 -71
- package/dist/src/commands/_async-ui.js +141 -0
- package/dist/src/commands/_doctor-checks.js +18 -0
- package/dist/src/commands/_operator-view.js +143 -4
- package/dist/src/commands/_pi-frontend.js +13 -1
- package/dist/src/commands/_preflight.js +7 -0
- package/dist/src/commands/_server-client.js +13 -0
- package/dist/src/commands/_snapshot-upload.js +7 -0
- package/dist/src/commands/_spinner.js +4 -2
- package/dist/src/commands/doctor.js +145 -1
- package/dist/src/commands/github.js +137 -3
- package/dist/src/commands/inbox.js +139 -6
- package/dist/src/commands/init.js +18 -0
- package/dist/src/commands/inspect.js +147 -8
- package/dist/src/commands/run.js +173 -31
- package/dist/src/commands/server.js +7 -0
- package/dist/src/commands/setup.js +150 -6
- package/dist/src/commands/stats.js +156 -22
- package/dist/src/commands/task-run-driver.js +7 -0
- package/dist/src/commands/task.js +186 -47
- package/dist/src/commands.js +232 -71
- package/dist/src/index.js +232 -71
- package/package.json +8 -8
package/dist/src/commands.js
CHANGED
|
@@ -2740,6 +2740,15 @@ import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
|
2740
2740
|
import { resolve as resolve10 } from "path";
|
|
2741
2741
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
2742
2742
|
var scopedGitHubBearerTokens = new Map;
|
|
2743
|
+
var serverPhaseListener = null;
|
|
2744
|
+
function setServerPhaseListener(listener) {
|
|
2745
|
+
const previous = serverPhaseListener;
|
|
2746
|
+
serverPhaseListener = listener;
|
|
2747
|
+
return previous;
|
|
2748
|
+
}
|
|
2749
|
+
function reportServerPhase(label) {
|
|
2750
|
+
serverPhaseListener?.(label);
|
|
2751
|
+
}
|
|
2743
2752
|
function cleanToken(value) {
|
|
2744
2753
|
const trimmed = value?.trim();
|
|
2745
2754
|
return trimmed ? trimmed : null;
|
|
@@ -2786,6 +2795,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
2786
2795
|
try {
|
|
2787
2796
|
const selected = resolveSelectedConnection(projectRoot);
|
|
2788
2797
|
if (selected?.connection.kind === "remote") {
|
|
2798
|
+
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
2789
2799
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
2790
2800
|
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
2791
2801
|
return {
|
|
@@ -2795,6 +2805,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
2795
2805
|
serverProjectRoot
|
|
2796
2806
|
};
|
|
2797
2807
|
}
|
|
2808
|
+
reportServerPhase("Starting local Rig server\u2026");
|
|
2798
2809
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
2799
2810
|
return {
|
|
2800
2811
|
baseUrl: connection.baseUrl,
|
|
@@ -2911,6 +2922,7 @@ async function requestServerJson(context, pathname, init = {}) {
|
|
|
2911
2922
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
2912
2923
|
if (server.serverProjectRoot)
|
|
2913
2924
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
2925
|
+
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
2914
2926
|
let response;
|
|
2915
2927
|
try {
|
|
2916
2928
|
response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
@@ -4431,6 +4443,127 @@ function formatConnectionStatus(selected, connections) {
|
|
|
4431
4443
|
`);
|
|
4432
4444
|
}
|
|
4433
4445
|
|
|
4446
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
4447
|
+
import pc4 from "picocolors";
|
|
4448
|
+
|
|
4449
|
+
// packages/cli/src/commands/_spinner.ts
|
|
4450
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
4451
|
+
function createTtySpinner(input) {
|
|
4452
|
+
const output = input.output ?? process.stdout;
|
|
4453
|
+
const isTty = output.isTTY === true;
|
|
4454
|
+
const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
|
|
4455
|
+
let label = input.label;
|
|
4456
|
+
let frame = 0;
|
|
4457
|
+
let paused = false;
|
|
4458
|
+
let stopped = false;
|
|
4459
|
+
let lastPrintedLabel = "";
|
|
4460
|
+
const render = () => {
|
|
4461
|
+
if (stopped || paused)
|
|
4462
|
+
return;
|
|
4463
|
+
if (!isTty) {
|
|
4464
|
+
if (label !== lastPrintedLabel) {
|
|
4465
|
+
output.write(`${label}
|
|
4466
|
+
`);
|
|
4467
|
+
lastPrintedLabel = label;
|
|
4468
|
+
}
|
|
4469
|
+
return;
|
|
4470
|
+
}
|
|
4471
|
+
frame = (frame + 1) % frames.length;
|
|
4472
|
+
const glyph = frames[frame] ?? frames[0] ?? "";
|
|
4473
|
+
output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
|
|
4474
|
+
};
|
|
4475
|
+
const clearLine = () => {
|
|
4476
|
+
if (isTty)
|
|
4477
|
+
output.write("\r\x1B[2K");
|
|
4478
|
+
};
|
|
4479
|
+
render();
|
|
4480
|
+
const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
|
|
4481
|
+
return {
|
|
4482
|
+
setLabel(next) {
|
|
4483
|
+
label = next;
|
|
4484
|
+
render();
|
|
4485
|
+
},
|
|
4486
|
+
pause() {
|
|
4487
|
+
paused = true;
|
|
4488
|
+
clearLine();
|
|
4489
|
+
},
|
|
4490
|
+
resume() {
|
|
4491
|
+
if (stopped)
|
|
4492
|
+
return;
|
|
4493
|
+
paused = false;
|
|
4494
|
+
render();
|
|
4495
|
+
},
|
|
4496
|
+
stop(finalLine) {
|
|
4497
|
+
if (stopped)
|
|
4498
|
+
return;
|
|
4499
|
+
stopped = true;
|
|
4500
|
+
if (timer)
|
|
4501
|
+
clearInterval(timer);
|
|
4502
|
+
clearLine();
|
|
4503
|
+
if (finalLine)
|
|
4504
|
+
output.write(`${finalLine}
|
|
4505
|
+
`);
|
|
4506
|
+
}
|
|
4507
|
+
};
|
|
4508
|
+
}
|
|
4509
|
+
|
|
4510
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
4511
|
+
var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
|
|
4512
|
+
var DONE_SYMBOL = pc4.green("\u25C7");
|
|
4513
|
+
var FAIL_SYMBOL = pc4.red("\u25A0");
|
|
4514
|
+
var activeUpdate = null;
|
|
4515
|
+
async function withSpinner(label, work, options = {}) {
|
|
4516
|
+
if (options.outputMode === "json") {
|
|
4517
|
+
return work(() => {});
|
|
4518
|
+
}
|
|
4519
|
+
if (activeUpdate) {
|
|
4520
|
+
const outer = activeUpdate;
|
|
4521
|
+
outer(label);
|
|
4522
|
+
return work(outer);
|
|
4523
|
+
}
|
|
4524
|
+
const output = options.output ?? process.stderr;
|
|
4525
|
+
const isTty = output.isTTY === true;
|
|
4526
|
+
let lastLabel = label;
|
|
4527
|
+
if (!isTty) {
|
|
4528
|
+
output.write(`${label}
|
|
4529
|
+
`);
|
|
4530
|
+
const update2 = (next) => {
|
|
4531
|
+
lastLabel = next;
|
|
4532
|
+
};
|
|
4533
|
+
activeUpdate = update2;
|
|
4534
|
+
const previousListener2 = setServerPhaseListener(update2);
|
|
4535
|
+
try {
|
|
4536
|
+
return await work(update2);
|
|
4537
|
+
} finally {
|
|
4538
|
+
activeUpdate = null;
|
|
4539
|
+
setServerPhaseListener(previousListener2);
|
|
4540
|
+
}
|
|
4541
|
+
}
|
|
4542
|
+
const spinner2 = createTtySpinner({
|
|
4543
|
+
label,
|
|
4544
|
+
output,
|
|
4545
|
+
frames: CLACK_SPINNER_FRAMES,
|
|
4546
|
+
styleFrame: (frame) => pc4.magenta(frame)
|
|
4547
|
+
});
|
|
4548
|
+
const update = (next) => {
|
|
4549
|
+
lastLabel = next;
|
|
4550
|
+
spinner2.setLabel(next);
|
|
4551
|
+
};
|
|
4552
|
+
activeUpdate = update;
|
|
4553
|
+
const previousListener = setServerPhaseListener(update);
|
|
4554
|
+
try {
|
|
4555
|
+
const result = await work(update);
|
|
4556
|
+
spinner2.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
|
|
4557
|
+
return result;
|
|
4558
|
+
} catch (error) {
|
|
4559
|
+
spinner2.stop(`${FAIL_SYMBOL} ${lastLabel}`);
|
|
4560
|
+
throw error;
|
|
4561
|
+
} finally {
|
|
4562
|
+
activeUpdate = null;
|
|
4563
|
+
setServerPhaseListener(previousListener);
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
|
|
4434
4567
|
// packages/cli/src/commands/inbox.ts
|
|
4435
4568
|
async function listInboxRecords(context, kind, filters) {
|
|
4436
4569
|
const params = new URLSearchParams;
|
|
@@ -4535,7 +4668,7 @@ async function executeInbox(context, args) {
|
|
|
4535
4668
|
const task = takeOption(pending, "--task");
|
|
4536
4669
|
pending = task.rest;
|
|
4537
4670
|
requireNoExtraArgs(pending, "rig inbox approvals [--run <id>] [--task <id>]");
|
|
4538
|
-
const approvals = await listInboxRecords(context, "approvals", { run: run.value, task: task.value });
|
|
4671
|
+
const approvals = await withSpinner("Reading approvals from server\u2026", () => listInboxRecords(context, "approvals", { run: run.value, task: task.value }), { outputMode: context.outputMode });
|
|
4539
4672
|
renderList(context, "approvals", approvals);
|
|
4540
4673
|
return { ok: true, group: "inbox", command, details: { approvals } };
|
|
4541
4674
|
}
|
|
@@ -4546,7 +4679,7 @@ async function executeInbox(context, args) {
|
|
|
4546
4679
|
const task = takeOption(pending, "--task");
|
|
4547
4680
|
pending = task.rest;
|
|
4548
4681
|
requireNoExtraArgs(pending, "rig inbox inputs [--run <id>] [--task <id>]");
|
|
4549
|
-
const requests = await listInboxRecords(context, "inputs", { run: run.value, task: task.value });
|
|
4682
|
+
const requests = await withSpinner("Reading input requests from server\u2026", () => listInboxRecords(context, "inputs", { run: run.value, task: task.value }), { outputMode: context.outputMode });
|
|
4550
4683
|
renderList(context, "inputs", requests);
|
|
4551
4684
|
return { ok: true, group: "inbox", command, details: { requests } };
|
|
4552
4685
|
}
|
|
@@ -4567,7 +4700,7 @@ async function executeInbox(context, args) {
|
|
|
4567
4700
|
if (decision.value !== "approve" && decision.value !== "reject") {
|
|
4568
4701
|
throw new CliError("decision must be approve or reject.", 1, { hint: "Re-run as `rig inbox approve --run <id> --request <id> --decision approve|reject`." });
|
|
4569
4702
|
}
|
|
4570
|
-
const result = await requestServerJson(context, "/api/inbox/approvals/resolve", {
|
|
4703
|
+
const result = await withSpinner(`Resolving approval ${request.value}\u2026`, () => requestServerJson(context, "/api/inbox/approvals/resolve", {
|
|
4571
4704
|
method: "POST",
|
|
4572
4705
|
headers: { "content-type": "application/json" },
|
|
4573
4706
|
body: JSON.stringify({
|
|
@@ -4576,7 +4709,7 @@ async function executeInbox(context, args) {
|
|
|
4576
4709
|
decision: decision.value,
|
|
4577
4710
|
note: note4.value ?? null
|
|
4578
4711
|
})
|
|
4579
|
-
});
|
|
4712
|
+
}), { outputMode: context.outputMode });
|
|
4580
4713
|
return { ok: true, group: "inbox", command, details: { result } };
|
|
4581
4714
|
}
|
|
4582
4715
|
case "respond": {
|
|
@@ -4610,7 +4743,7 @@ async function executeInbox(context, args) {
|
|
|
4610
4743
|
const [key, ...restValue] = entry.split("=");
|
|
4611
4744
|
return [key, restValue.join("=")];
|
|
4612
4745
|
}));
|
|
4613
|
-
const result = await requestServerJson(context, "/api/inbox/inputs/respond", {
|
|
4746
|
+
const result = await withSpinner(`Sending response for ${request.value}\u2026`, () => requestServerJson(context, "/api/inbox/inputs/respond", {
|
|
4614
4747
|
method: "POST",
|
|
4615
4748
|
headers: { "content-type": "application/json" },
|
|
4616
4749
|
body: JSON.stringify({
|
|
@@ -4618,7 +4751,7 @@ async function executeInbox(context, args) {
|
|
|
4618
4751
|
requestId: request.value,
|
|
4619
4752
|
answers: parsedAnswers
|
|
4620
4753
|
})
|
|
4621
|
-
});
|
|
4754
|
+
}), { outputMode: context.outputMode });
|
|
4622
4755
|
return { ok: true, group: "inbox", command, details: { result } };
|
|
4623
4756
|
}
|
|
4624
4757
|
case "watch": {
|
|
@@ -5035,7 +5168,10 @@ async function runRigDoctorChecks(options) {
|
|
|
5035
5168
|
const bunVersion = options.bunVersion ?? Bun.version;
|
|
5036
5169
|
const request = options.requestJson ?? ((pathname, init) => requestServerJson({ projectRoot }, pathname, init));
|
|
5037
5170
|
const loadConfig = options.loadConfig ?? loadRigConfigOrNull;
|
|
5171
|
+
const progress = options.onProgress ?? (() => {});
|
|
5172
|
+
progress("Checking local toolchain\u2026");
|
|
5038
5173
|
checks.push(check("bun", `bun >= ${MIN_SUPPORTED_BUN_VERSION}`, isSupportedBunVersion(bunVersion) ? "pass" : "fail", `found ${bunVersion}`, `Install Bun ${MIN_SUPPORTED_BUN_VERSION} or newer.`), check("git", "git", which("git") ? "pass" : "fail", which("git") ?? undefined, "Install git and ensure it is on PATH."), check("jq", "jq", which("jq") ? "pass" : "warn", which("jq") ?? undefined, "Install jq (for example `brew install jq`)."));
|
|
5174
|
+
progress("Loading rig.config\u2026");
|
|
5039
5175
|
const loadedConfig = await loadConfig(projectRoot).catch(() => null);
|
|
5040
5176
|
const config = loadedConfig ?? loadFallbackConfig(projectRoot);
|
|
5041
5177
|
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync10(resolve16(projectRoot, name)));
|
|
@@ -5054,6 +5190,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5054
5190
|
checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server", repo ? "fail" : "warn", repo ? "selected alias is missing" : "will auto-start local server", repo ? "Run `rig server list` and `rig server use <alias|local>`." : undefined));
|
|
5055
5191
|
let server = null;
|
|
5056
5192
|
try {
|
|
5193
|
+
progress("Connecting to the selected Rig server\u2026");
|
|
5057
5194
|
server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
|
|
5058
5195
|
checks.push(check("server", "Rig server reachable", "pass", `${server.connectionKind} ${server.baseUrl}`));
|
|
5059
5196
|
} catch (error) {
|
|
@@ -5061,18 +5198,21 @@ async function runRigDoctorChecks(options) {
|
|
|
5061
5198
|
}
|
|
5062
5199
|
if (server || options.requestJson) {
|
|
5063
5200
|
try {
|
|
5201
|
+
progress("Checking server status\u2026");
|
|
5064
5202
|
const status = await request("/api/server/status");
|
|
5065
5203
|
checks.push(check("server-status", "server project status", "pass", JSON.stringify(status).slice(0, 180)));
|
|
5066
5204
|
} catch (error) {
|
|
5067
5205
|
checks.push(check("server-status", "server project status", "fail", errorMessage(error), "Run `rig doctor` after the selected server is reachable."));
|
|
5068
5206
|
}
|
|
5069
5207
|
try {
|
|
5208
|
+
progress("Checking GitHub auth\u2026");
|
|
5070
5209
|
const auth = await request("/api/github/auth/status");
|
|
5071
5210
|
checks.push(isAuthenticated2(auth) ? check("github-auth", "GitHub auth", "pass") : check("github-auth", "GitHub auth", "fail", "not authenticated", "Run `rig github auth import-gh` or `rig github auth token --token <token>`."));
|
|
5072
5211
|
} catch (error) {
|
|
5073
5212
|
checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig and ensure the server exposes auth status."));
|
|
5074
5213
|
}
|
|
5075
5214
|
try {
|
|
5215
|
+
progress("Checking GitHub repo permissions\u2026");
|
|
5076
5216
|
const permissions = await request("/api/github/repo/permissions");
|
|
5077
5217
|
const allowed = permissionAllowsPr2(permissions);
|
|
5078
5218
|
checks.push(allowed === true ? check("github-repo-permissions", "GitHub repo PR permissions", "pass", JSON.stringify(permissions).slice(0, 180)) : allowed === false ? check("github-repo-permissions", "GitHub repo PR permissions", "fail", JSON.stringify(permissions).slice(0, 180), "Grant the selected GitHub token permission to push branches, open PRs, and merge according to repo rules.") : check("github-repo-permissions", "GitHub repo PR permissions", "warn", JSON.stringify(permissions).slice(0, 180), "Confirm the selected token can push branches and open PRs."));
|
|
@@ -5080,6 +5220,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5080
5220
|
checks.push(check("github-repo-permissions", "GitHub repo PR permissions", "warn", errorMessage(error), "Ensure the server exposes repo permission checks and the token can open PRs."));
|
|
5081
5221
|
}
|
|
5082
5222
|
try {
|
|
5223
|
+
progress("Checking GitHub issue labels\u2026");
|
|
5083
5224
|
const labels = await request("/api/workspace/task-labels");
|
|
5084
5225
|
const ready = labelsReady(labels);
|
|
5085
5226
|
checks.push(ready === false ? check("task-labels", "GitHub issue labels", "fail", JSON.stringify(labels).slice(0, 180), "Let Rig create required labels or create the configured lifecycle labels manually.") : check("task-labels", "GitHub issue labels", ready === true ? "pass" : "warn", JSON.stringify(labels).slice(0, 180), "Confirm required Rig lifecycle labels exist."));
|
|
@@ -5087,6 +5228,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5087
5228
|
checks.push(check("task-labels", "GitHub issue labels", "warn", errorMessage(error), "Run `rig init`/`rig doctor` after label setup is wired on the server."));
|
|
5088
5229
|
}
|
|
5089
5230
|
try {
|
|
5231
|
+
progress("Checking task projection\u2026");
|
|
5090
5232
|
const projection = await request("/api/workspace/task-projection");
|
|
5091
5233
|
checks.push(check("task-projection", "task projection", "pass", JSON.stringify(projection).slice(0, 180)));
|
|
5092
5234
|
} catch (error) {
|
|
@@ -5095,6 +5237,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5095
5237
|
const slug = projectStatusSlug(projectRoot, config);
|
|
5096
5238
|
if (slug) {
|
|
5097
5239
|
try {
|
|
5240
|
+
progress("Checking server project checkout\u2026");
|
|
5098
5241
|
const project = await request(`/api/projects/${encodeURIComponent(slug)}`);
|
|
5099
5242
|
checks.push(check("remote-checkout", "server project checkout", "pass", JSON.stringify(project).slice(0, 180)));
|
|
5100
5243
|
} catch (error) {
|
|
@@ -5109,6 +5252,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5109
5252
|
}
|
|
5110
5253
|
checks.push(githubProjectsCheck(config));
|
|
5111
5254
|
checks.push(prMergeCheck(config));
|
|
5255
|
+
progress("Checking Pi installation\u2026");
|
|
5112
5256
|
const piChecks = await (options.piChecks ?? (() => buildPiSetupChecks()))().catch((error) => [{
|
|
5113
5257
|
ok: false,
|
|
5114
5258
|
label: "pi/pi-rig checks",
|
|
@@ -6031,7 +6175,7 @@ async function executeGithub(context, args) {
|
|
|
6031
6175
|
case "status": {
|
|
6032
6176
|
if (rest.length > 0)
|
|
6033
6177
|
throw new CliError("Usage: rig github auth status", 1);
|
|
6034
|
-
const status = await getGitHubAuthStatusViaServer(context);
|
|
6178
|
+
const status = await withSpinner("Checking GitHub auth on the server\u2026", () => getGitHubAuthStatusViaServer(context), { outputMode: context.outputMode });
|
|
6035
6179
|
printPayload(context, status, `GitHub auth: ${status.authenticated ? "authenticated" : "unauthenticated"}`);
|
|
6036
6180
|
return { ok: true, group: "github", command: "auth status", details: status };
|
|
6037
6181
|
}
|
|
@@ -6042,14 +6186,15 @@ async function executeGithub(context, args) {
|
|
|
6042
6186
|
const token = parsed.value?.trim();
|
|
6043
6187
|
if (!token)
|
|
6044
6188
|
throw new CliError("Missing --token value.", 1, { hint: "Re-run as `rig github auth token --token <token>`." });
|
|
6045
|
-
const result = await postGitHubTokenViaServer(context, token);
|
|
6189
|
+
const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token), { outputMode: context.outputMode });
|
|
6046
6190
|
printPayload(context, result, "GitHub token stored on the selected Rig server.");
|
|
6047
6191
|
return { ok: true, group: "github", command: "auth token", details: result };
|
|
6048
6192
|
}
|
|
6049
6193
|
case "import-gh": {
|
|
6050
6194
|
if (rest.length > 0)
|
|
6051
6195
|
throw new CliError("Usage: rig github auth import-gh", 1);
|
|
6052
|
-
const
|
|
6196
|
+
const importedToken = readGhToken();
|
|
6197
|
+
const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken), { outputMode: context.outputMode });
|
|
6053
6198
|
printPayload(context, result, "GitHub token imported from gh and stored on the selected Rig server.");
|
|
6054
6199
|
return { ok: true, group: "github", command: "auth import-gh", details: result };
|
|
6055
6200
|
}
|
|
@@ -6062,7 +6207,7 @@ async function executeGithub(context, args) {
|
|
|
6062
6207
|
init_runner();
|
|
6063
6208
|
async function executeDoctor(context, args) {
|
|
6064
6209
|
requireNoExtraArgs(args, "rig doctor");
|
|
6065
|
-
const checks = await runRigDoctorChecks({ projectRoot: context.projectRoot });
|
|
6210
|
+
const checks = await withSpinner("Running doctor checks\u2026", (update) => runRigDoctorChecks({ projectRoot: context.projectRoot, onProgress: update }), { outputMode: context.outputMode });
|
|
6066
6211
|
if (context.outputMode === "text") {
|
|
6067
6212
|
console.log(formatDoctorChecks(checks));
|
|
6068
6213
|
}
|
|
@@ -6369,13 +6514,19 @@ async function executeInspect(context, args) {
|
|
|
6369
6514
|
const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
|
|
6370
6515
|
const latestRun = listAuthorityRuns(context.projectRoot).map((entry) => readAuthorityRun3(context.projectRoot, entry.runId)).filter((run) => Boolean(run)).filter((run) => run.taskId === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
|
|
6371
6516
|
if (!latestRun) {
|
|
6372
|
-
const
|
|
6373
|
-
|
|
6374
|
-
|
|
6517
|
+
const fallback = await withSpinner(`Finding runs for ${requiredTask} on the server\u2026`, async (update) => {
|
|
6518
|
+
const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
|
|
6519
|
+
const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
|
|
6520
|
+
if (!serverRun || typeof serverRun.runId !== "string")
|
|
6521
|
+
return null;
|
|
6522
|
+
update(`Reading logs for run ${serverRun.runId}\u2026`);
|
|
6523
|
+
const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
|
|
6524
|
+
return { runId: serverRun.runId, page };
|
|
6525
|
+
}, { outputMode: context.outputMode });
|
|
6526
|
+
if (!fallback) {
|
|
6375
6527
|
throw new CliError(`No runs found for ${requiredTask} (local or on the selected server).`, 1, { hint: "Start one with `rig task run --task <id>`, or check `rig run list`." });
|
|
6376
6528
|
}
|
|
6377
|
-
const
|
|
6378
|
-
const entries = Array.isArray(page.entries) ? page.entries : [];
|
|
6529
|
+
const entries = Array.isArray(fallback.page.entries) ? fallback.page.entries : [];
|
|
6379
6530
|
if (context.outputMode === "text") {
|
|
6380
6531
|
for (const entry of entries) {
|
|
6381
6532
|
const record = entry && typeof entry === "object" ? entry : {};
|
|
@@ -6384,9 +6535,9 @@ async function executeInspect(context, args) {
|
|
|
6384
6535
|
console.log([title, detail].filter(Boolean).join(" \u2014 "));
|
|
6385
6536
|
}
|
|
6386
6537
|
if (entries.length === 0)
|
|
6387
|
-
console.log(`(no log entries for run ${
|
|
6538
|
+
console.log(`(no log entries for run ${fallback.runId})`);
|
|
6388
6539
|
}
|
|
6389
|
-
return { ok: true, group: "inspect", command, details: { task: requiredTask, runId:
|
|
6540
|
+
return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: fallback.runId, source: "server", entries } };
|
|
6390
6541
|
}
|
|
6391
6542
|
const logsPath = resolve19(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
|
|
6392
6543
|
if (!existsSync12(logsPath)) {
|
|
@@ -6444,7 +6595,7 @@ async function executeInspect(context, args) {
|
|
|
6444
6595
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
6445
6596
|
requireNoExtraArgs(remaining, "rig inspect diff [--task <task-id>]");
|
|
6446
6597
|
if (task) {
|
|
6447
|
-
const files = changedFilesForTask(context.projectRoot, task, false);
|
|
6598
|
+
const files = await withSpinner(`Computing changed files for ${task}\u2026`, async () => changedFilesForTask(context.projectRoot, task, false), { outputMode: context.outputMode });
|
|
6448
6599
|
for (const file of files) {
|
|
6449
6600
|
console.log(file);
|
|
6450
6601
|
}
|
|
@@ -7532,7 +7683,12 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
7532
7683
|
};
|
|
7533
7684
|
let detached = false;
|
|
7534
7685
|
try {
|
|
7535
|
-
await runPiMain([
|
|
7686
|
+
await runPiMain([
|
|
7687
|
+
"--no-extensions",
|
|
7688
|
+
"--no-skills",
|
|
7689
|
+
"--no-prompt-templates",
|
|
7690
|
+
"--no-context-files"
|
|
7691
|
+
], {
|
|
7536
7692
|
extensionFactories: [piRigExtensionFactory]
|
|
7537
7693
|
});
|
|
7538
7694
|
detached = true;
|
|
@@ -7597,8 +7753,9 @@ async function readOperatorSnapshot(context, runId, options = {}) {
|
|
|
7597
7753
|
}
|
|
7598
7754
|
async function attachRunOperatorView(context, input) {
|
|
7599
7755
|
let steered = false;
|
|
7600
|
-
|
|
7601
|
-
|
|
7756
|
+
const attachMessage = input.message?.trim();
|
|
7757
|
+
if (attachMessage) {
|
|
7758
|
+
await withSpinner("Queueing steering message\u2026", () => sendRunPiPromptViaServer(context, input.runId, attachMessage, "steer").catch(() => steerRunViaServer(context, input.runId, attachMessage)), { outputMode: context.outputMode });
|
|
7602
7759
|
steered = true;
|
|
7603
7760
|
}
|
|
7604
7761
|
if (input.follow && !input.once && input.interactive !== false && context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
@@ -7608,7 +7765,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
7608
7765
|
});
|
|
7609
7766
|
}
|
|
7610
7767
|
const surface = createOperatorSurface({ interactive: input.interactive !== false });
|
|
7611
|
-
let snapshot = await readOperatorSnapshot(context, input.runId);
|
|
7768
|
+
let snapshot = await withSpinner(`Connecting to run ${input.runId}\u2026`, () => readOperatorSnapshot(context, input.runId), { outputMode: context.outputMode });
|
|
7612
7769
|
if (context.outputMode === "text") {
|
|
7613
7770
|
surface.renderSnapshot(snapshot);
|
|
7614
7771
|
surface.renderTimeline(snapshot.timeline);
|
|
@@ -7739,7 +7896,7 @@ async function executeRun(context, args) {
|
|
|
7739
7896
|
switch (command) {
|
|
7740
7897
|
case "list": {
|
|
7741
7898
|
requireNoExtraArgs(rest, "rig run list");
|
|
7742
|
-
const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
|
|
7899
|
+
const { runs, source } = isRemoteConnectionSelected(context.projectRoot) ? await withSpinner("Reading runs from server\u2026", () => listRunsForSelectedConnection(context, { limit: 100 }), { outputMode: context.outputMode }) : await listRunsForSelectedConnection(context, { limit: 100 });
|
|
7743
7900
|
if (context.outputMode === "text") {
|
|
7744
7901
|
printFormattedOutput(formatRunList(runs, { source }));
|
|
7745
7902
|
await printPendingInboxFooter(context);
|
|
@@ -7812,7 +7969,7 @@ async function executeRun(context, args) {
|
|
|
7812
7969
|
if (!runId) {
|
|
7813
7970
|
throw new CliError("run show requires a run id.", 1, { hint: "Run `rig run list` to find run ids, then `rig run show <run-id>`." });
|
|
7814
7971
|
}
|
|
7815
|
-
const record = readAuthorityRun5(context.projectRoot, runId) ?? normalizeRemoteRunDetails(await getRunDetailsViaServer(context, runId).catch(() => ({})));
|
|
7972
|
+
const record = readAuthorityRun5(context.projectRoot, runId) ?? normalizeRemoteRunDetails(await withSpinner(`Reading run ${runId} from server\u2026`, () => getRunDetailsViaServer(context, runId).catch(() => ({})), { outputMode: context.outputMode }));
|
|
7816
7973
|
if (!record) {
|
|
7817
7974
|
throw new CliError(`Run not found: ${runId}`, 2, { hint: "Run `rig run list` to see recorded runs." });
|
|
7818
7975
|
}
|
|
@@ -7833,7 +7990,8 @@ async function executeRun(context, args) {
|
|
|
7833
7990
|
}
|
|
7834
7991
|
const renderer = createPiRunStreamRenderer();
|
|
7835
7992
|
let cursor = null;
|
|
7836
|
-
const
|
|
7993
|
+
const timelineRunId = run.value;
|
|
7994
|
+
const page = await withSpinner(`Reading timeline for ${timelineRunId}\u2026`, () => getRunTimelineViaServer(context, timelineRunId, { limit: 500 }), { outputMode: context.outputMode });
|
|
7837
7995
|
const events = Array.isArray(page.entries) ? page.entries.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))) : [];
|
|
7838
7996
|
cursor = typeof page.nextCursor === "string" ? page.nextCursor : null;
|
|
7839
7997
|
if (context.outputMode === "text") {
|
|
@@ -7910,8 +8068,9 @@ async function executeRun(context, args) {
|
|
|
7910
8068
|
throw new CliError("run attach requires a run id.", 2, { hint: "Run `rig run list` to find run ids, then `rig run attach <run-id> --follow`." });
|
|
7911
8069
|
}
|
|
7912
8070
|
let steered = false;
|
|
7913
|
-
|
|
7914
|
-
|
|
8071
|
+
const steerMessage = messageOption.value?.trim();
|
|
8072
|
+
if (steerMessage) {
|
|
8073
|
+
await withSpinner("Queueing steering message\u2026", () => steerRunViaServer(context, runId, steerMessage), { outputMode: context.outputMode });
|
|
7915
8074
|
steered = true;
|
|
7916
8075
|
}
|
|
7917
8076
|
const attached = await attachRunOperatorView(context, {
|
|
@@ -7931,7 +8090,7 @@ async function executeRun(context, args) {
|
|
|
7931
8090
|
}
|
|
7932
8091
|
return { ok: true, group: "run", command };
|
|
7933
8092
|
}
|
|
7934
|
-
const summary = isRemoteConnectionSelected(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
|
|
8093
|
+
const summary = isRemoteConnectionSelected(context.projectRoot) ? buildServerRunStatus(await withSpinner("Reading run status from server\u2026", () => listRunsViaServer(context, { limit: 100 }), { outputMode: context.outputMode })) : runStatus(context.projectRoot, runtimeContext);
|
|
7935
8094
|
const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
7936
8095
|
const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
7937
8096
|
if (context.outputMode === "text") {
|
|
@@ -8066,7 +8225,8 @@ async function executeRun(context, args) {
|
|
|
8066
8225
|
}
|
|
8067
8226
|
return { ok: true, group: "run", command, details: { runId, dryRun: true } };
|
|
8068
8227
|
}
|
|
8069
|
-
|
|
8228
|
+
const trimmedMessage = message2.trim();
|
|
8229
|
+
await withSpinner("Queueing steering message\u2026", () => steerRunViaServer(context, runId, trimmedMessage), { outputMode: context.outputMode });
|
|
8070
8230
|
if (context.outputMode === "text") {
|
|
8071
8231
|
console.log(`Steering message queued for ${runId}.`);
|
|
8072
8232
|
}
|
|
@@ -8087,7 +8247,7 @@ async function executeRun(context, args) {
|
|
|
8087
8247
|
};
|
|
8088
8248
|
}
|
|
8089
8249
|
if (runId) {
|
|
8090
|
-
const stopped = await stopRunViaServer(context, runId);
|
|
8250
|
+
const stopped = await withSpinner(`Requesting stop for ${runId}\u2026`, () => stopRunViaServer(context, runId), { outputMode: context.outputMode });
|
|
8091
8251
|
if (context.outputMode === "text")
|
|
8092
8252
|
console.log(`Stop requested: ${runId}`);
|
|
8093
8253
|
return { ok: true, group: "run", command, details: stopped };
|
|
@@ -8333,12 +8493,12 @@ async function executeServer(context, args, options) {
|
|
|
8333
8493
|
|
|
8334
8494
|
// packages/cli/src/commands/stats.ts
|
|
8335
8495
|
init_runner();
|
|
8336
|
-
import
|
|
8496
|
+
import pc6 from "picocolors";
|
|
8337
8497
|
import { computeRigStats } from "@rig/runtime/control-plane/native/run-stats";
|
|
8338
8498
|
|
|
8339
8499
|
// packages/cli/src/commands/_help-catalog.ts
|
|
8340
8500
|
import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@clack/prompts";
|
|
8341
|
-
import
|
|
8501
|
+
import pc5 from "picocolors";
|
|
8342
8502
|
var TOP_LEVEL_SECTIONS = [
|
|
8343
8503
|
{
|
|
8344
8504
|
title: "Start here",
|
|
@@ -8626,13 +8786,13 @@ var ADVANCED_COMMANDS = [
|
|
|
8626
8786
|
];
|
|
8627
8787
|
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
8628
8788
|
function heading(title) {
|
|
8629
|
-
return
|
|
8789
|
+
return pc5.bold(pc5.cyan(title));
|
|
8630
8790
|
}
|
|
8631
8791
|
function renderRigBanner(version) {
|
|
8632
|
-
const m = (s) =>
|
|
8633
|
-
const c = (s) =>
|
|
8634
|
-
const y = (s) =>
|
|
8635
|
-
const d = (s) =>
|
|
8792
|
+
const m = (s) => pc5.bold(pc5.magenta(s));
|
|
8793
|
+
const c = (s) => pc5.bold(pc5.cyan(s));
|
|
8794
|
+
const y = (s) => pc5.yellow(s);
|
|
8795
|
+
const d = (s) => pc5.dim(s);
|
|
8636
8796
|
const lines = [
|
|
8637
8797
|
m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
|
|
8638
8798
|
m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
|
|
@@ -8641,7 +8801,7 @@ function renderRigBanner(version) {
|
|
|
8641
8801
|
y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
|
|
8642
8802
|
y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
|
|
8643
8803
|
"",
|
|
8644
|
-
` ${c("\u25E2\u25E4")} ${
|
|
8804
|
+
` ${c("\u25E2\u25E4")} ${pc5.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
|
|
8645
8805
|
version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
|
|
8646
8806
|
];
|
|
8647
8807
|
return lines.join(`
|
|
@@ -8649,7 +8809,7 @@ function renderRigBanner(version) {
|
|
|
8649
8809
|
}
|
|
8650
8810
|
function commandLine(command, description) {
|
|
8651
8811
|
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
8652
|
-
return `${
|
|
8812
|
+
return `${pc5.dim("\u2502")} ${pc5.bold(commandColumn)} ${description}`;
|
|
8653
8813
|
}
|
|
8654
8814
|
function renderCommandBlock(commands) {
|
|
8655
8815
|
return commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
@@ -8659,37 +8819,37 @@ function renderGroup(group) {
|
|
|
8659
8819
|
const lines = [
|
|
8660
8820
|
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
8661
8821
|
"",
|
|
8662
|
-
|
|
8822
|
+
pc5.bold("Usage"),
|
|
8663
8823
|
...group.usage.map((line) => ` ${line}`),
|
|
8664
8824
|
"",
|
|
8665
|
-
|
|
8825
|
+
pc5.bold("Commands"),
|
|
8666
8826
|
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
8667
8827
|
];
|
|
8668
8828
|
if (group.examples?.length) {
|
|
8669
|
-
lines.push("",
|
|
8829
|
+
lines.push("", pc5.bold("Examples"), ...group.examples.map((line) => ` ${pc5.dim("$")} ${line}`));
|
|
8670
8830
|
}
|
|
8671
8831
|
if (group.next?.length) {
|
|
8672
|
-
lines.push("",
|
|
8832
|
+
lines.push("", pc5.bold("Next steps"), ...group.next.map((line) => ` ${pc5.dim("\u203A")} ${line}`));
|
|
8673
8833
|
}
|
|
8674
8834
|
if (group.advanced?.length) {
|
|
8675
|
-
lines.push("",
|
|
8835
|
+
lines.push("", pc5.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc5.dim("\u203A")} ${line}`));
|
|
8676
8836
|
}
|
|
8677
8837
|
return lines.join(`
|
|
8678
8838
|
`);
|
|
8679
8839
|
}
|
|
8680
8840
|
function renderTopLevelHelp() {
|
|
8681
8841
|
return [
|
|
8682
|
-
`${heading("rig")} ${
|
|
8683
|
-
|
|
8842
|
+
`${heading("rig")} ${pc5.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
8843
|
+
pc5.dim("Current path: select a server, choose a task, submit a run, attach with native Pi, clear inbox gates."),
|
|
8684
8844
|
"",
|
|
8685
8845
|
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
8686
|
-
`${
|
|
8846
|
+
`${pc5.bold(pc5.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc5.dim(section.subtitle)}`,
|
|
8687
8847
|
renderCommandBlock(section.commands),
|
|
8688
8848
|
""
|
|
8689
8849
|
]),
|
|
8690
|
-
|
|
8850
|
+
pc5.dim("More: `rig help --advanced` for dev/compatibility commands; `rig <group> --help` for rich per-group help; `rig --version` for the installed version."),
|
|
8691
8851
|
"",
|
|
8692
|
-
|
|
8852
|
+
pc5.bold("Global options"),
|
|
8693
8853
|
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
8694
8854
|
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
8695
8855
|
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
@@ -8700,16 +8860,16 @@ function renderAdvancedHelp() {
|
|
|
8700
8860
|
return [
|
|
8701
8861
|
`${heading("rig advanced")} \u2014 compatibility, diagnostics, and internal surfaces`,
|
|
8702
8862
|
"",
|
|
8703
|
-
|
|
8863
|
+
pc5.bold("Primary groups"),
|
|
8704
8864
|
" init, server, task, run, inbox, repo, plugin, inspect, stats, doctor, github",
|
|
8705
8865
|
"",
|
|
8706
|
-
|
|
8866
|
+
pc5.bold("Advanced commands"),
|
|
8707
8867
|
...ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)),
|
|
8708
8868
|
"",
|
|
8709
|
-
|
|
8869
|
+
pc5.bold("Advanced groups"),
|
|
8710
8870
|
...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
8711
8871
|
"",
|
|
8712
|
-
|
|
8872
|
+
pc5.dim("All groups remain callable. Prefer `rig server`, `rig task`, `rig run`, and `rig inbox` for day-to-day work.")
|
|
8713
8873
|
].join(`
|
|
8714
8874
|
`);
|
|
8715
8875
|
}
|
|
@@ -8857,11 +9017,11 @@ function formatStatsReport(stats) {
|
|
|
8857
9017
|
const keyWidth = Math.max(...rows.map(([key]) => key.length));
|
|
8858
9018
|
const lines = [
|
|
8859
9019
|
formatSection("Fleet stats", window),
|
|
8860
|
-
...rows.map(([key, value]) => `${
|
|
9020
|
+
...rows.map(([key, value]) => `${pc6.dim("\u2502")} ${pc6.dim(key.padEnd(keyWidth + 2))} ${value}`)
|
|
8861
9021
|
];
|
|
8862
9022
|
const otherStatuses = Object.entries(stats.statusCounts).filter(([status]) => !["completed", "failed", "needs-attention"].includes(status)).sort(([, left], [, right]) => right - left);
|
|
8863
9023
|
if (otherStatuses.length > 0) {
|
|
8864
|
-
lines.push(`${
|
|
9024
|
+
lines.push(`${pc6.dim("\u2502")} ${pc6.dim("other".padEnd(keyWidth + 2))} ${otherStatuses.map(([status, count]) => `${status}:${count}`).join(" ")}`);
|
|
8865
9025
|
}
|
|
8866
9026
|
lines.push("", ...formatNextSteps([
|
|
8867
9027
|
"Inspect a run: `rig run list` then `rig run show <run-id>`",
|
|
@@ -8880,7 +9040,8 @@ async function executeStats(context, args) {
|
|
|
8880
9040
|
const sinceResult = takeOption(pending, "--since");
|
|
8881
9041
|
requireNoExtraArgs(sinceResult.rest, "rig stats [show] [--since <7d|30d|ISO date>]");
|
|
8882
9042
|
const since = parseSinceOption(sinceResult.value);
|
|
8883
|
-
const
|
|
9043
|
+
const remoteStats = isRemoteConnectionSelected(context.projectRoot);
|
|
9044
|
+
const stats = await withSpinner(remoteStats ? "Computing fleet stats on the server\u2026" : "Scanning local run state\u2026", async () => remoteStats ? await requestServerJson(context, `/api/stats${since ? `?since=${encodeURIComponent(since.toISOString())}` : ""}`) : computeRigStats(context.projectRoot, { since }), { outputMode: context.outputMode });
|
|
8884
9045
|
if (context.outputMode === "text") {
|
|
8885
9046
|
printFormattedOutput(formatStatsReport(stats));
|
|
8886
9047
|
}
|
|
@@ -9135,7 +9296,7 @@ async function executeTask(context, args, options) {
|
|
|
9135
9296
|
pending = rawResult.rest;
|
|
9136
9297
|
const { filters, rest: remaining } = parseTaskFilters(pending);
|
|
9137
9298
|
requireNoExtraArgs(remaining, "rig task list [--raw] [--assignee <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
9138
|
-
const tasks = await listWorkspaceTasksViaServer(context, filters);
|
|
9299
|
+
const tasks = await withSpinner("Reading tasks from server\u2026", () => listWorkspaceTasksViaServer(context, filters), { outputMode: context.outputMode });
|
|
9139
9300
|
if (context.outputMode === "text") {
|
|
9140
9301
|
const renderedTasks = rawResult.value ? tasks.map((task) => summarizeTask(task, { raw: true })) : tasks.map((task) => summarizeTask(task));
|
|
9141
9302
|
printFormattedOutput(formatTaskList(renderedTasks, { raw: rawResult.value }));
|
|
@@ -9159,7 +9320,7 @@ async function executeTask(context, args, options) {
|
|
|
9159
9320
|
const taskId3 = normalizeTaskRunTaskId(taskOption.value ?? positional);
|
|
9160
9321
|
if (!taskId3)
|
|
9161
9322
|
throw new CliError("task show requires a task id.", 2, { hint: "Run `rig task list` to find ids, then `rig task show <id>`." });
|
|
9162
|
-
const task = await getWorkspaceTaskViaServer(context, taskId3);
|
|
9323
|
+
const task = await withSpinner(`Reading task ${taskId3} from server\u2026`, () => getWorkspaceTaskViaServer(context, taskId3), { outputMode: context.outputMode });
|
|
9163
9324
|
if (!task)
|
|
9164
9325
|
throw new CliError(`Task not found: ${taskId3}`, 3, { hint: "Run `rig task list` to see available tasks." });
|
|
9165
9326
|
const summary = summarizeTask(task, { raw: true });
|
|
@@ -9171,7 +9332,7 @@ async function executeTask(context, args, options) {
|
|
|
9171
9332
|
case "next": {
|
|
9172
9333
|
const { filters, rest: remaining } = parseTaskFilters(rest);
|
|
9173
9334
|
requireNoExtraArgs(remaining, "rig task next [--assignee <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
9174
|
-
const selected = await selectNextWorkspaceTaskViaServer(context, filters);
|
|
9335
|
+
const selected = await withSpinner("Selecting next ready task\u2026", () => selectNextWorkspaceTaskViaServer(context, filters), { outputMode: context.outputMode });
|
|
9175
9336
|
if (context.outputMode === "text") {
|
|
9176
9337
|
if (selected.task) {
|
|
9177
9338
|
printFormattedOutput(formatTaskCard(summarizeTask(selected.task, { raw: true }), { title: "Selected task", selected: true }));
|
|
@@ -9321,7 +9482,7 @@ async function executeTask(context, args, options) {
|
|
|
9321
9482
|
let selectedTask = null;
|
|
9322
9483
|
let selectedTaskId = normalizeTaskRunTaskId(taskResult.value) ?? positionalTaskId;
|
|
9323
9484
|
if (nextResult.value) {
|
|
9324
|
-
const selected = await selectNextWorkspaceTaskViaServer(context, filterResult.filters);
|
|
9485
|
+
const selected = await withSpinner("Selecting next ready task\u2026", () => selectNextWorkspaceTaskViaServer(context, filterResult.filters), { outputMode: context.outputMode });
|
|
9325
9486
|
selectedTask = selected.task;
|
|
9326
9487
|
selectedTaskId = selected.task ? readTaskId(selected.task) : null;
|
|
9327
9488
|
if (!selectedTaskId) {
|
|
@@ -9332,7 +9493,7 @@ async function executeTask(context, args, options) {
|
|
|
9332
9493
|
if (context.outputMode !== "text" || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
9333
9494
|
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);
|
|
9334
9495
|
}
|
|
9335
|
-
const tasks = await listWorkspaceTasksViaServer(context, filterResult.filters);
|
|
9496
|
+
const tasks = await withSpinner("Reading tasks from server\u2026", () => listWorkspaceTasksViaServer(context, filterResult.filters), { outputMode: context.outputMode });
|
|
9336
9497
|
selectedTask = await selectTaskWithTextPicker(tasks);
|
|
9337
9498
|
selectedTaskId = selectedTask ? readTaskId(selectedTask) : null;
|
|
9338
9499
|
if (!selectedTaskId) {
|
|
@@ -9342,13 +9503,13 @@ async function executeTask(context, args, options) {
|
|
|
9342
9503
|
await runProjectMainSyncPreflight(context, { disabled: skipProjectSyncResult.value });
|
|
9343
9504
|
const projectDefaults = await loadTaskRunProjectDefaults(context.projectRoot);
|
|
9344
9505
|
const runtimeAdapter = normalizeRuntimeAdapter(runtimeAdapterResult.value ?? projectDefaults.runtimeAdapter);
|
|
9345
|
-
await runFastTaskRunPreflight(context, {
|
|
9506
|
+
await withSpinner("Running task-run preflight\u2026", () => runFastTaskRunPreflight(context, {
|
|
9346
9507
|
taskId: selectedTaskId,
|
|
9347
9508
|
runtimeAdapter
|
|
9348
|
-
});
|
|
9509
|
+
}), { outputMode: context.outputMode });
|
|
9349
9510
|
const dirtyBaseline = await resolveDirtyBaselineForTaskRun(context, dirtyBaselineResult.value);
|
|
9350
9511
|
const prMode = noPrResult.value ? "off" : normalizePrMode(prResult.value) ?? projectDefaults.prMode;
|
|
9351
|
-
const submitted = await submitTaskRunViaServer(context, {
|
|
9512
|
+
const submitted = await withSpinner("Dispatching run\u2026", () => submitTaskRunViaServer(context, {
|
|
9352
9513
|
runId: context.runId,
|
|
9353
9514
|
taskId: selectedTaskId ?? undefined,
|
|
9354
9515
|
title: titleResult.value ?? undefined,
|
|
@@ -9359,7 +9520,7 @@ async function executeTask(context, args, options) {
|
|
|
9359
9520
|
initialPrompt: initialPromptResult.value ?? undefined,
|
|
9360
9521
|
baselineMode: dirtyBaseline.mode,
|
|
9361
9522
|
prMode
|
|
9362
|
-
});
|
|
9523
|
+
}), { outputMode: context.outputMode });
|
|
9363
9524
|
let attachDetails = null;
|
|
9364
9525
|
if (!detachResult.value && context.outputMode === "text") {
|
|
9365
9526
|
printFormattedOutput(formatSubmittedRun({
|
|
@@ -11537,7 +11698,7 @@ async function executeSetup(context, args) {
|
|
|
11537
11698
|
case "check":
|
|
11538
11699
|
requireNoExtraArgs(rest, `rig setup ${command}`);
|
|
11539
11700
|
{
|
|
11540
|
-
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
|
|
11701
|
+
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot, context.outputMode));
|
|
11541
11702
|
return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
|
|
11542
11703
|
}
|
|
11543
11704
|
case "setup":
|
|
@@ -11546,7 +11707,7 @@ async function executeSetup(context, args) {
|
|
|
11546
11707
|
return { ok: true, group: "setup", command };
|
|
11547
11708
|
case "preflight":
|
|
11548
11709
|
requireNoExtraArgs(rest, "rig setup preflight");
|
|
11549
|
-
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
|
|
11710
|
+
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot, context.outputMode));
|
|
11550
11711
|
return { ok: true, group: "setup", command };
|
|
11551
11712
|
default:
|
|
11552
11713
|
throw new CliError(`Unknown setup command: ${command}`, 1, { hint: "Run `rig setup --help` \u2014 commands are bootstrap|check|preflight." });
|
|
@@ -11567,8 +11728,8 @@ function runSetupInit(projectRoot) {
|
|
|
11567
11728
|
}
|
|
11568
11729
|
console.log("Harness directories ready.");
|
|
11569
11730
|
}
|
|
11570
|
-
async function runSetupCheck(projectRoot) {
|
|
11571
|
-
const doctorChecks = await runRigDoctorChecks({ projectRoot });
|
|
11731
|
+
async function runSetupCheck(projectRoot, outputMode = "text") {
|
|
11732
|
+
const doctorChecks = await withSpinner("Running setup checks\u2026", (update) => runRigDoctorChecks({ projectRoot, onProgress: update }), { outputMode });
|
|
11572
11733
|
console.log(formatDoctorChecks(doctorChecks));
|
|
11573
11734
|
const failures = countDoctorFailures(doctorChecks);
|
|
11574
11735
|
if (failures > 0) {
|
|
@@ -11576,8 +11737,8 @@ async function runSetupCheck(projectRoot) {
|
|
|
11576
11737
|
}
|
|
11577
11738
|
return doctorChecks;
|
|
11578
11739
|
}
|
|
11579
|
-
async function runSetupPreflight(projectRoot) {
|
|
11580
|
-
await runSetupCheck(projectRoot);
|
|
11740
|
+
async function runSetupPreflight(projectRoot, outputMode = "text") {
|
|
11741
|
+
await runSetupCheck(projectRoot, outputMode);
|
|
11581
11742
|
const validationRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
|
|
11582
11743
|
if (existsSync15(validationRoot)) {
|
|
11583
11744
|
const validators = readdirSync3(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|