@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/bin/rig.js
CHANGED
|
@@ -2933,6 +2933,15 @@ import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
|
|
|
2933
2933
|
import { resolve as resolve11 } from "path";
|
|
2934
2934
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
2935
2935
|
var scopedGitHubBearerTokens = new Map;
|
|
2936
|
+
var serverPhaseListener = null;
|
|
2937
|
+
function setServerPhaseListener(listener) {
|
|
2938
|
+
const previous = serverPhaseListener;
|
|
2939
|
+
serverPhaseListener = listener;
|
|
2940
|
+
return previous;
|
|
2941
|
+
}
|
|
2942
|
+
function reportServerPhase(label) {
|
|
2943
|
+
serverPhaseListener?.(label);
|
|
2944
|
+
}
|
|
2936
2945
|
function cleanToken(value) {
|
|
2937
2946
|
const trimmed = value?.trim();
|
|
2938
2947
|
return trimmed ? trimmed : null;
|
|
@@ -2979,6 +2988,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
2979
2988
|
try {
|
|
2980
2989
|
const selected = resolveSelectedConnection(projectRoot);
|
|
2981
2990
|
if (selected?.connection.kind === "remote") {
|
|
2991
|
+
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
2982
2992
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
2983
2993
|
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
2984
2994
|
return {
|
|
@@ -2988,6 +2998,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
2988
2998
|
serverProjectRoot
|
|
2989
2999
|
};
|
|
2990
3000
|
}
|
|
3001
|
+
reportServerPhase("Starting local Rig server\u2026");
|
|
2991
3002
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
2992
3003
|
return {
|
|
2993
3004
|
baseUrl: connection.baseUrl,
|
|
@@ -3104,6 +3115,7 @@ async function requestServerJson(context, pathname, init = {}) {
|
|
|
3104
3115
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
3105
3116
|
if (server.serverProjectRoot)
|
|
3106
3117
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
3118
|
+
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
3107
3119
|
let response;
|
|
3108
3120
|
try {
|
|
3109
3121
|
response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
@@ -4624,6 +4636,127 @@ function formatConnectionStatus(selected, connections) {
|
|
|
4624
4636
|
`);
|
|
4625
4637
|
}
|
|
4626
4638
|
|
|
4639
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
4640
|
+
import pc4 from "picocolors";
|
|
4641
|
+
|
|
4642
|
+
// packages/cli/src/commands/_spinner.ts
|
|
4643
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
4644
|
+
function createTtySpinner(input) {
|
|
4645
|
+
const output = input.output ?? process.stdout;
|
|
4646
|
+
const isTty = output.isTTY === true;
|
|
4647
|
+
const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
|
|
4648
|
+
let label = input.label;
|
|
4649
|
+
let frame = 0;
|
|
4650
|
+
let paused = false;
|
|
4651
|
+
let stopped = false;
|
|
4652
|
+
let lastPrintedLabel = "";
|
|
4653
|
+
const render = () => {
|
|
4654
|
+
if (stopped || paused)
|
|
4655
|
+
return;
|
|
4656
|
+
if (!isTty) {
|
|
4657
|
+
if (label !== lastPrintedLabel) {
|
|
4658
|
+
output.write(`${label}
|
|
4659
|
+
`);
|
|
4660
|
+
lastPrintedLabel = label;
|
|
4661
|
+
}
|
|
4662
|
+
return;
|
|
4663
|
+
}
|
|
4664
|
+
frame = (frame + 1) % frames.length;
|
|
4665
|
+
const glyph = frames[frame] ?? frames[0] ?? "";
|
|
4666
|
+
output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
|
|
4667
|
+
};
|
|
4668
|
+
const clearLine = () => {
|
|
4669
|
+
if (isTty)
|
|
4670
|
+
output.write("\r\x1B[2K");
|
|
4671
|
+
};
|
|
4672
|
+
render();
|
|
4673
|
+
const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
|
|
4674
|
+
return {
|
|
4675
|
+
setLabel(next) {
|
|
4676
|
+
label = next;
|
|
4677
|
+
render();
|
|
4678
|
+
},
|
|
4679
|
+
pause() {
|
|
4680
|
+
paused = true;
|
|
4681
|
+
clearLine();
|
|
4682
|
+
},
|
|
4683
|
+
resume() {
|
|
4684
|
+
if (stopped)
|
|
4685
|
+
return;
|
|
4686
|
+
paused = false;
|
|
4687
|
+
render();
|
|
4688
|
+
},
|
|
4689
|
+
stop(finalLine) {
|
|
4690
|
+
if (stopped)
|
|
4691
|
+
return;
|
|
4692
|
+
stopped = true;
|
|
4693
|
+
if (timer)
|
|
4694
|
+
clearInterval(timer);
|
|
4695
|
+
clearLine();
|
|
4696
|
+
if (finalLine)
|
|
4697
|
+
output.write(`${finalLine}
|
|
4698
|
+
`);
|
|
4699
|
+
}
|
|
4700
|
+
};
|
|
4701
|
+
}
|
|
4702
|
+
|
|
4703
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
4704
|
+
var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
|
|
4705
|
+
var DONE_SYMBOL = pc4.green("\u25C7");
|
|
4706
|
+
var FAIL_SYMBOL = pc4.red("\u25A0");
|
|
4707
|
+
var activeUpdate = null;
|
|
4708
|
+
async function withSpinner(label, work, options = {}) {
|
|
4709
|
+
if (options.outputMode === "json") {
|
|
4710
|
+
return work(() => {});
|
|
4711
|
+
}
|
|
4712
|
+
if (activeUpdate) {
|
|
4713
|
+
const outer = activeUpdate;
|
|
4714
|
+
outer(label);
|
|
4715
|
+
return work(outer);
|
|
4716
|
+
}
|
|
4717
|
+
const output = options.output ?? process.stderr;
|
|
4718
|
+
const isTty = output.isTTY === true;
|
|
4719
|
+
let lastLabel = label;
|
|
4720
|
+
if (!isTty) {
|
|
4721
|
+
output.write(`${label}
|
|
4722
|
+
`);
|
|
4723
|
+
const update2 = (next) => {
|
|
4724
|
+
lastLabel = next;
|
|
4725
|
+
};
|
|
4726
|
+
activeUpdate = update2;
|
|
4727
|
+
const previousListener2 = setServerPhaseListener(update2);
|
|
4728
|
+
try {
|
|
4729
|
+
return await work(update2);
|
|
4730
|
+
} finally {
|
|
4731
|
+
activeUpdate = null;
|
|
4732
|
+
setServerPhaseListener(previousListener2);
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
4735
|
+
const spinner2 = createTtySpinner({
|
|
4736
|
+
label,
|
|
4737
|
+
output,
|
|
4738
|
+
frames: CLACK_SPINNER_FRAMES,
|
|
4739
|
+
styleFrame: (frame) => pc4.magenta(frame)
|
|
4740
|
+
});
|
|
4741
|
+
const update = (next) => {
|
|
4742
|
+
lastLabel = next;
|
|
4743
|
+
spinner2.setLabel(next);
|
|
4744
|
+
};
|
|
4745
|
+
activeUpdate = update;
|
|
4746
|
+
const previousListener = setServerPhaseListener(update);
|
|
4747
|
+
try {
|
|
4748
|
+
const result = await work(update);
|
|
4749
|
+
spinner2.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
|
|
4750
|
+
return result;
|
|
4751
|
+
} catch (error) {
|
|
4752
|
+
spinner2.stop(`${FAIL_SYMBOL} ${lastLabel}`);
|
|
4753
|
+
throw error;
|
|
4754
|
+
} finally {
|
|
4755
|
+
activeUpdate = null;
|
|
4756
|
+
setServerPhaseListener(previousListener);
|
|
4757
|
+
}
|
|
4758
|
+
}
|
|
4759
|
+
|
|
4627
4760
|
// packages/cli/src/commands/inbox.ts
|
|
4628
4761
|
async function listInboxRecords(context, kind, filters) {
|
|
4629
4762
|
const params = new URLSearchParams;
|
|
@@ -4728,7 +4861,7 @@ async function executeInbox(context, args) {
|
|
|
4728
4861
|
const task = takeOption(pending, "--task");
|
|
4729
4862
|
pending = task.rest;
|
|
4730
4863
|
requireNoExtraArgs(pending, "rig inbox approvals [--run <id>] [--task <id>]");
|
|
4731
|
-
const approvals = await listInboxRecords(context, "approvals", { run: run.value, task: task.value });
|
|
4864
|
+
const approvals = await withSpinner("Reading approvals from server\u2026", () => listInboxRecords(context, "approvals", { run: run.value, task: task.value }), { outputMode: context.outputMode });
|
|
4732
4865
|
renderList(context, "approvals", approvals);
|
|
4733
4866
|
return { ok: true, group: "inbox", command, details: { approvals } };
|
|
4734
4867
|
}
|
|
@@ -4739,7 +4872,7 @@ async function executeInbox(context, args) {
|
|
|
4739
4872
|
const task = takeOption(pending, "--task");
|
|
4740
4873
|
pending = task.rest;
|
|
4741
4874
|
requireNoExtraArgs(pending, "rig inbox inputs [--run <id>] [--task <id>]");
|
|
4742
|
-
const requests = await listInboxRecords(context, "inputs", { run: run.value, task: task.value });
|
|
4875
|
+
const requests = await withSpinner("Reading input requests from server\u2026", () => listInboxRecords(context, "inputs", { run: run.value, task: task.value }), { outputMode: context.outputMode });
|
|
4743
4876
|
renderList(context, "inputs", requests);
|
|
4744
4877
|
return { ok: true, group: "inbox", command, details: { requests } };
|
|
4745
4878
|
}
|
|
@@ -4760,7 +4893,7 @@ async function executeInbox(context, args) {
|
|
|
4760
4893
|
if (decision.value !== "approve" && decision.value !== "reject") {
|
|
4761
4894
|
throw new CliError("decision must be approve or reject.", 1, { hint: "Re-run as `rig inbox approve --run <id> --request <id> --decision approve|reject`." });
|
|
4762
4895
|
}
|
|
4763
|
-
const result = await requestServerJson(context, "/api/inbox/approvals/resolve", {
|
|
4896
|
+
const result = await withSpinner(`Resolving approval ${request.value}\u2026`, () => requestServerJson(context, "/api/inbox/approvals/resolve", {
|
|
4764
4897
|
method: "POST",
|
|
4765
4898
|
headers: { "content-type": "application/json" },
|
|
4766
4899
|
body: JSON.stringify({
|
|
@@ -4769,7 +4902,7 @@ async function executeInbox(context, args) {
|
|
|
4769
4902
|
decision: decision.value,
|
|
4770
4903
|
note: note4.value ?? null
|
|
4771
4904
|
})
|
|
4772
|
-
});
|
|
4905
|
+
}), { outputMode: context.outputMode });
|
|
4773
4906
|
return { ok: true, group: "inbox", command, details: { result } };
|
|
4774
4907
|
}
|
|
4775
4908
|
case "respond": {
|
|
@@ -4803,7 +4936,7 @@ async function executeInbox(context, args) {
|
|
|
4803
4936
|
const [key, ...restValue] = entry.split("=");
|
|
4804
4937
|
return [key, restValue.join("=")];
|
|
4805
4938
|
}));
|
|
4806
|
-
const result = await requestServerJson(context, "/api/inbox/inputs/respond", {
|
|
4939
|
+
const result = await withSpinner(`Sending response for ${request.value}\u2026`, () => requestServerJson(context, "/api/inbox/inputs/respond", {
|
|
4807
4940
|
method: "POST",
|
|
4808
4941
|
headers: { "content-type": "application/json" },
|
|
4809
4942
|
body: JSON.stringify({
|
|
@@ -4811,7 +4944,7 @@ async function executeInbox(context, args) {
|
|
|
4811
4944
|
requestId: request.value,
|
|
4812
4945
|
answers: parsedAnswers
|
|
4813
4946
|
})
|
|
4814
|
-
});
|
|
4947
|
+
}), { outputMode: context.outputMode });
|
|
4815
4948
|
return { ok: true, group: "inbox", command, details: { result } };
|
|
4816
4949
|
}
|
|
4817
4950
|
case "watch": {
|
|
@@ -5228,7 +5361,10 @@ async function runRigDoctorChecks(options) {
|
|
|
5228
5361
|
const bunVersion = options.bunVersion ?? Bun.version;
|
|
5229
5362
|
const request = options.requestJson ?? ((pathname, init) => requestServerJson({ projectRoot }, pathname, init));
|
|
5230
5363
|
const loadConfig = options.loadConfig ?? loadRigConfigOrNull;
|
|
5364
|
+
const progress = options.onProgress ?? (() => {});
|
|
5365
|
+
progress("Checking local toolchain\u2026");
|
|
5231
5366
|
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`)."));
|
|
5367
|
+
progress("Loading rig.config\u2026");
|
|
5232
5368
|
const loadedConfig = await loadConfig(projectRoot).catch(() => null);
|
|
5233
5369
|
const config = loadedConfig ?? loadFallbackConfig(projectRoot);
|
|
5234
5370
|
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync11(resolve17(projectRoot, name)));
|
|
@@ -5247,6 +5383,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5247
5383
|
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));
|
|
5248
5384
|
let server = null;
|
|
5249
5385
|
try {
|
|
5386
|
+
progress("Connecting to the selected Rig server\u2026");
|
|
5250
5387
|
server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
|
|
5251
5388
|
checks.push(check("server", "Rig server reachable", "pass", `${server.connectionKind} ${server.baseUrl}`));
|
|
5252
5389
|
} catch (error) {
|
|
@@ -5254,18 +5391,21 @@ async function runRigDoctorChecks(options) {
|
|
|
5254
5391
|
}
|
|
5255
5392
|
if (server || options.requestJson) {
|
|
5256
5393
|
try {
|
|
5394
|
+
progress("Checking server status\u2026");
|
|
5257
5395
|
const status = await request("/api/server/status");
|
|
5258
5396
|
checks.push(check("server-status", "server project status", "pass", JSON.stringify(status).slice(0, 180)));
|
|
5259
5397
|
} catch (error) {
|
|
5260
5398
|
checks.push(check("server-status", "server project status", "fail", errorMessage(error), "Run `rig doctor` after the selected server is reachable."));
|
|
5261
5399
|
}
|
|
5262
5400
|
try {
|
|
5401
|
+
progress("Checking GitHub auth\u2026");
|
|
5263
5402
|
const auth = await request("/api/github/auth/status");
|
|
5264
5403
|
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>`."));
|
|
5265
5404
|
} catch (error) {
|
|
5266
5405
|
checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig and ensure the server exposes auth status."));
|
|
5267
5406
|
}
|
|
5268
5407
|
try {
|
|
5408
|
+
progress("Checking GitHub repo permissions\u2026");
|
|
5269
5409
|
const permissions = await request("/api/github/repo/permissions");
|
|
5270
5410
|
const allowed = permissionAllowsPr2(permissions);
|
|
5271
5411
|
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."));
|
|
@@ -5273,6 +5413,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5273
5413
|
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."));
|
|
5274
5414
|
}
|
|
5275
5415
|
try {
|
|
5416
|
+
progress("Checking GitHub issue labels\u2026");
|
|
5276
5417
|
const labels = await request("/api/workspace/task-labels");
|
|
5277
5418
|
const ready = labelsReady(labels);
|
|
5278
5419
|
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."));
|
|
@@ -5280,6 +5421,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5280
5421
|
checks.push(check("task-labels", "GitHub issue labels", "warn", errorMessage(error), "Run `rig init`/`rig doctor` after label setup is wired on the server."));
|
|
5281
5422
|
}
|
|
5282
5423
|
try {
|
|
5424
|
+
progress("Checking task projection\u2026");
|
|
5283
5425
|
const projection = await request("/api/workspace/task-projection");
|
|
5284
5426
|
checks.push(check("task-projection", "task projection", "pass", JSON.stringify(projection).slice(0, 180)));
|
|
5285
5427
|
} catch (error) {
|
|
@@ -5288,6 +5430,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5288
5430
|
const slug = projectStatusSlug(projectRoot, config);
|
|
5289
5431
|
if (slug) {
|
|
5290
5432
|
try {
|
|
5433
|
+
progress("Checking server project checkout\u2026");
|
|
5291
5434
|
const project = await request(`/api/projects/${encodeURIComponent(slug)}`);
|
|
5292
5435
|
checks.push(check("remote-checkout", "server project checkout", "pass", JSON.stringify(project).slice(0, 180)));
|
|
5293
5436
|
} catch (error) {
|
|
@@ -5302,6 +5445,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5302
5445
|
}
|
|
5303
5446
|
checks.push(githubProjectsCheck(config));
|
|
5304
5447
|
checks.push(prMergeCheck(config));
|
|
5448
|
+
progress("Checking Pi installation\u2026");
|
|
5305
5449
|
const piChecks = await (options.piChecks ?? (() => buildPiSetupChecks()))().catch((error) => [{
|
|
5306
5450
|
ok: false,
|
|
5307
5451
|
label: "pi/pi-rig checks",
|
|
@@ -6224,7 +6368,7 @@ async function executeGithub(context, args) {
|
|
|
6224
6368
|
case "status": {
|
|
6225
6369
|
if (rest.length > 0)
|
|
6226
6370
|
throw new CliError("Usage: rig github auth status", 1);
|
|
6227
|
-
const status = await getGitHubAuthStatusViaServer(context);
|
|
6371
|
+
const status = await withSpinner("Checking GitHub auth on the server\u2026", () => getGitHubAuthStatusViaServer(context), { outputMode: context.outputMode });
|
|
6228
6372
|
printPayload(context, status, `GitHub auth: ${status.authenticated ? "authenticated" : "unauthenticated"}`);
|
|
6229
6373
|
return { ok: true, group: "github", command: "auth status", details: status };
|
|
6230
6374
|
}
|
|
@@ -6235,14 +6379,15 @@ async function executeGithub(context, args) {
|
|
|
6235
6379
|
const token = parsed.value?.trim();
|
|
6236
6380
|
if (!token)
|
|
6237
6381
|
throw new CliError("Missing --token value.", 1, { hint: "Re-run as `rig github auth token --token <token>`." });
|
|
6238
|
-
const result = await postGitHubTokenViaServer(context, token);
|
|
6382
|
+
const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token), { outputMode: context.outputMode });
|
|
6239
6383
|
printPayload(context, result, "GitHub token stored on the selected Rig server.");
|
|
6240
6384
|
return { ok: true, group: "github", command: "auth token", details: result };
|
|
6241
6385
|
}
|
|
6242
6386
|
case "import-gh": {
|
|
6243
6387
|
if (rest.length > 0)
|
|
6244
6388
|
throw new CliError("Usage: rig github auth import-gh", 1);
|
|
6245
|
-
const
|
|
6389
|
+
const importedToken = readGhToken();
|
|
6390
|
+
const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken), { outputMode: context.outputMode });
|
|
6246
6391
|
printPayload(context, result, "GitHub token imported from gh and stored on the selected Rig server.");
|
|
6247
6392
|
return { ok: true, group: "github", command: "auth import-gh", details: result };
|
|
6248
6393
|
}
|
|
@@ -6255,7 +6400,7 @@ async function executeGithub(context, args) {
|
|
|
6255
6400
|
init_runner();
|
|
6256
6401
|
async function executeDoctor(context, args) {
|
|
6257
6402
|
requireNoExtraArgs(args, "rig doctor");
|
|
6258
|
-
const checks = await runRigDoctorChecks({ projectRoot: context.projectRoot });
|
|
6403
|
+
const checks = await withSpinner("Running doctor checks\u2026", (update) => runRigDoctorChecks({ projectRoot: context.projectRoot, onProgress: update }), { outputMode: context.outputMode });
|
|
6259
6404
|
if (context.outputMode === "text") {
|
|
6260
6405
|
console.log(formatDoctorChecks(checks));
|
|
6261
6406
|
}
|
|
@@ -6562,13 +6707,19 @@ async function executeInspect(context, args) {
|
|
|
6562
6707
|
const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
|
|
6563
6708
|
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];
|
|
6564
6709
|
if (!latestRun) {
|
|
6565
|
-
const
|
|
6566
|
-
|
|
6567
|
-
|
|
6710
|
+
const fallback = await withSpinner(`Finding runs for ${requiredTask} on the server\u2026`, async (update) => {
|
|
6711
|
+
const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
|
|
6712
|
+
const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
|
|
6713
|
+
if (!serverRun || typeof serverRun.runId !== "string")
|
|
6714
|
+
return null;
|
|
6715
|
+
update(`Reading logs for run ${serverRun.runId}\u2026`);
|
|
6716
|
+
const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
|
|
6717
|
+
return { runId: serverRun.runId, page };
|
|
6718
|
+
}, { outputMode: context.outputMode });
|
|
6719
|
+
if (!fallback) {
|
|
6568
6720
|
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`." });
|
|
6569
6721
|
}
|
|
6570
|
-
const
|
|
6571
|
-
const entries = Array.isArray(page.entries) ? page.entries : [];
|
|
6722
|
+
const entries = Array.isArray(fallback.page.entries) ? fallback.page.entries : [];
|
|
6572
6723
|
if (context.outputMode === "text") {
|
|
6573
6724
|
for (const entry of entries) {
|
|
6574
6725
|
const record = entry && typeof entry === "object" ? entry : {};
|
|
@@ -6577,9 +6728,9 @@ async function executeInspect(context, args) {
|
|
|
6577
6728
|
console.log([title, detail].filter(Boolean).join(" \u2014 "));
|
|
6578
6729
|
}
|
|
6579
6730
|
if (entries.length === 0)
|
|
6580
|
-
console.log(`(no log entries for run ${
|
|
6731
|
+
console.log(`(no log entries for run ${fallback.runId})`);
|
|
6581
6732
|
}
|
|
6582
|
-
return { ok: true, group: "inspect", command, details: { task: requiredTask, runId:
|
|
6733
|
+
return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: fallback.runId, source: "server", entries } };
|
|
6583
6734
|
}
|
|
6584
6735
|
const logsPath = resolve20(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
|
|
6585
6736
|
if (!existsSync13(logsPath)) {
|
|
@@ -6637,7 +6788,7 @@ async function executeInspect(context, args) {
|
|
|
6637
6788
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
6638
6789
|
requireNoExtraArgs(remaining, "rig inspect diff [--task <task-id>]");
|
|
6639
6790
|
if (task) {
|
|
6640
|
-
const files = changedFilesForTask(context.projectRoot, task, false);
|
|
6791
|
+
const files = await withSpinner(`Computing changed files for ${task}\u2026`, async () => changedFilesForTask(context.projectRoot, task, false), { outputMode: context.outputMode });
|
|
6641
6792
|
for (const file of files) {
|
|
6642
6793
|
console.log(file);
|
|
6643
6794
|
}
|
|
@@ -7725,7 +7876,12 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
7725
7876
|
};
|
|
7726
7877
|
let detached = false;
|
|
7727
7878
|
try {
|
|
7728
|
-
await runPiMain([
|
|
7879
|
+
await runPiMain([
|
|
7880
|
+
"--no-extensions",
|
|
7881
|
+
"--no-skills",
|
|
7882
|
+
"--no-prompt-templates",
|
|
7883
|
+
"--no-context-files"
|
|
7884
|
+
], {
|
|
7729
7885
|
extensionFactories: [piRigExtensionFactory]
|
|
7730
7886
|
});
|
|
7731
7887
|
detached = true;
|
|
@@ -7790,8 +7946,9 @@ async function readOperatorSnapshot(context, runId, options = {}) {
|
|
|
7790
7946
|
}
|
|
7791
7947
|
async function attachRunOperatorView(context, input) {
|
|
7792
7948
|
let steered = false;
|
|
7793
|
-
|
|
7794
|
-
|
|
7949
|
+
const attachMessage = input.message?.trim();
|
|
7950
|
+
if (attachMessage) {
|
|
7951
|
+
await withSpinner("Queueing steering message\u2026", () => sendRunPiPromptViaServer(context, input.runId, attachMessage, "steer").catch(() => steerRunViaServer(context, input.runId, attachMessage)), { outputMode: context.outputMode });
|
|
7795
7952
|
steered = true;
|
|
7796
7953
|
}
|
|
7797
7954
|
if (input.follow && !input.once && input.interactive !== false && context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
@@ -7801,7 +7958,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
7801
7958
|
});
|
|
7802
7959
|
}
|
|
7803
7960
|
const surface = createOperatorSurface({ interactive: input.interactive !== false });
|
|
7804
|
-
let snapshot = await readOperatorSnapshot(context, input.runId);
|
|
7961
|
+
let snapshot = await withSpinner(`Connecting to run ${input.runId}\u2026`, () => readOperatorSnapshot(context, input.runId), { outputMode: context.outputMode });
|
|
7805
7962
|
if (context.outputMode === "text") {
|
|
7806
7963
|
surface.renderSnapshot(snapshot);
|
|
7807
7964
|
surface.renderTimeline(snapshot.timeline);
|
|
@@ -7932,7 +8089,7 @@ async function executeRun(context, args) {
|
|
|
7932
8089
|
switch (command) {
|
|
7933
8090
|
case "list": {
|
|
7934
8091
|
requireNoExtraArgs(rest, "rig run list");
|
|
7935
|
-
const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
|
|
8092
|
+
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 });
|
|
7936
8093
|
if (context.outputMode === "text") {
|
|
7937
8094
|
printFormattedOutput(formatRunList(runs, { source }));
|
|
7938
8095
|
await printPendingInboxFooter(context);
|
|
@@ -8005,7 +8162,7 @@ async function executeRun(context, args) {
|
|
|
8005
8162
|
if (!runId) {
|
|
8006
8163
|
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>`." });
|
|
8007
8164
|
}
|
|
8008
|
-
const record = readAuthorityRun5(context.projectRoot, runId) ?? normalizeRemoteRunDetails(await getRunDetailsViaServer(context, runId).catch(() => ({})));
|
|
8165
|
+
const record = readAuthorityRun5(context.projectRoot, runId) ?? normalizeRemoteRunDetails(await withSpinner(`Reading run ${runId} from server\u2026`, () => getRunDetailsViaServer(context, runId).catch(() => ({})), { outputMode: context.outputMode }));
|
|
8009
8166
|
if (!record) {
|
|
8010
8167
|
throw new CliError(`Run not found: ${runId}`, 2, { hint: "Run `rig run list` to see recorded runs." });
|
|
8011
8168
|
}
|
|
@@ -8026,7 +8183,8 @@ async function executeRun(context, args) {
|
|
|
8026
8183
|
}
|
|
8027
8184
|
const renderer = createPiRunStreamRenderer();
|
|
8028
8185
|
let cursor = null;
|
|
8029
|
-
const
|
|
8186
|
+
const timelineRunId = run.value;
|
|
8187
|
+
const page = await withSpinner(`Reading timeline for ${timelineRunId}\u2026`, () => getRunTimelineViaServer(context, timelineRunId, { limit: 500 }), { outputMode: context.outputMode });
|
|
8030
8188
|
const events = Array.isArray(page.entries) ? page.entries.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))) : [];
|
|
8031
8189
|
cursor = typeof page.nextCursor === "string" ? page.nextCursor : null;
|
|
8032
8190
|
if (context.outputMode === "text") {
|
|
@@ -8103,8 +8261,9 @@ async function executeRun(context, args) {
|
|
|
8103
8261
|
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`." });
|
|
8104
8262
|
}
|
|
8105
8263
|
let steered = false;
|
|
8106
|
-
|
|
8107
|
-
|
|
8264
|
+
const steerMessage = messageOption.value?.trim();
|
|
8265
|
+
if (steerMessage) {
|
|
8266
|
+
await withSpinner("Queueing steering message\u2026", () => steerRunViaServer(context, runId, steerMessage), { outputMode: context.outputMode });
|
|
8108
8267
|
steered = true;
|
|
8109
8268
|
}
|
|
8110
8269
|
const attached = await attachRunOperatorView(context, {
|
|
@@ -8124,7 +8283,7 @@ async function executeRun(context, args) {
|
|
|
8124
8283
|
}
|
|
8125
8284
|
return { ok: true, group: "run", command };
|
|
8126
8285
|
}
|
|
8127
|
-
const summary = isRemoteConnectionSelected(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
|
|
8286
|
+
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);
|
|
8128
8287
|
const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
8129
8288
|
const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
8130
8289
|
if (context.outputMode === "text") {
|
|
@@ -8259,7 +8418,8 @@ async function executeRun(context, args) {
|
|
|
8259
8418
|
}
|
|
8260
8419
|
return { ok: true, group: "run", command, details: { runId, dryRun: true } };
|
|
8261
8420
|
}
|
|
8262
|
-
|
|
8421
|
+
const trimmedMessage = message2.trim();
|
|
8422
|
+
await withSpinner("Queueing steering message\u2026", () => steerRunViaServer(context, runId, trimmedMessage), { outputMode: context.outputMode });
|
|
8263
8423
|
if (context.outputMode === "text") {
|
|
8264
8424
|
console.log(`Steering message queued for ${runId}.`);
|
|
8265
8425
|
}
|
|
@@ -8280,7 +8440,7 @@ async function executeRun(context, args) {
|
|
|
8280
8440
|
};
|
|
8281
8441
|
}
|
|
8282
8442
|
if (runId) {
|
|
8283
|
-
const stopped = await stopRunViaServer(context, runId);
|
|
8443
|
+
const stopped = await withSpinner(`Requesting stop for ${runId}\u2026`, () => stopRunViaServer(context, runId), { outputMode: context.outputMode });
|
|
8284
8444
|
if (context.outputMode === "text")
|
|
8285
8445
|
console.log(`Stop requested: ${runId}`);
|
|
8286
8446
|
return { ok: true, group: "run", command, details: stopped };
|
|
@@ -8526,12 +8686,12 @@ async function executeServer(context, args, options) {
|
|
|
8526
8686
|
|
|
8527
8687
|
// packages/cli/src/commands/stats.ts
|
|
8528
8688
|
init_runner();
|
|
8529
|
-
import
|
|
8689
|
+
import pc6 from "picocolors";
|
|
8530
8690
|
import { computeRigStats } from "@rig/runtime/control-plane/native/run-stats";
|
|
8531
8691
|
|
|
8532
8692
|
// packages/cli/src/commands/_help-catalog.ts
|
|
8533
8693
|
import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@clack/prompts";
|
|
8534
|
-
import
|
|
8694
|
+
import pc5 from "picocolors";
|
|
8535
8695
|
var TOP_LEVEL_SECTIONS = [
|
|
8536
8696
|
{
|
|
8537
8697
|
title: "Start here",
|
|
@@ -8819,13 +8979,13 @@ var ADVANCED_COMMANDS = [
|
|
|
8819
8979
|
];
|
|
8820
8980
|
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
8821
8981
|
function heading(title) {
|
|
8822
|
-
return
|
|
8982
|
+
return pc5.bold(pc5.cyan(title));
|
|
8823
8983
|
}
|
|
8824
8984
|
function renderRigBanner(version) {
|
|
8825
|
-
const m = (s) =>
|
|
8826
|
-
const c = (s) =>
|
|
8827
|
-
const y = (s) =>
|
|
8828
|
-
const d = (s) =>
|
|
8985
|
+
const m = (s) => pc5.bold(pc5.magenta(s));
|
|
8986
|
+
const c = (s) => pc5.bold(pc5.cyan(s));
|
|
8987
|
+
const y = (s) => pc5.yellow(s);
|
|
8988
|
+
const d = (s) => pc5.dim(s);
|
|
8829
8989
|
const lines = [
|
|
8830
8990
|
m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
|
|
8831
8991
|
m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
|
|
@@ -8834,7 +8994,7 @@ function renderRigBanner(version) {
|
|
|
8834
8994
|
y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
|
|
8835
8995
|
y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
|
|
8836
8996
|
"",
|
|
8837
|
-
` ${c("\u25E2\u25E4")} ${
|
|
8997
|
+
` ${c("\u25E2\u25E4")} ${pc5.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
|
|
8838
8998
|
version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
|
|
8839
8999
|
];
|
|
8840
9000
|
return lines.join(`
|
|
@@ -8842,7 +9002,7 @@ function renderRigBanner(version) {
|
|
|
8842
9002
|
}
|
|
8843
9003
|
function commandLine(command, description) {
|
|
8844
9004
|
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
8845
|
-
return `${
|
|
9005
|
+
return `${pc5.dim("\u2502")} ${pc5.bold(commandColumn)} ${description}`;
|
|
8846
9006
|
}
|
|
8847
9007
|
function renderCommandBlock(commands) {
|
|
8848
9008
|
return commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
@@ -8852,37 +9012,37 @@ function renderGroup(group) {
|
|
|
8852
9012
|
const lines = [
|
|
8853
9013
|
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
8854
9014
|
"",
|
|
8855
|
-
|
|
9015
|
+
pc5.bold("Usage"),
|
|
8856
9016
|
...group.usage.map((line) => ` ${line}`),
|
|
8857
9017
|
"",
|
|
8858
|
-
|
|
9018
|
+
pc5.bold("Commands"),
|
|
8859
9019
|
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
8860
9020
|
];
|
|
8861
9021
|
if (group.examples?.length) {
|
|
8862
|
-
lines.push("",
|
|
9022
|
+
lines.push("", pc5.bold("Examples"), ...group.examples.map((line) => ` ${pc5.dim("$")} ${line}`));
|
|
8863
9023
|
}
|
|
8864
9024
|
if (group.next?.length) {
|
|
8865
|
-
lines.push("",
|
|
9025
|
+
lines.push("", pc5.bold("Next steps"), ...group.next.map((line) => ` ${pc5.dim("\u203A")} ${line}`));
|
|
8866
9026
|
}
|
|
8867
9027
|
if (group.advanced?.length) {
|
|
8868
|
-
lines.push("",
|
|
9028
|
+
lines.push("", pc5.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc5.dim("\u203A")} ${line}`));
|
|
8869
9029
|
}
|
|
8870
9030
|
return lines.join(`
|
|
8871
9031
|
`);
|
|
8872
9032
|
}
|
|
8873
9033
|
function renderTopLevelHelp() {
|
|
8874
9034
|
return [
|
|
8875
|
-
`${heading("rig")} ${
|
|
8876
|
-
|
|
9035
|
+
`${heading("rig")} ${pc5.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
9036
|
+
pc5.dim("Current path: select a server, choose a task, submit a run, attach with native Pi, clear inbox gates."),
|
|
8877
9037
|
"",
|
|
8878
9038
|
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
8879
|
-
`${
|
|
9039
|
+
`${pc5.bold(pc5.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc5.dim(section.subtitle)}`,
|
|
8880
9040
|
renderCommandBlock(section.commands),
|
|
8881
9041
|
""
|
|
8882
9042
|
]),
|
|
8883
|
-
|
|
9043
|
+
pc5.dim("More: `rig help --advanced` for dev/compatibility commands; `rig <group> --help` for rich per-group help; `rig --version` for the installed version."),
|
|
8884
9044
|
"",
|
|
8885
|
-
|
|
9045
|
+
pc5.bold("Global options"),
|
|
8886
9046
|
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
8887
9047
|
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
8888
9048
|
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
@@ -8893,16 +9053,16 @@ function renderAdvancedHelp() {
|
|
|
8893
9053
|
return [
|
|
8894
9054
|
`${heading("rig advanced")} \u2014 compatibility, diagnostics, and internal surfaces`,
|
|
8895
9055
|
"",
|
|
8896
|
-
|
|
9056
|
+
pc5.bold("Primary groups"),
|
|
8897
9057
|
" init, server, task, run, inbox, repo, plugin, inspect, stats, doctor, github",
|
|
8898
9058
|
"",
|
|
8899
|
-
|
|
9059
|
+
pc5.bold("Advanced commands"),
|
|
8900
9060
|
...ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)),
|
|
8901
9061
|
"",
|
|
8902
|
-
|
|
9062
|
+
pc5.bold("Advanced groups"),
|
|
8903
9063
|
...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
8904
9064
|
"",
|
|
8905
|
-
|
|
9065
|
+
pc5.dim("All groups remain callable. Prefer `rig server`, `rig task`, `rig run`, and `rig inbox` for day-to-day work.")
|
|
8906
9066
|
].join(`
|
|
8907
9067
|
`);
|
|
8908
9068
|
}
|
|
@@ -9050,11 +9210,11 @@ function formatStatsReport(stats) {
|
|
|
9050
9210
|
const keyWidth = Math.max(...rows.map(([key]) => key.length));
|
|
9051
9211
|
const lines = [
|
|
9052
9212
|
formatSection("Fleet stats", window),
|
|
9053
|
-
...rows.map(([key, value]) => `${
|
|
9213
|
+
...rows.map(([key, value]) => `${pc6.dim("\u2502")} ${pc6.dim(key.padEnd(keyWidth + 2))} ${value}`)
|
|
9054
9214
|
];
|
|
9055
9215
|
const otherStatuses = Object.entries(stats.statusCounts).filter(([status]) => !["completed", "failed", "needs-attention"].includes(status)).sort(([, left], [, right]) => right - left);
|
|
9056
9216
|
if (otherStatuses.length > 0) {
|
|
9057
|
-
lines.push(`${
|
|
9217
|
+
lines.push(`${pc6.dim("\u2502")} ${pc6.dim("other".padEnd(keyWidth + 2))} ${otherStatuses.map(([status, count]) => `${status}:${count}`).join(" ")}`);
|
|
9058
9218
|
}
|
|
9059
9219
|
lines.push("", ...formatNextSteps([
|
|
9060
9220
|
"Inspect a run: `rig run list` then `rig run show <run-id>`",
|
|
@@ -9073,7 +9233,8 @@ async function executeStats(context, args) {
|
|
|
9073
9233
|
const sinceResult = takeOption(pending, "--since");
|
|
9074
9234
|
requireNoExtraArgs(sinceResult.rest, "rig stats [show] [--since <7d|30d|ISO date>]");
|
|
9075
9235
|
const since = parseSinceOption(sinceResult.value);
|
|
9076
|
-
const
|
|
9236
|
+
const remoteStats = isRemoteConnectionSelected(context.projectRoot);
|
|
9237
|
+
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 });
|
|
9077
9238
|
if (context.outputMode === "text") {
|
|
9078
9239
|
printFormattedOutput(formatStatsReport(stats));
|
|
9079
9240
|
}
|
|
@@ -9328,7 +9489,7 @@ async function executeTask(context, args, options) {
|
|
|
9328
9489
|
pending = rawResult.rest;
|
|
9329
9490
|
const { filters, rest: remaining } = parseTaskFilters(pending);
|
|
9330
9491
|
requireNoExtraArgs(remaining, "rig task list [--raw] [--assignee <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
9331
|
-
const tasks = await listWorkspaceTasksViaServer(context, filters);
|
|
9492
|
+
const tasks = await withSpinner("Reading tasks from server\u2026", () => listWorkspaceTasksViaServer(context, filters), { outputMode: context.outputMode });
|
|
9332
9493
|
if (context.outputMode === "text") {
|
|
9333
9494
|
const renderedTasks = rawResult.value ? tasks.map((task) => summarizeTask(task, { raw: true })) : tasks.map((task) => summarizeTask(task));
|
|
9334
9495
|
printFormattedOutput(formatTaskList(renderedTasks, { raw: rawResult.value }));
|
|
@@ -9352,7 +9513,7 @@ async function executeTask(context, args, options) {
|
|
|
9352
9513
|
const taskId3 = normalizeTaskRunTaskId(taskOption.value ?? positional);
|
|
9353
9514
|
if (!taskId3)
|
|
9354
9515
|
throw new CliError("task show requires a task id.", 2, { hint: "Run `rig task list` to find ids, then `rig task show <id>`." });
|
|
9355
|
-
const task = await getWorkspaceTaskViaServer(context, taskId3);
|
|
9516
|
+
const task = await withSpinner(`Reading task ${taskId3} from server\u2026`, () => getWorkspaceTaskViaServer(context, taskId3), { outputMode: context.outputMode });
|
|
9356
9517
|
if (!task)
|
|
9357
9518
|
throw new CliError(`Task not found: ${taskId3}`, 3, { hint: "Run `rig task list` to see available tasks." });
|
|
9358
9519
|
const summary = summarizeTask(task, { raw: true });
|
|
@@ -9364,7 +9525,7 @@ async function executeTask(context, args, options) {
|
|
|
9364
9525
|
case "next": {
|
|
9365
9526
|
const { filters, rest: remaining } = parseTaskFilters(rest);
|
|
9366
9527
|
requireNoExtraArgs(remaining, "rig task next [--assignee <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
9367
|
-
const selected = await selectNextWorkspaceTaskViaServer(context, filters);
|
|
9528
|
+
const selected = await withSpinner("Selecting next ready task\u2026", () => selectNextWorkspaceTaskViaServer(context, filters), { outputMode: context.outputMode });
|
|
9368
9529
|
if (context.outputMode === "text") {
|
|
9369
9530
|
if (selected.task) {
|
|
9370
9531
|
printFormattedOutput(formatTaskCard(summarizeTask(selected.task, { raw: true }), { title: "Selected task", selected: true }));
|
|
@@ -9514,7 +9675,7 @@ async function executeTask(context, args, options) {
|
|
|
9514
9675
|
let selectedTask = null;
|
|
9515
9676
|
let selectedTaskId = normalizeTaskRunTaskId(taskResult.value) ?? positionalTaskId;
|
|
9516
9677
|
if (nextResult.value) {
|
|
9517
|
-
const selected = await selectNextWorkspaceTaskViaServer(context, filterResult.filters);
|
|
9678
|
+
const selected = await withSpinner("Selecting next ready task\u2026", () => selectNextWorkspaceTaskViaServer(context, filterResult.filters), { outputMode: context.outputMode });
|
|
9518
9679
|
selectedTask = selected.task;
|
|
9519
9680
|
selectedTaskId = selected.task ? readTaskId(selected.task) : null;
|
|
9520
9681
|
if (!selectedTaskId) {
|
|
@@ -9525,7 +9686,7 @@ async function executeTask(context, args, options) {
|
|
|
9525
9686
|
if (context.outputMode !== "text" || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
9526
9687
|
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);
|
|
9527
9688
|
}
|
|
9528
|
-
const tasks = await listWorkspaceTasksViaServer(context, filterResult.filters);
|
|
9689
|
+
const tasks = await withSpinner("Reading tasks from server\u2026", () => listWorkspaceTasksViaServer(context, filterResult.filters), { outputMode: context.outputMode });
|
|
9529
9690
|
selectedTask = await selectTaskWithTextPicker(tasks);
|
|
9530
9691
|
selectedTaskId = selectedTask ? readTaskId(selectedTask) : null;
|
|
9531
9692
|
if (!selectedTaskId) {
|
|
@@ -9535,13 +9696,13 @@ async function executeTask(context, args, options) {
|
|
|
9535
9696
|
await runProjectMainSyncPreflight(context, { disabled: skipProjectSyncResult.value });
|
|
9536
9697
|
const projectDefaults = await loadTaskRunProjectDefaults(context.projectRoot);
|
|
9537
9698
|
const runtimeAdapter = normalizeRuntimeAdapter(runtimeAdapterResult.value ?? projectDefaults.runtimeAdapter);
|
|
9538
|
-
await runFastTaskRunPreflight(context, {
|
|
9699
|
+
await withSpinner("Running task-run preflight\u2026", () => runFastTaskRunPreflight(context, {
|
|
9539
9700
|
taskId: selectedTaskId,
|
|
9540
9701
|
runtimeAdapter
|
|
9541
|
-
});
|
|
9702
|
+
}), { outputMode: context.outputMode });
|
|
9542
9703
|
const dirtyBaseline = await resolveDirtyBaselineForTaskRun(context, dirtyBaselineResult.value);
|
|
9543
9704
|
const prMode = noPrResult.value ? "off" : normalizePrMode(prResult.value) ?? projectDefaults.prMode;
|
|
9544
|
-
const submitted = await submitTaskRunViaServer(context, {
|
|
9705
|
+
const submitted = await withSpinner("Dispatching run\u2026", () => submitTaskRunViaServer(context, {
|
|
9545
9706
|
runId: context.runId,
|
|
9546
9707
|
taskId: selectedTaskId ?? undefined,
|
|
9547
9708
|
title: titleResult.value ?? undefined,
|
|
@@ -9552,7 +9713,7 @@ async function executeTask(context, args, options) {
|
|
|
9552
9713
|
initialPrompt: initialPromptResult.value ?? undefined,
|
|
9553
9714
|
baselineMode: dirtyBaseline.mode,
|
|
9554
9715
|
prMode
|
|
9555
|
-
});
|
|
9716
|
+
}), { outputMode: context.outputMode });
|
|
9556
9717
|
let attachDetails = null;
|
|
9557
9718
|
if (!detachResult.value && context.outputMode === "text") {
|
|
9558
9719
|
printFormattedOutput(formatSubmittedRun({
|
|
@@ -11730,7 +11891,7 @@ async function executeSetup(context, args) {
|
|
|
11730
11891
|
case "check":
|
|
11731
11892
|
requireNoExtraArgs(rest, `rig setup ${command}`);
|
|
11732
11893
|
{
|
|
11733
|
-
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
|
|
11894
|
+
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot, context.outputMode));
|
|
11734
11895
|
return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
|
|
11735
11896
|
}
|
|
11736
11897
|
case "setup":
|
|
@@ -11739,7 +11900,7 @@ async function executeSetup(context, args) {
|
|
|
11739
11900
|
return { ok: true, group: "setup", command };
|
|
11740
11901
|
case "preflight":
|
|
11741
11902
|
requireNoExtraArgs(rest, "rig setup preflight");
|
|
11742
|
-
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
|
|
11903
|
+
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot, context.outputMode));
|
|
11743
11904
|
return { ok: true, group: "setup", command };
|
|
11744
11905
|
default:
|
|
11745
11906
|
throw new CliError(`Unknown setup command: ${command}`, 1, { hint: "Run `rig setup --help` \u2014 commands are bootstrap|check|preflight." });
|
|
@@ -11760,8 +11921,8 @@ function runSetupInit(projectRoot) {
|
|
|
11760
11921
|
}
|
|
11761
11922
|
console.log("Harness directories ready.");
|
|
11762
11923
|
}
|
|
11763
|
-
async function runSetupCheck(projectRoot) {
|
|
11764
|
-
const doctorChecks = await runRigDoctorChecks({ projectRoot });
|
|
11924
|
+
async function runSetupCheck(projectRoot, outputMode = "text") {
|
|
11925
|
+
const doctorChecks = await withSpinner("Running setup checks\u2026", (update) => runRigDoctorChecks({ projectRoot, onProgress: update }), { outputMode });
|
|
11765
11926
|
console.log(formatDoctorChecks(doctorChecks));
|
|
11766
11927
|
const failures = countDoctorFailures(doctorChecks);
|
|
11767
11928
|
if (failures > 0) {
|
|
@@ -11769,8 +11930,8 @@ async function runSetupCheck(projectRoot) {
|
|
|
11769
11930
|
}
|
|
11770
11931
|
return doctorChecks;
|
|
11771
11932
|
}
|
|
11772
|
-
async function runSetupPreflight(projectRoot) {
|
|
11773
|
-
await runSetupCheck(projectRoot);
|
|
11933
|
+
async function runSetupPreflight(projectRoot, outputMode = "text") {
|
|
11934
|
+
await runSetupCheck(projectRoot, outputMode);
|
|
11774
11935
|
const validationRoot = resolve24(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
|
|
11775
11936
|
if (existsSync16(validationRoot)) {
|
|
11776
11937
|
const validators = readdirSync3(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|