@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/index.js
CHANGED
|
@@ -2929,6 +2929,15 @@ import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
|
|
|
2929
2929
|
import { resolve as resolve11 } from "path";
|
|
2930
2930
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
2931
2931
|
var scopedGitHubBearerTokens = new Map;
|
|
2932
|
+
var serverPhaseListener = null;
|
|
2933
|
+
function setServerPhaseListener(listener) {
|
|
2934
|
+
const previous = serverPhaseListener;
|
|
2935
|
+
serverPhaseListener = listener;
|
|
2936
|
+
return previous;
|
|
2937
|
+
}
|
|
2938
|
+
function reportServerPhase(label) {
|
|
2939
|
+
serverPhaseListener?.(label);
|
|
2940
|
+
}
|
|
2932
2941
|
function cleanToken(value) {
|
|
2933
2942
|
const trimmed = value?.trim();
|
|
2934
2943
|
return trimmed ? trimmed : null;
|
|
@@ -2975,6 +2984,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
2975
2984
|
try {
|
|
2976
2985
|
const selected = resolveSelectedConnection(projectRoot);
|
|
2977
2986
|
if (selected?.connection.kind === "remote") {
|
|
2987
|
+
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
2978
2988
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
2979
2989
|
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
2980
2990
|
return {
|
|
@@ -2984,6 +2994,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
2984
2994
|
serverProjectRoot
|
|
2985
2995
|
};
|
|
2986
2996
|
}
|
|
2997
|
+
reportServerPhase("Starting local Rig server\u2026");
|
|
2987
2998
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
2988
2999
|
return {
|
|
2989
3000
|
baseUrl: connection.baseUrl,
|
|
@@ -3100,6 +3111,7 @@ async function requestServerJson(context, pathname, init = {}) {
|
|
|
3100
3111
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
3101
3112
|
if (server.serverProjectRoot)
|
|
3102
3113
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
3114
|
+
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
3103
3115
|
let response;
|
|
3104
3116
|
try {
|
|
3105
3117
|
response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
@@ -4620,6 +4632,127 @@ function formatConnectionStatus(selected, connections) {
|
|
|
4620
4632
|
`);
|
|
4621
4633
|
}
|
|
4622
4634
|
|
|
4635
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
4636
|
+
import pc4 from "picocolors";
|
|
4637
|
+
|
|
4638
|
+
// packages/cli/src/commands/_spinner.ts
|
|
4639
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
4640
|
+
function createTtySpinner(input) {
|
|
4641
|
+
const output = input.output ?? process.stdout;
|
|
4642
|
+
const isTty = output.isTTY === true;
|
|
4643
|
+
const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
|
|
4644
|
+
let label = input.label;
|
|
4645
|
+
let frame = 0;
|
|
4646
|
+
let paused = false;
|
|
4647
|
+
let stopped = false;
|
|
4648
|
+
let lastPrintedLabel = "";
|
|
4649
|
+
const render = () => {
|
|
4650
|
+
if (stopped || paused)
|
|
4651
|
+
return;
|
|
4652
|
+
if (!isTty) {
|
|
4653
|
+
if (label !== lastPrintedLabel) {
|
|
4654
|
+
output.write(`${label}
|
|
4655
|
+
`);
|
|
4656
|
+
lastPrintedLabel = label;
|
|
4657
|
+
}
|
|
4658
|
+
return;
|
|
4659
|
+
}
|
|
4660
|
+
frame = (frame + 1) % frames.length;
|
|
4661
|
+
const glyph = frames[frame] ?? frames[0] ?? "";
|
|
4662
|
+
output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
|
|
4663
|
+
};
|
|
4664
|
+
const clearLine = () => {
|
|
4665
|
+
if (isTty)
|
|
4666
|
+
output.write("\r\x1B[2K");
|
|
4667
|
+
};
|
|
4668
|
+
render();
|
|
4669
|
+
const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
|
|
4670
|
+
return {
|
|
4671
|
+
setLabel(next) {
|
|
4672
|
+
label = next;
|
|
4673
|
+
render();
|
|
4674
|
+
},
|
|
4675
|
+
pause() {
|
|
4676
|
+
paused = true;
|
|
4677
|
+
clearLine();
|
|
4678
|
+
},
|
|
4679
|
+
resume() {
|
|
4680
|
+
if (stopped)
|
|
4681
|
+
return;
|
|
4682
|
+
paused = false;
|
|
4683
|
+
render();
|
|
4684
|
+
},
|
|
4685
|
+
stop(finalLine) {
|
|
4686
|
+
if (stopped)
|
|
4687
|
+
return;
|
|
4688
|
+
stopped = true;
|
|
4689
|
+
if (timer)
|
|
4690
|
+
clearInterval(timer);
|
|
4691
|
+
clearLine();
|
|
4692
|
+
if (finalLine)
|
|
4693
|
+
output.write(`${finalLine}
|
|
4694
|
+
`);
|
|
4695
|
+
}
|
|
4696
|
+
};
|
|
4697
|
+
}
|
|
4698
|
+
|
|
4699
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
4700
|
+
var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
|
|
4701
|
+
var DONE_SYMBOL = pc4.green("\u25C7");
|
|
4702
|
+
var FAIL_SYMBOL = pc4.red("\u25A0");
|
|
4703
|
+
var activeUpdate = null;
|
|
4704
|
+
async function withSpinner(label, work, options = {}) {
|
|
4705
|
+
if (options.outputMode === "json") {
|
|
4706
|
+
return work(() => {});
|
|
4707
|
+
}
|
|
4708
|
+
if (activeUpdate) {
|
|
4709
|
+
const outer = activeUpdate;
|
|
4710
|
+
outer(label);
|
|
4711
|
+
return work(outer);
|
|
4712
|
+
}
|
|
4713
|
+
const output = options.output ?? process.stderr;
|
|
4714
|
+
const isTty = output.isTTY === true;
|
|
4715
|
+
let lastLabel = label;
|
|
4716
|
+
if (!isTty) {
|
|
4717
|
+
output.write(`${label}
|
|
4718
|
+
`);
|
|
4719
|
+
const update2 = (next) => {
|
|
4720
|
+
lastLabel = next;
|
|
4721
|
+
};
|
|
4722
|
+
activeUpdate = update2;
|
|
4723
|
+
const previousListener2 = setServerPhaseListener(update2);
|
|
4724
|
+
try {
|
|
4725
|
+
return await work(update2);
|
|
4726
|
+
} finally {
|
|
4727
|
+
activeUpdate = null;
|
|
4728
|
+
setServerPhaseListener(previousListener2);
|
|
4729
|
+
}
|
|
4730
|
+
}
|
|
4731
|
+
const spinner2 = createTtySpinner({
|
|
4732
|
+
label,
|
|
4733
|
+
output,
|
|
4734
|
+
frames: CLACK_SPINNER_FRAMES,
|
|
4735
|
+
styleFrame: (frame) => pc4.magenta(frame)
|
|
4736
|
+
});
|
|
4737
|
+
const update = (next) => {
|
|
4738
|
+
lastLabel = next;
|
|
4739
|
+
spinner2.setLabel(next);
|
|
4740
|
+
};
|
|
4741
|
+
activeUpdate = update;
|
|
4742
|
+
const previousListener = setServerPhaseListener(update);
|
|
4743
|
+
try {
|
|
4744
|
+
const result = await work(update);
|
|
4745
|
+
spinner2.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
|
|
4746
|
+
return result;
|
|
4747
|
+
} catch (error) {
|
|
4748
|
+
spinner2.stop(`${FAIL_SYMBOL} ${lastLabel}`);
|
|
4749
|
+
throw error;
|
|
4750
|
+
} finally {
|
|
4751
|
+
activeUpdate = null;
|
|
4752
|
+
setServerPhaseListener(previousListener);
|
|
4753
|
+
}
|
|
4754
|
+
}
|
|
4755
|
+
|
|
4623
4756
|
// packages/cli/src/commands/inbox.ts
|
|
4624
4757
|
async function listInboxRecords(context, kind, filters) {
|
|
4625
4758
|
const params = new URLSearchParams;
|
|
@@ -4724,7 +4857,7 @@ async function executeInbox(context, args) {
|
|
|
4724
4857
|
const task = takeOption(pending, "--task");
|
|
4725
4858
|
pending = task.rest;
|
|
4726
4859
|
requireNoExtraArgs(pending, "rig inbox approvals [--run <id>] [--task <id>]");
|
|
4727
|
-
const approvals = await listInboxRecords(context, "approvals", { run: run.value, task: task.value });
|
|
4860
|
+
const approvals = await withSpinner("Reading approvals from server\u2026", () => listInboxRecords(context, "approvals", { run: run.value, task: task.value }), { outputMode: context.outputMode });
|
|
4728
4861
|
renderList(context, "approvals", approvals);
|
|
4729
4862
|
return { ok: true, group: "inbox", command, details: { approvals } };
|
|
4730
4863
|
}
|
|
@@ -4735,7 +4868,7 @@ async function executeInbox(context, args) {
|
|
|
4735
4868
|
const task = takeOption(pending, "--task");
|
|
4736
4869
|
pending = task.rest;
|
|
4737
4870
|
requireNoExtraArgs(pending, "rig inbox inputs [--run <id>] [--task <id>]");
|
|
4738
|
-
const requests = await listInboxRecords(context, "inputs", { run: run.value, task: task.value });
|
|
4871
|
+
const requests = await withSpinner("Reading input requests from server\u2026", () => listInboxRecords(context, "inputs", { run: run.value, task: task.value }), { outputMode: context.outputMode });
|
|
4739
4872
|
renderList(context, "inputs", requests);
|
|
4740
4873
|
return { ok: true, group: "inbox", command, details: { requests } };
|
|
4741
4874
|
}
|
|
@@ -4756,7 +4889,7 @@ async function executeInbox(context, args) {
|
|
|
4756
4889
|
if (decision.value !== "approve" && decision.value !== "reject") {
|
|
4757
4890
|
throw new CliError("decision must be approve or reject.", 1, { hint: "Re-run as `rig inbox approve --run <id> --request <id> --decision approve|reject`." });
|
|
4758
4891
|
}
|
|
4759
|
-
const result = await requestServerJson(context, "/api/inbox/approvals/resolve", {
|
|
4892
|
+
const result = await withSpinner(`Resolving approval ${request.value}\u2026`, () => requestServerJson(context, "/api/inbox/approvals/resolve", {
|
|
4760
4893
|
method: "POST",
|
|
4761
4894
|
headers: { "content-type": "application/json" },
|
|
4762
4895
|
body: JSON.stringify({
|
|
@@ -4765,7 +4898,7 @@ async function executeInbox(context, args) {
|
|
|
4765
4898
|
decision: decision.value,
|
|
4766
4899
|
note: note4.value ?? null
|
|
4767
4900
|
})
|
|
4768
|
-
});
|
|
4901
|
+
}), { outputMode: context.outputMode });
|
|
4769
4902
|
return { ok: true, group: "inbox", command, details: { result } };
|
|
4770
4903
|
}
|
|
4771
4904
|
case "respond": {
|
|
@@ -4799,7 +4932,7 @@ async function executeInbox(context, args) {
|
|
|
4799
4932
|
const [key, ...restValue] = entry.split("=");
|
|
4800
4933
|
return [key, restValue.join("=")];
|
|
4801
4934
|
}));
|
|
4802
|
-
const result = await requestServerJson(context, "/api/inbox/inputs/respond", {
|
|
4935
|
+
const result = await withSpinner(`Sending response for ${request.value}\u2026`, () => requestServerJson(context, "/api/inbox/inputs/respond", {
|
|
4803
4936
|
method: "POST",
|
|
4804
4937
|
headers: { "content-type": "application/json" },
|
|
4805
4938
|
body: JSON.stringify({
|
|
@@ -4807,7 +4940,7 @@ async function executeInbox(context, args) {
|
|
|
4807
4940
|
requestId: request.value,
|
|
4808
4941
|
answers: parsedAnswers
|
|
4809
4942
|
})
|
|
4810
|
-
});
|
|
4943
|
+
}), { outputMode: context.outputMode });
|
|
4811
4944
|
return { ok: true, group: "inbox", command, details: { result } };
|
|
4812
4945
|
}
|
|
4813
4946
|
case "watch": {
|
|
@@ -5224,7 +5357,10 @@ async function runRigDoctorChecks(options) {
|
|
|
5224
5357
|
const bunVersion = options.bunVersion ?? Bun.version;
|
|
5225
5358
|
const request = options.requestJson ?? ((pathname, init) => requestServerJson({ projectRoot }, pathname, init));
|
|
5226
5359
|
const loadConfig = options.loadConfig ?? loadRigConfigOrNull;
|
|
5360
|
+
const progress = options.onProgress ?? (() => {});
|
|
5361
|
+
progress("Checking local toolchain\u2026");
|
|
5227
5362
|
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`)."));
|
|
5363
|
+
progress("Loading rig.config\u2026");
|
|
5228
5364
|
const loadedConfig = await loadConfig(projectRoot).catch(() => null);
|
|
5229
5365
|
const config = loadedConfig ?? loadFallbackConfig(projectRoot);
|
|
5230
5366
|
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync11(resolve17(projectRoot, name)));
|
|
@@ -5243,6 +5379,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5243
5379
|
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));
|
|
5244
5380
|
let server = null;
|
|
5245
5381
|
try {
|
|
5382
|
+
progress("Connecting to the selected Rig server\u2026");
|
|
5246
5383
|
server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
|
|
5247
5384
|
checks.push(check("server", "Rig server reachable", "pass", `${server.connectionKind} ${server.baseUrl}`));
|
|
5248
5385
|
} catch (error) {
|
|
@@ -5250,18 +5387,21 @@ async function runRigDoctorChecks(options) {
|
|
|
5250
5387
|
}
|
|
5251
5388
|
if (server || options.requestJson) {
|
|
5252
5389
|
try {
|
|
5390
|
+
progress("Checking server status\u2026");
|
|
5253
5391
|
const status = await request("/api/server/status");
|
|
5254
5392
|
checks.push(check("server-status", "server project status", "pass", JSON.stringify(status).slice(0, 180)));
|
|
5255
5393
|
} catch (error) {
|
|
5256
5394
|
checks.push(check("server-status", "server project status", "fail", errorMessage(error), "Run `rig doctor` after the selected server is reachable."));
|
|
5257
5395
|
}
|
|
5258
5396
|
try {
|
|
5397
|
+
progress("Checking GitHub auth\u2026");
|
|
5259
5398
|
const auth = await request("/api/github/auth/status");
|
|
5260
5399
|
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>`."));
|
|
5261
5400
|
} catch (error) {
|
|
5262
5401
|
checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig and ensure the server exposes auth status."));
|
|
5263
5402
|
}
|
|
5264
5403
|
try {
|
|
5404
|
+
progress("Checking GitHub repo permissions\u2026");
|
|
5265
5405
|
const permissions = await request("/api/github/repo/permissions");
|
|
5266
5406
|
const allowed = permissionAllowsPr2(permissions);
|
|
5267
5407
|
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."));
|
|
@@ -5269,6 +5409,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5269
5409
|
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."));
|
|
5270
5410
|
}
|
|
5271
5411
|
try {
|
|
5412
|
+
progress("Checking GitHub issue labels\u2026");
|
|
5272
5413
|
const labels = await request("/api/workspace/task-labels");
|
|
5273
5414
|
const ready = labelsReady(labels);
|
|
5274
5415
|
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."));
|
|
@@ -5276,6 +5417,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5276
5417
|
checks.push(check("task-labels", "GitHub issue labels", "warn", errorMessage(error), "Run `rig init`/`rig doctor` after label setup is wired on the server."));
|
|
5277
5418
|
}
|
|
5278
5419
|
try {
|
|
5420
|
+
progress("Checking task projection\u2026");
|
|
5279
5421
|
const projection = await request("/api/workspace/task-projection");
|
|
5280
5422
|
checks.push(check("task-projection", "task projection", "pass", JSON.stringify(projection).slice(0, 180)));
|
|
5281
5423
|
} catch (error) {
|
|
@@ -5284,6 +5426,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5284
5426
|
const slug = projectStatusSlug(projectRoot, config);
|
|
5285
5427
|
if (slug) {
|
|
5286
5428
|
try {
|
|
5429
|
+
progress("Checking server project checkout\u2026");
|
|
5287
5430
|
const project = await request(`/api/projects/${encodeURIComponent(slug)}`);
|
|
5288
5431
|
checks.push(check("remote-checkout", "server project checkout", "pass", JSON.stringify(project).slice(0, 180)));
|
|
5289
5432
|
} catch (error) {
|
|
@@ -5298,6 +5441,7 @@ async function runRigDoctorChecks(options) {
|
|
|
5298
5441
|
}
|
|
5299
5442
|
checks.push(githubProjectsCheck(config));
|
|
5300
5443
|
checks.push(prMergeCheck(config));
|
|
5444
|
+
progress("Checking Pi installation\u2026");
|
|
5301
5445
|
const piChecks = await (options.piChecks ?? (() => buildPiSetupChecks()))().catch((error) => [{
|
|
5302
5446
|
ok: false,
|
|
5303
5447
|
label: "pi/pi-rig checks",
|
|
@@ -6220,7 +6364,7 @@ async function executeGithub(context, args) {
|
|
|
6220
6364
|
case "status": {
|
|
6221
6365
|
if (rest.length > 0)
|
|
6222
6366
|
throw new CliError("Usage: rig github auth status", 1);
|
|
6223
|
-
const status = await getGitHubAuthStatusViaServer(context);
|
|
6367
|
+
const status = await withSpinner("Checking GitHub auth on the server\u2026", () => getGitHubAuthStatusViaServer(context), { outputMode: context.outputMode });
|
|
6224
6368
|
printPayload(context, status, `GitHub auth: ${status.authenticated ? "authenticated" : "unauthenticated"}`);
|
|
6225
6369
|
return { ok: true, group: "github", command: "auth status", details: status };
|
|
6226
6370
|
}
|
|
@@ -6231,14 +6375,15 @@ async function executeGithub(context, args) {
|
|
|
6231
6375
|
const token = parsed.value?.trim();
|
|
6232
6376
|
if (!token)
|
|
6233
6377
|
throw new CliError("Missing --token value.", 1, { hint: "Re-run as `rig github auth token --token <token>`." });
|
|
6234
|
-
const result = await postGitHubTokenViaServer(context, token);
|
|
6378
|
+
const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token), { outputMode: context.outputMode });
|
|
6235
6379
|
printPayload(context, result, "GitHub token stored on the selected Rig server.");
|
|
6236
6380
|
return { ok: true, group: "github", command: "auth token", details: result };
|
|
6237
6381
|
}
|
|
6238
6382
|
case "import-gh": {
|
|
6239
6383
|
if (rest.length > 0)
|
|
6240
6384
|
throw new CliError("Usage: rig github auth import-gh", 1);
|
|
6241
|
-
const
|
|
6385
|
+
const importedToken = readGhToken();
|
|
6386
|
+
const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken), { outputMode: context.outputMode });
|
|
6242
6387
|
printPayload(context, result, "GitHub token imported from gh and stored on the selected Rig server.");
|
|
6243
6388
|
return { ok: true, group: "github", command: "auth import-gh", details: result };
|
|
6244
6389
|
}
|
|
@@ -6251,7 +6396,7 @@ async function executeGithub(context, args) {
|
|
|
6251
6396
|
init_runner();
|
|
6252
6397
|
async function executeDoctor(context, args) {
|
|
6253
6398
|
requireNoExtraArgs(args, "rig doctor");
|
|
6254
|
-
const checks = await runRigDoctorChecks({ projectRoot: context.projectRoot });
|
|
6399
|
+
const checks = await withSpinner("Running doctor checks\u2026", (update) => runRigDoctorChecks({ projectRoot: context.projectRoot, onProgress: update }), { outputMode: context.outputMode });
|
|
6255
6400
|
if (context.outputMode === "text") {
|
|
6256
6401
|
console.log(formatDoctorChecks(checks));
|
|
6257
6402
|
}
|
|
@@ -6558,13 +6703,19 @@ async function executeInspect(context, args) {
|
|
|
6558
6703
|
const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
|
|
6559
6704
|
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];
|
|
6560
6705
|
if (!latestRun) {
|
|
6561
|
-
const
|
|
6562
|
-
|
|
6563
|
-
|
|
6706
|
+
const fallback = await withSpinner(`Finding runs for ${requiredTask} on the server\u2026`, async (update) => {
|
|
6707
|
+
const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
|
|
6708
|
+
const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
|
|
6709
|
+
if (!serverRun || typeof serverRun.runId !== "string")
|
|
6710
|
+
return null;
|
|
6711
|
+
update(`Reading logs for run ${serverRun.runId}\u2026`);
|
|
6712
|
+
const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
|
|
6713
|
+
return { runId: serverRun.runId, page };
|
|
6714
|
+
}, { outputMode: context.outputMode });
|
|
6715
|
+
if (!fallback) {
|
|
6564
6716
|
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`." });
|
|
6565
6717
|
}
|
|
6566
|
-
const
|
|
6567
|
-
const entries = Array.isArray(page.entries) ? page.entries : [];
|
|
6718
|
+
const entries = Array.isArray(fallback.page.entries) ? fallback.page.entries : [];
|
|
6568
6719
|
if (context.outputMode === "text") {
|
|
6569
6720
|
for (const entry of entries) {
|
|
6570
6721
|
const record = entry && typeof entry === "object" ? entry : {};
|
|
@@ -6573,9 +6724,9 @@ async function executeInspect(context, args) {
|
|
|
6573
6724
|
console.log([title, detail].filter(Boolean).join(" \u2014 "));
|
|
6574
6725
|
}
|
|
6575
6726
|
if (entries.length === 0)
|
|
6576
|
-
console.log(`(no log entries for run ${
|
|
6727
|
+
console.log(`(no log entries for run ${fallback.runId})`);
|
|
6577
6728
|
}
|
|
6578
|
-
return { ok: true, group: "inspect", command, details: { task: requiredTask, runId:
|
|
6729
|
+
return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: fallback.runId, source: "server", entries } };
|
|
6579
6730
|
}
|
|
6580
6731
|
const logsPath = resolve20(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
|
|
6581
6732
|
if (!existsSync13(logsPath)) {
|
|
@@ -6633,7 +6784,7 @@ async function executeInspect(context, args) {
|
|
|
6633
6784
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
6634
6785
|
requireNoExtraArgs(remaining, "rig inspect diff [--task <task-id>]");
|
|
6635
6786
|
if (task) {
|
|
6636
|
-
const files = changedFilesForTask(context.projectRoot, task, false);
|
|
6787
|
+
const files = await withSpinner(`Computing changed files for ${task}\u2026`, async () => changedFilesForTask(context.projectRoot, task, false), { outputMode: context.outputMode });
|
|
6637
6788
|
for (const file of files) {
|
|
6638
6789
|
console.log(file);
|
|
6639
6790
|
}
|
|
@@ -7721,7 +7872,12 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
7721
7872
|
};
|
|
7722
7873
|
let detached = false;
|
|
7723
7874
|
try {
|
|
7724
|
-
await runPiMain([
|
|
7875
|
+
await runPiMain([
|
|
7876
|
+
"--no-extensions",
|
|
7877
|
+
"--no-skills",
|
|
7878
|
+
"--no-prompt-templates",
|
|
7879
|
+
"--no-context-files"
|
|
7880
|
+
], {
|
|
7725
7881
|
extensionFactories: [piRigExtensionFactory]
|
|
7726
7882
|
});
|
|
7727
7883
|
detached = true;
|
|
@@ -7786,8 +7942,9 @@ async function readOperatorSnapshot(context, runId, options = {}) {
|
|
|
7786
7942
|
}
|
|
7787
7943
|
async function attachRunOperatorView(context, input) {
|
|
7788
7944
|
let steered = false;
|
|
7789
|
-
|
|
7790
|
-
|
|
7945
|
+
const attachMessage = input.message?.trim();
|
|
7946
|
+
if (attachMessage) {
|
|
7947
|
+
await withSpinner("Queueing steering message\u2026", () => sendRunPiPromptViaServer(context, input.runId, attachMessage, "steer").catch(() => steerRunViaServer(context, input.runId, attachMessage)), { outputMode: context.outputMode });
|
|
7791
7948
|
steered = true;
|
|
7792
7949
|
}
|
|
7793
7950
|
if (input.follow && !input.once && input.interactive !== false && context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
@@ -7797,7 +7954,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
7797
7954
|
});
|
|
7798
7955
|
}
|
|
7799
7956
|
const surface = createOperatorSurface({ interactive: input.interactive !== false });
|
|
7800
|
-
let snapshot = await readOperatorSnapshot(context, input.runId);
|
|
7957
|
+
let snapshot = await withSpinner(`Connecting to run ${input.runId}\u2026`, () => readOperatorSnapshot(context, input.runId), { outputMode: context.outputMode });
|
|
7801
7958
|
if (context.outputMode === "text") {
|
|
7802
7959
|
surface.renderSnapshot(snapshot);
|
|
7803
7960
|
surface.renderTimeline(snapshot.timeline);
|
|
@@ -7928,7 +8085,7 @@ async function executeRun(context, args) {
|
|
|
7928
8085
|
switch (command) {
|
|
7929
8086
|
case "list": {
|
|
7930
8087
|
requireNoExtraArgs(rest, "rig run list");
|
|
7931
|
-
const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
|
|
8088
|
+
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 });
|
|
7932
8089
|
if (context.outputMode === "text") {
|
|
7933
8090
|
printFormattedOutput(formatRunList(runs, { source }));
|
|
7934
8091
|
await printPendingInboxFooter(context);
|
|
@@ -8001,7 +8158,7 @@ async function executeRun(context, args) {
|
|
|
8001
8158
|
if (!runId) {
|
|
8002
8159
|
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>`." });
|
|
8003
8160
|
}
|
|
8004
|
-
const record = readAuthorityRun5(context.projectRoot, runId) ?? normalizeRemoteRunDetails(await getRunDetailsViaServer(context, runId).catch(() => ({})));
|
|
8161
|
+
const record = readAuthorityRun5(context.projectRoot, runId) ?? normalizeRemoteRunDetails(await withSpinner(`Reading run ${runId} from server\u2026`, () => getRunDetailsViaServer(context, runId).catch(() => ({})), { outputMode: context.outputMode }));
|
|
8005
8162
|
if (!record) {
|
|
8006
8163
|
throw new CliError(`Run not found: ${runId}`, 2, { hint: "Run `rig run list` to see recorded runs." });
|
|
8007
8164
|
}
|
|
@@ -8022,7 +8179,8 @@ async function executeRun(context, args) {
|
|
|
8022
8179
|
}
|
|
8023
8180
|
const renderer = createPiRunStreamRenderer();
|
|
8024
8181
|
let cursor = null;
|
|
8025
|
-
const
|
|
8182
|
+
const timelineRunId = run.value;
|
|
8183
|
+
const page = await withSpinner(`Reading timeline for ${timelineRunId}\u2026`, () => getRunTimelineViaServer(context, timelineRunId, { limit: 500 }), { outputMode: context.outputMode });
|
|
8026
8184
|
const events = Array.isArray(page.entries) ? page.entries.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))) : [];
|
|
8027
8185
|
cursor = typeof page.nextCursor === "string" ? page.nextCursor : null;
|
|
8028
8186
|
if (context.outputMode === "text") {
|
|
@@ -8099,8 +8257,9 @@ async function executeRun(context, args) {
|
|
|
8099
8257
|
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`." });
|
|
8100
8258
|
}
|
|
8101
8259
|
let steered = false;
|
|
8102
|
-
|
|
8103
|
-
|
|
8260
|
+
const steerMessage = messageOption.value?.trim();
|
|
8261
|
+
if (steerMessage) {
|
|
8262
|
+
await withSpinner("Queueing steering message\u2026", () => steerRunViaServer(context, runId, steerMessage), { outputMode: context.outputMode });
|
|
8104
8263
|
steered = true;
|
|
8105
8264
|
}
|
|
8106
8265
|
const attached = await attachRunOperatorView(context, {
|
|
@@ -8120,7 +8279,7 @@ async function executeRun(context, args) {
|
|
|
8120
8279
|
}
|
|
8121
8280
|
return { ok: true, group: "run", command };
|
|
8122
8281
|
}
|
|
8123
|
-
const summary = isRemoteConnectionSelected(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
|
|
8282
|
+
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);
|
|
8124
8283
|
const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
8125
8284
|
const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
8126
8285
|
if (context.outputMode === "text") {
|
|
@@ -8255,7 +8414,8 @@ async function executeRun(context, args) {
|
|
|
8255
8414
|
}
|
|
8256
8415
|
return { ok: true, group: "run", command, details: { runId, dryRun: true } };
|
|
8257
8416
|
}
|
|
8258
|
-
|
|
8417
|
+
const trimmedMessage = message2.trim();
|
|
8418
|
+
await withSpinner("Queueing steering message\u2026", () => steerRunViaServer(context, runId, trimmedMessage), { outputMode: context.outputMode });
|
|
8259
8419
|
if (context.outputMode === "text") {
|
|
8260
8420
|
console.log(`Steering message queued for ${runId}.`);
|
|
8261
8421
|
}
|
|
@@ -8276,7 +8436,7 @@ async function executeRun(context, args) {
|
|
|
8276
8436
|
};
|
|
8277
8437
|
}
|
|
8278
8438
|
if (runId) {
|
|
8279
|
-
const stopped = await stopRunViaServer(context, runId);
|
|
8439
|
+
const stopped = await withSpinner(`Requesting stop for ${runId}\u2026`, () => stopRunViaServer(context, runId), { outputMode: context.outputMode });
|
|
8280
8440
|
if (context.outputMode === "text")
|
|
8281
8441
|
console.log(`Stop requested: ${runId}`);
|
|
8282
8442
|
return { ok: true, group: "run", command, details: stopped };
|
|
@@ -8522,12 +8682,12 @@ async function executeServer(context, args, options) {
|
|
|
8522
8682
|
|
|
8523
8683
|
// packages/cli/src/commands/stats.ts
|
|
8524
8684
|
init_runner();
|
|
8525
|
-
import
|
|
8685
|
+
import pc6 from "picocolors";
|
|
8526
8686
|
import { computeRigStats } from "@rig/runtime/control-plane/native/run-stats";
|
|
8527
8687
|
|
|
8528
8688
|
// packages/cli/src/commands/_help-catalog.ts
|
|
8529
8689
|
import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@clack/prompts";
|
|
8530
|
-
import
|
|
8690
|
+
import pc5 from "picocolors";
|
|
8531
8691
|
var TOP_LEVEL_SECTIONS = [
|
|
8532
8692
|
{
|
|
8533
8693
|
title: "Start here",
|
|
@@ -8815,13 +8975,13 @@ var ADVANCED_COMMANDS = [
|
|
|
8815
8975
|
];
|
|
8816
8976
|
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
8817
8977
|
function heading(title) {
|
|
8818
|
-
return
|
|
8978
|
+
return pc5.bold(pc5.cyan(title));
|
|
8819
8979
|
}
|
|
8820
8980
|
function renderRigBanner(version) {
|
|
8821
|
-
const m = (s) =>
|
|
8822
|
-
const c = (s) =>
|
|
8823
|
-
const y = (s) =>
|
|
8824
|
-
const d = (s) =>
|
|
8981
|
+
const m = (s) => pc5.bold(pc5.magenta(s));
|
|
8982
|
+
const c = (s) => pc5.bold(pc5.cyan(s));
|
|
8983
|
+
const y = (s) => pc5.yellow(s);
|
|
8984
|
+
const d = (s) => pc5.dim(s);
|
|
8825
8985
|
const lines = [
|
|
8826
8986
|
m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
|
|
8827
8987
|
m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
|
|
@@ -8830,7 +8990,7 @@ function renderRigBanner(version) {
|
|
|
8830
8990
|
y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
|
|
8831
8991
|
y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
|
|
8832
8992
|
"",
|
|
8833
|
-
` ${c("\u25E2\u25E4")} ${
|
|
8993
|
+
` ${c("\u25E2\u25E4")} ${pc5.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
|
|
8834
8994
|
version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
|
|
8835
8995
|
];
|
|
8836
8996
|
return lines.join(`
|
|
@@ -8838,7 +8998,7 @@ function renderRigBanner(version) {
|
|
|
8838
8998
|
}
|
|
8839
8999
|
function commandLine(command, description) {
|
|
8840
9000
|
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
8841
|
-
return `${
|
|
9001
|
+
return `${pc5.dim("\u2502")} ${pc5.bold(commandColumn)} ${description}`;
|
|
8842
9002
|
}
|
|
8843
9003
|
function renderCommandBlock(commands) {
|
|
8844
9004
|
return commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
@@ -8848,37 +9008,37 @@ function renderGroup(group) {
|
|
|
8848
9008
|
const lines = [
|
|
8849
9009
|
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
8850
9010
|
"",
|
|
8851
|
-
|
|
9011
|
+
pc5.bold("Usage"),
|
|
8852
9012
|
...group.usage.map((line) => ` ${line}`),
|
|
8853
9013
|
"",
|
|
8854
|
-
|
|
9014
|
+
pc5.bold("Commands"),
|
|
8855
9015
|
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
8856
9016
|
];
|
|
8857
9017
|
if (group.examples?.length) {
|
|
8858
|
-
lines.push("",
|
|
9018
|
+
lines.push("", pc5.bold("Examples"), ...group.examples.map((line) => ` ${pc5.dim("$")} ${line}`));
|
|
8859
9019
|
}
|
|
8860
9020
|
if (group.next?.length) {
|
|
8861
|
-
lines.push("",
|
|
9021
|
+
lines.push("", pc5.bold("Next steps"), ...group.next.map((line) => ` ${pc5.dim("\u203A")} ${line}`));
|
|
8862
9022
|
}
|
|
8863
9023
|
if (group.advanced?.length) {
|
|
8864
|
-
lines.push("",
|
|
9024
|
+
lines.push("", pc5.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc5.dim("\u203A")} ${line}`));
|
|
8865
9025
|
}
|
|
8866
9026
|
return lines.join(`
|
|
8867
9027
|
`);
|
|
8868
9028
|
}
|
|
8869
9029
|
function renderTopLevelHelp() {
|
|
8870
9030
|
return [
|
|
8871
|
-
`${heading("rig")} ${
|
|
8872
|
-
|
|
9031
|
+
`${heading("rig")} ${pc5.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
9032
|
+
pc5.dim("Current path: select a server, choose a task, submit a run, attach with native Pi, clear inbox gates."),
|
|
8873
9033
|
"",
|
|
8874
9034
|
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
8875
|
-
`${
|
|
9035
|
+
`${pc5.bold(pc5.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc5.dim(section.subtitle)}`,
|
|
8876
9036
|
renderCommandBlock(section.commands),
|
|
8877
9037
|
""
|
|
8878
9038
|
]),
|
|
8879
|
-
|
|
9039
|
+
pc5.dim("More: `rig help --advanced` for dev/compatibility commands; `rig <group> --help` for rich per-group help; `rig --version` for the installed version."),
|
|
8880
9040
|
"",
|
|
8881
|
-
|
|
9041
|
+
pc5.bold("Global options"),
|
|
8882
9042
|
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
8883
9043
|
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
8884
9044
|
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
@@ -8889,16 +9049,16 @@ function renderAdvancedHelp() {
|
|
|
8889
9049
|
return [
|
|
8890
9050
|
`${heading("rig advanced")} \u2014 compatibility, diagnostics, and internal surfaces`,
|
|
8891
9051
|
"",
|
|
8892
|
-
|
|
9052
|
+
pc5.bold("Primary groups"),
|
|
8893
9053
|
" init, server, task, run, inbox, repo, plugin, inspect, stats, doctor, github",
|
|
8894
9054
|
"",
|
|
8895
|
-
|
|
9055
|
+
pc5.bold("Advanced commands"),
|
|
8896
9056
|
...ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)),
|
|
8897
9057
|
"",
|
|
8898
|
-
|
|
9058
|
+
pc5.bold("Advanced groups"),
|
|
8899
9059
|
...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
8900
9060
|
"",
|
|
8901
|
-
|
|
9061
|
+
pc5.dim("All groups remain callable. Prefer `rig server`, `rig task`, `rig run`, and `rig inbox` for day-to-day work.")
|
|
8902
9062
|
].join(`
|
|
8903
9063
|
`);
|
|
8904
9064
|
}
|
|
@@ -9046,11 +9206,11 @@ function formatStatsReport(stats) {
|
|
|
9046
9206
|
const keyWidth = Math.max(...rows.map(([key]) => key.length));
|
|
9047
9207
|
const lines = [
|
|
9048
9208
|
formatSection("Fleet stats", window),
|
|
9049
|
-
...rows.map(([key, value]) => `${
|
|
9209
|
+
...rows.map(([key, value]) => `${pc6.dim("\u2502")} ${pc6.dim(key.padEnd(keyWidth + 2))} ${value}`)
|
|
9050
9210
|
];
|
|
9051
9211
|
const otherStatuses = Object.entries(stats.statusCounts).filter(([status]) => !["completed", "failed", "needs-attention"].includes(status)).sort(([, left], [, right]) => right - left);
|
|
9052
9212
|
if (otherStatuses.length > 0) {
|
|
9053
|
-
lines.push(`${
|
|
9213
|
+
lines.push(`${pc6.dim("\u2502")} ${pc6.dim("other".padEnd(keyWidth + 2))} ${otherStatuses.map(([status, count]) => `${status}:${count}`).join(" ")}`);
|
|
9054
9214
|
}
|
|
9055
9215
|
lines.push("", ...formatNextSteps([
|
|
9056
9216
|
"Inspect a run: `rig run list` then `rig run show <run-id>`",
|
|
@@ -9069,7 +9229,8 @@ async function executeStats(context, args) {
|
|
|
9069
9229
|
const sinceResult = takeOption(pending, "--since");
|
|
9070
9230
|
requireNoExtraArgs(sinceResult.rest, "rig stats [show] [--since <7d|30d|ISO date>]");
|
|
9071
9231
|
const since = parseSinceOption(sinceResult.value);
|
|
9072
|
-
const
|
|
9232
|
+
const remoteStats = isRemoteConnectionSelected(context.projectRoot);
|
|
9233
|
+
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 });
|
|
9073
9234
|
if (context.outputMode === "text") {
|
|
9074
9235
|
printFormattedOutput(formatStatsReport(stats));
|
|
9075
9236
|
}
|
|
@@ -9324,7 +9485,7 @@ async function executeTask(context, args, options) {
|
|
|
9324
9485
|
pending = rawResult.rest;
|
|
9325
9486
|
const { filters, rest: remaining } = parseTaskFilters(pending);
|
|
9326
9487
|
requireNoExtraArgs(remaining, "rig task list [--raw] [--assignee <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
9327
|
-
const tasks = await listWorkspaceTasksViaServer(context, filters);
|
|
9488
|
+
const tasks = await withSpinner("Reading tasks from server\u2026", () => listWorkspaceTasksViaServer(context, filters), { outputMode: context.outputMode });
|
|
9328
9489
|
if (context.outputMode === "text") {
|
|
9329
9490
|
const renderedTasks = rawResult.value ? tasks.map((task) => summarizeTask(task, { raw: true })) : tasks.map((task) => summarizeTask(task));
|
|
9330
9491
|
printFormattedOutput(formatTaskList(renderedTasks, { raw: rawResult.value }));
|
|
@@ -9348,7 +9509,7 @@ async function executeTask(context, args, options) {
|
|
|
9348
9509
|
const taskId3 = normalizeTaskRunTaskId(taskOption.value ?? positional);
|
|
9349
9510
|
if (!taskId3)
|
|
9350
9511
|
throw new CliError("task show requires a task id.", 2, { hint: "Run `rig task list` to find ids, then `rig task show <id>`." });
|
|
9351
|
-
const task = await getWorkspaceTaskViaServer(context, taskId3);
|
|
9512
|
+
const task = await withSpinner(`Reading task ${taskId3} from server\u2026`, () => getWorkspaceTaskViaServer(context, taskId3), { outputMode: context.outputMode });
|
|
9352
9513
|
if (!task)
|
|
9353
9514
|
throw new CliError(`Task not found: ${taskId3}`, 3, { hint: "Run `rig task list` to see available tasks." });
|
|
9354
9515
|
const summary = summarizeTask(task, { raw: true });
|
|
@@ -9360,7 +9521,7 @@ async function executeTask(context, args, options) {
|
|
|
9360
9521
|
case "next": {
|
|
9361
9522
|
const { filters, rest: remaining } = parseTaskFilters(rest);
|
|
9362
9523
|
requireNoExtraArgs(remaining, "rig task next [--assignee <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
9363
|
-
const selected = await selectNextWorkspaceTaskViaServer(context, filters);
|
|
9524
|
+
const selected = await withSpinner("Selecting next ready task\u2026", () => selectNextWorkspaceTaskViaServer(context, filters), { outputMode: context.outputMode });
|
|
9364
9525
|
if (context.outputMode === "text") {
|
|
9365
9526
|
if (selected.task) {
|
|
9366
9527
|
printFormattedOutput(formatTaskCard(summarizeTask(selected.task, { raw: true }), { title: "Selected task", selected: true }));
|
|
@@ -9510,7 +9671,7 @@ async function executeTask(context, args, options) {
|
|
|
9510
9671
|
let selectedTask = null;
|
|
9511
9672
|
let selectedTaskId = normalizeTaskRunTaskId(taskResult.value) ?? positionalTaskId;
|
|
9512
9673
|
if (nextResult.value) {
|
|
9513
|
-
const selected = await selectNextWorkspaceTaskViaServer(context, filterResult.filters);
|
|
9674
|
+
const selected = await withSpinner("Selecting next ready task\u2026", () => selectNextWorkspaceTaskViaServer(context, filterResult.filters), { outputMode: context.outputMode });
|
|
9514
9675
|
selectedTask = selected.task;
|
|
9515
9676
|
selectedTaskId = selected.task ? readTaskId(selected.task) : null;
|
|
9516
9677
|
if (!selectedTaskId) {
|
|
@@ -9521,7 +9682,7 @@ async function executeTask(context, args, options) {
|
|
|
9521
9682
|
if (context.outputMode !== "text" || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
9522
9683
|
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);
|
|
9523
9684
|
}
|
|
9524
|
-
const tasks = await listWorkspaceTasksViaServer(context, filterResult.filters);
|
|
9685
|
+
const tasks = await withSpinner("Reading tasks from server\u2026", () => listWorkspaceTasksViaServer(context, filterResult.filters), { outputMode: context.outputMode });
|
|
9525
9686
|
selectedTask = await selectTaskWithTextPicker(tasks);
|
|
9526
9687
|
selectedTaskId = selectedTask ? readTaskId(selectedTask) : null;
|
|
9527
9688
|
if (!selectedTaskId) {
|
|
@@ -9531,13 +9692,13 @@ async function executeTask(context, args, options) {
|
|
|
9531
9692
|
await runProjectMainSyncPreflight(context, { disabled: skipProjectSyncResult.value });
|
|
9532
9693
|
const projectDefaults = await loadTaskRunProjectDefaults(context.projectRoot);
|
|
9533
9694
|
const runtimeAdapter = normalizeRuntimeAdapter(runtimeAdapterResult.value ?? projectDefaults.runtimeAdapter);
|
|
9534
|
-
await runFastTaskRunPreflight(context, {
|
|
9695
|
+
await withSpinner("Running task-run preflight\u2026", () => runFastTaskRunPreflight(context, {
|
|
9535
9696
|
taskId: selectedTaskId,
|
|
9536
9697
|
runtimeAdapter
|
|
9537
|
-
});
|
|
9698
|
+
}), { outputMode: context.outputMode });
|
|
9538
9699
|
const dirtyBaseline = await resolveDirtyBaselineForTaskRun(context, dirtyBaselineResult.value);
|
|
9539
9700
|
const prMode = noPrResult.value ? "off" : normalizePrMode(prResult.value) ?? projectDefaults.prMode;
|
|
9540
|
-
const submitted = await submitTaskRunViaServer(context, {
|
|
9701
|
+
const submitted = await withSpinner("Dispatching run\u2026", () => submitTaskRunViaServer(context, {
|
|
9541
9702
|
runId: context.runId,
|
|
9542
9703
|
taskId: selectedTaskId ?? undefined,
|
|
9543
9704
|
title: titleResult.value ?? undefined,
|
|
@@ -9548,7 +9709,7 @@ async function executeTask(context, args, options) {
|
|
|
9548
9709
|
initialPrompt: initialPromptResult.value ?? undefined,
|
|
9549
9710
|
baselineMode: dirtyBaseline.mode,
|
|
9550
9711
|
prMode
|
|
9551
|
-
});
|
|
9712
|
+
}), { outputMode: context.outputMode });
|
|
9552
9713
|
let attachDetails = null;
|
|
9553
9714
|
if (!detachResult.value && context.outputMode === "text") {
|
|
9554
9715
|
printFormattedOutput(formatSubmittedRun({
|
|
@@ -11726,7 +11887,7 @@ async function executeSetup(context, args) {
|
|
|
11726
11887
|
case "check":
|
|
11727
11888
|
requireNoExtraArgs(rest, `rig setup ${command}`);
|
|
11728
11889
|
{
|
|
11729
|
-
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
|
|
11890
|
+
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot, context.outputMode));
|
|
11730
11891
|
return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
|
|
11731
11892
|
}
|
|
11732
11893
|
case "setup":
|
|
@@ -11735,7 +11896,7 @@ async function executeSetup(context, args) {
|
|
|
11735
11896
|
return { ok: true, group: "setup", command };
|
|
11736
11897
|
case "preflight":
|
|
11737
11898
|
requireNoExtraArgs(rest, "rig setup preflight");
|
|
11738
|
-
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
|
|
11899
|
+
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot, context.outputMode));
|
|
11739
11900
|
return { ok: true, group: "setup", command };
|
|
11740
11901
|
default:
|
|
11741
11902
|
throw new CliError(`Unknown setup command: ${command}`, 1, { hint: "Run `rig setup --help` \u2014 commands are bootstrap|check|preflight." });
|
|
@@ -11756,8 +11917,8 @@ function runSetupInit(projectRoot) {
|
|
|
11756
11917
|
}
|
|
11757
11918
|
console.log("Harness directories ready.");
|
|
11758
11919
|
}
|
|
11759
|
-
async function runSetupCheck(projectRoot) {
|
|
11760
|
-
const doctorChecks = await runRigDoctorChecks({ projectRoot });
|
|
11920
|
+
async function runSetupCheck(projectRoot, outputMode = "text") {
|
|
11921
|
+
const doctorChecks = await withSpinner("Running setup checks\u2026", (update) => runRigDoctorChecks({ projectRoot, onProgress: update }), { outputMode });
|
|
11761
11922
|
console.log(formatDoctorChecks(doctorChecks));
|
|
11762
11923
|
const failures = countDoctorFailures(doctorChecks);
|
|
11763
11924
|
if (failures > 0) {
|
|
@@ -11765,8 +11926,8 @@ async function runSetupCheck(projectRoot) {
|
|
|
11765
11926
|
}
|
|
11766
11927
|
return doctorChecks;
|
|
11767
11928
|
}
|
|
11768
|
-
async function runSetupPreflight(projectRoot) {
|
|
11769
|
-
await runSetupCheck(projectRoot);
|
|
11929
|
+
async function runSetupPreflight(projectRoot, outputMode = "text") {
|
|
11930
|
+
await runSetupCheck(projectRoot, outputMode);
|
|
11770
11931
|
const validationRoot = resolve24(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
|
|
11771
11932
|
if (existsSync16(validationRoot)) {
|
|
11772
11933
|
const validators = readdirSync3(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|