@h-rig/cli 0.0.6-alpha.67 → 0.0.6-alpha.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/rig.js +232 -71
- package/dist/src/commands/_async-ui.js +141 -0
- package/dist/src/commands/_doctor-checks.js +18 -0
- package/dist/src/commands/_operator-view.js +143 -4
- package/dist/src/commands/_pi-frontend.js +13 -1
- package/dist/src/commands/_preflight.js +7 -0
- package/dist/src/commands/_server-client.js +13 -0
- package/dist/src/commands/_snapshot-upload.js +7 -0
- package/dist/src/commands/_spinner.js +4 -2
- package/dist/src/commands/doctor.js +145 -1
- package/dist/src/commands/github.js +137 -3
- package/dist/src/commands/inbox.js +139 -6
- package/dist/src/commands/init.js +18 -0
- package/dist/src/commands/inspect.js +147 -8
- package/dist/src/commands/run.js +173 -31
- package/dist/src/commands/server.js +7 -0
- package/dist/src/commands/setup.js +150 -6
- package/dist/src/commands/stats.js +156 -22
- package/dist/src/commands/task-run-driver.js +7 -0
- package/dist/src/commands/task.js +186 -47
- package/dist/src/commands.js +232 -71
- package/dist/src/index.js +232 -71
- package/package.json +8 -8
package/dist/src/commands/run.js
CHANGED
|
@@ -194,6 +194,15 @@ function isRemoteConnectionSelected(projectRoot) {
|
|
|
194
194
|
|
|
195
195
|
// packages/cli/src/commands/_server-client.ts
|
|
196
196
|
var scopedGitHubBearerTokens = new Map;
|
|
197
|
+
var serverPhaseListener = null;
|
|
198
|
+
function setServerPhaseListener(listener) {
|
|
199
|
+
const previous = serverPhaseListener;
|
|
200
|
+
serverPhaseListener = listener;
|
|
201
|
+
return previous;
|
|
202
|
+
}
|
|
203
|
+
function reportServerPhase(label) {
|
|
204
|
+
serverPhaseListener?.(label);
|
|
205
|
+
}
|
|
197
206
|
function cleanToken(value) {
|
|
198
207
|
const trimmed = value?.trim();
|
|
199
208
|
return trimmed ? trimmed : null;
|
|
@@ -236,6 +245,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
236
245
|
try {
|
|
237
246
|
const selected = resolveSelectedConnection(projectRoot);
|
|
238
247
|
if (selected?.connection.kind === "remote") {
|
|
248
|
+
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
239
249
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
240
250
|
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
241
251
|
return {
|
|
@@ -245,6 +255,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
245
255
|
serverProjectRoot
|
|
246
256
|
};
|
|
247
257
|
}
|
|
258
|
+
reportServerPhase("Starting local Rig server\u2026");
|
|
248
259
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
249
260
|
return {
|
|
250
261
|
baseUrl: connection.baseUrl,
|
|
@@ -351,6 +362,7 @@ async function requestServerJson(context, pathname, init = {}) {
|
|
|
351
362
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
352
363
|
if (server.serverProjectRoot)
|
|
353
364
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
365
|
+
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
354
366
|
let response;
|
|
355
367
|
try {
|
|
356
368
|
response = await fetch(`${server.baseUrl}${pathname}`, {
|
|
@@ -811,7 +823,12 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
811
823
|
};
|
|
812
824
|
let detached = false;
|
|
813
825
|
try {
|
|
814
|
-
await runPiMain([
|
|
826
|
+
await runPiMain([
|
|
827
|
+
"--no-extensions",
|
|
828
|
+
"--no-skills",
|
|
829
|
+
"--no-prompt-templates",
|
|
830
|
+
"--no-context-files"
|
|
831
|
+
], {
|
|
815
832
|
extensionFactories: [piRigExtensionFactory]
|
|
816
833
|
});
|
|
817
834
|
detached = true;
|
|
@@ -834,6 +851,127 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
834
851
|
};
|
|
835
852
|
}
|
|
836
853
|
|
|
854
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
855
|
+
import pc from "picocolors";
|
|
856
|
+
|
|
857
|
+
// packages/cli/src/commands/_spinner.ts
|
|
858
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
859
|
+
function createTtySpinner(input) {
|
|
860
|
+
const output = input.output ?? process.stdout;
|
|
861
|
+
const isTty = output.isTTY === true;
|
|
862
|
+
const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
|
|
863
|
+
let label = input.label;
|
|
864
|
+
let frame = 0;
|
|
865
|
+
let paused = false;
|
|
866
|
+
let stopped = false;
|
|
867
|
+
let lastPrintedLabel = "";
|
|
868
|
+
const render = () => {
|
|
869
|
+
if (stopped || paused)
|
|
870
|
+
return;
|
|
871
|
+
if (!isTty) {
|
|
872
|
+
if (label !== lastPrintedLabel) {
|
|
873
|
+
output.write(`${label}
|
|
874
|
+
`);
|
|
875
|
+
lastPrintedLabel = label;
|
|
876
|
+
}
|
|
877
|
+
return;
|
|
878
|
+
}
|
|
879
|
+
frame = (frame + 1) % frames.length;
|
|
880
|
+
const glyph = frames[frame] ?? frames[0] ?? "";
|
|
881
|
+
output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
|
|
882
|
+
};
|
|
883
|
+
const clearLine = () => {
|
|
884
|
+
if (isTty)
|
|
885
|
+
output.write("\r\x1B[2K");
|
|
886
|
+
};
|
|
887
|
+
render();
|
|
888
|
+
const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
|
|
889
|
+
return {
|
|
890
|
+
setLabel(next) {
|
|
891
|
+
label = next;
|
|
892
|
+
render();
|
|
893
|
+
},
|
|
894
|
+
pause() {
|
|
895
|
+
paused = true;
|
|
896
|
+
clearLine();
|
|
897
|
+
},
|
|
898
|
+
resume() {
|
|
899
|
+
if (stopped)
|
|
900
|
+
return;
|
|
901
|
+
paused = false;
|
|
902
|
+
render();
|
|
903
|
+
},
|
|
904
|
+
stop(finalLine) {
|
|
905
|
+
if (stopped)
|
|
906
|
+
return;
|
|
907
|
+
stopped = true;
|
|
908
|
+
if (timer)
|
|
909
|
+
clearInterval(timer);
|
|
910
|
+
clearLine();
|
|
911
|
+
if (finalLine)
|
|
912
|
+
output.write(`${finalLine}
|
|
913
|
+
`);
|
|
914
|
+
}
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
// packages/cli/src/commands/_async-ui.ts
|
|
919
|
+
var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
|
|
920
|
+
var DONE_SYMBOL = pc.green("\u25C7");
|
|
921
|
+
var FAIL_SYMBOL = pc.red("\u25A0");
|
|
922
|
+
var activeUpdate = null;
|
|
923
|
+
async function withSpinner(label, work, options = {}) {
|
|
924
|
+
if (options.outputMode === "json") {
|
|
925
|
+
return work(() => {});
|
|
926
|
+
}
|
|
927
|
+
if (activeUpdate) {
|
|
928
|
+
const outer = activeUpdate;
|
|
929
|
+
outer(label);
|
|
930
|
+
return work(outer);
|
|
931
|
+
}
|
|
932
|
+
const output = options.output ?? process.stderr;
|
|
933
|
+
const isTty = output.isTTY === true;
|
|
934
|
+
let lastLabel = label;
|
|
935
|
+
if (!isTty) {
|
|
936
|
+
output.write(`${label}
|
|
937
|
+
`);
|
|
938
|
+
const update2 = (next) => {
|
|
939
|
+
lastLabel = next;
|
|
940
|
+
};
|
|
941
|
+
activeUpdate = update2;
|
|
942
|
+
const previousListener2 = setServerPhaseListener(update2);
|
|
943
|
+
try {
|
|
944
|
+
return await work(update2);
|
|
945
|
+
} finally {
|
|
946
|
+
activeUpdate = null;
|
|
947
|
+
setServerPhaseListener(previousListener2);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
const spinner = createTtySpinner({
|
|
951
|
+
label,
|
|
952
|
+
output,
|
|
953
|
+
frames: CLACK_SPINNER_FRAMES,
|
|
954
|
+
styleFrame: (frame) => pc.magenta(frame)
|
|
955
|
+
});
|
|
956
|
+
const update = (next) => {
|
|
957
|
+
lastLabel = next;
|
|
958
|
+
spinner.setLabel(next);
|
|
959
|
+
};
|
|
960
|
+
activeUpdate = update;
|
|
961
|
+
const previousListener = setServerPhaseListener(update);
|
|
962
|
+
try {
|
|
963
|
+
const result = await work(update);
|
|
964
|
+
spinner.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
|
|
965
|
+
return result;
|
|
966
|
+
} catch (error) {
|
|
967
|
+
spinner.stop(`${FAIL_SYMBOL} ${lastLabel}`);
|
|
968
|
+
throw error;
|
|
969
|
+
} finally {
|
|
970
|
+
activeUpdate = null;
|
|
971
|
+
setServerPhaseListener(previousListener);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
|
|
837
975
|
// packages/cli/src/commands/_operator-view.ts
|
|
838
976
|
var TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
|
|
839
977
|
function runStatusFromPayload(payload) {
|
|
@@ -876,8 +1014,9 @@ async function readOperatorSnapshot(context, runId, options = {}) {
|
|
|
876
1014
|
}
|
|
877
1015
|
async function attachRunOperatorView(context, input) {
|
|
878
1016
|
let steered = false;
|
|
879
|
-
|
|
880
|
-
|
|
1017
|
+
const attachMessage = input.message?.trim();
|
|
1018
|
+
if (attachMessage) {
|
|
1019
|
+
await withSpinner("Queueing steering message\u2026", () => sendRunPiPromptViaServer(context, input.runId, attachMessage, "steer").catch(() => steerRunViaServer(context, input.runId, attachMessage)), { outputMode: context.outputMode });
|
|
881
1020
|
steered = true;
|
|
882
1021
|
}
|
|
883
1022
|
if (input.follow && !input.once && input.interactive !== false && context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
@@ -887,7 +1026,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
887
1026
|
});
|
|
888
1027
|
}
|
|
889
1028
|
const surface = createOperatorSurface({ interactive: input.interactive !== false });
|
|
890
|
-
let snapshot = await readOperatorSnapshot(context, input.runId);
|
|
1029
|
+
let snapshot = await withSpinner(`Connecting to run ${input.runId}\u2026`, () => readOperatorSnapshot(context, input.runId), { outputMode: context.outputMode });
|
|
891
1030
|
if (context.outputMode === "text") {
|
|
892
1031
|
surface.renderSnapshot(snapshot);
|
|
893
1032
|
surface.renderTimeline(snapshot.timeline);
|
|
@@ -927,7 +1066,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
927
1066
|
|
|
928
1067
|
// packages/cli/src/commands/_cli-format.ts
|
|
929
1068
|
import { log, note } from "@clack/prompts";
|
|
930
|
-
import
|
|
1069
|
+
import pc2 from "picocolors";
|
|
931
1070
|
function stringField(record, key, fallback = "") {
|
|
932
1071
|
const value = record[key];
|
|
933
1072
|
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
@@ -949,14 +1088,14 @@ function pad(value, width) {
|
|
|
949
1088
|
function statusColor(status) {
|
|
950
1089
|
const normalized = status.toLowerCase();
|
|
951
1090
|
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
|
|
952
|
-
return
|
|
1091
|
+
return pc2.green;
|
|
953
1092
|
if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
|
|
954
|
-
return
|
|
1093
|
+
return pc2.red;
|
|
955
1094
|
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
956
|
-
return
|
|
1095
|
+
return pc2.cyan;
|
|
957
1096
|
if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
|
|
958
|
-
return
|
|
959
|
-
return
|
|
1097
|
+
return pc2.yellow;
|
|
1098
|
+
return pc2.dim;
|
|
960
1099
|
}
|
|
961
1100
|
function compactDate(value) {
|
|
962
1101
|
if (!value.trim())
|
|
@@ -1001,23 +1140,23 @@ function formatStatusPill(status) {
|
|
|
1001
1140
|
return statusColor(label)(`\u25CF ${label}`);
|
|
1002
1141
|
}
|
|
1003
1142
|
function formatSection(title, subtitle) {
|
|
1004
|
-
return `${
|
|
1143
|
+
return `${pc2.bold(pc2.cyan("\u25C6"))} ${pc2.bold(title)}${subtitle ? pc2.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
1005
1144
|
}
|
|
1006
1145
|
function formatSuccessCard(title, rows = []) {
|
|
1007
|
-
const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${
|
|
1146
|
+
const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${pc2.dim("\u2502")} ${pc2.dim(key.padEnd(12))} ${value}`);
|
|
1008
1147
|
return [formatSection(title), ...body].join(`
|
|
1009
1148
|
`);
|
|
1010
1149
|
}
|
|
1011
1150
|
function formatNextSteps(steps) {
|
|
1012
1151
|
if (steps.length === 0)
|
|
1013
1152
|
return [];
|
|
1014
|
-
return [
|
|
1153
|
+
return [pc2.bold("Next"), ...steps.map((step) => `${pc2.dim("\u203A")} ${step}`)];
|
|
1015
1154
|
}
|
|
1016
1155
|
function formatRunList(runs, options = {}) {
|
|
1017
1156
|
if (runs.length === 0) {
|
|
1018
1157
|
return [
|
|
1019
1158
|
formatSection("Runs", "none recorded"),
|
|
1020
|
-
options.source === "server" ?
|
|
1159
|
+
options.source === "server" ? pc2.dim("No runs recorded on the selected Rig server.") : pc2.dim("No runs recorded in .rig/runs."),
|
|
1021
1160
|
"",
|
|
1022
1161
|
...formatNextSteps(["Start one: `rig task run --next`", "Check server: `rig server status`"])
|
|
1023
1162
|
].join(`
|
|
@@ -1033,11 +1172,11 @@ function formatRunList(runs, options = {}) {
|
|
|
1033
1172
|
});
|
|
1034
1173
|
const idWidth = Math.min(36, Math.max(6, ...rows.map((row) => row.runId.length)));
|
|
1035
1174
|
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
1036
|
-
const header = `${
|
|
1175
|
+
const header = `${pc2.bold(pad("RUN", idWidth))} ${pc2.bold(pad("STATUS", statusWidth))} ${pc2.bold("TITLE")}`;
|
|
1037
1176
|
const body = rows.map((row) => [
|
|
1038
|
-
|
|
1177
|
+
pc2.bold(pad(truncate(row.runId, idWidth), idWidth)),
|
|
1039
1178
|
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
1040
|
-
`${row.title}${row.runtime ?
|
|
1179
|
+
`${row.title}${row.runtime ? pc2.dim(` ${row.runtime}`) : ""}`
|
|
1041
1180
|
].join(" "));
|
|
1042
1181
|
return [formatSection("Runs", options.source === "server" ? "selected server" : "local state"), header, ...body, "", ...formatNextSteps(["Follow live: `rig run attach <run-id> --follow`", "Details: `rig run show <run-id>`"])].join(`
|
|
1043
1182
|
`);
|
|
@@ -1062,7 +1201,7 @@ function formatRunCard(run, options = {}) {
|
|
|
1062
1201
|
const approvals = Array.isArray(merged.approvals) ? merged.approvals.length : null;
|
|
1063
1202
|
const inputs = Array.isArray(merged.userInputs) ? merged.userInputs.length : null;
|
|
1064
1203
|
const rows = [
|
|
1065
|
-
["run",
|
|
1204
|
+
["run", pc2.bold(runId)],
|
|
1066
1205
|
["status", formatStatusPill(status)],
|
|
1067
1206
|
["task", taskId],
|
|
1068
1207
|
["title", title],
|
|
@@ -1088,17 +1227,17 @@ function formatRunStatus(summary, options = {}) {
|
|
|
1088
1227
|
const activeRuns = summary.activeRuns ?? [];
|
|
1089
1228
|
const recentRuns = summary.recentRuns ?? [];
|
|
1090
1229
|
const lines = [formatSection("Run status", options.source === "server" ? "selected server" : "local state")];
|
|
1091
|
-
lines.push("",
|
|
1230
|
+
lines.push("", pc2.bold(`Active runs (${activeRuns.length})`));
|
|
1092
1231
|
if (activeRuns.length === 0) {
|
|
1093
|
-
lines.push(
|
|
1232
|
+
lines.push(pc2.dim("No active runs."));
|
|
1094
1233
|
} else {
|
|
1095
1234
|
for (const run of activeRuns) {
|
|
1096
1235
|
lines.push(formatRunSummaryLine(run));
|
|
1097
1236
|
}
|
|
1098
1237
|
}
|
|
1099
|
-
lines.push("",
|
|
1238
|
+
lines.push("", pc2.bold(`Recent runs (${recentRuns.length})`));
|
|
1100
1239
|
if (recentRuns.length === 0) {
|
|
1101
|
-
lines.push(
|
|
1240
|
+
lines.push(pc2.dim("No recent terminal runs."));
|
|
1102
1241
|
} else {
|
|
1103
1242
|
for (const run of recentRuns.slice(0, 10)) {
|
|
1104
1243
|
lines.push(formatRunSummaryLine(run));
|
|
@@ -1116,7 +1255,7 @@ function formatRunSummaryLine(run) {
|
|
|
1116
1255
|
const title = runTitleOf(record);
|
|
1117
1256
|
const runtime = firstString(record, ["runtimeAdapter", "runtime", "adapter"]);
|
|
1118
1257
|
const descriptor = [taskId, title].filter(Boolean).join(" \xB7 ");
|
|
1119
|
-
return `${
|
|
1258
|
+
return `${pc2.dim("\u2502")} ${pc2.bold(runId)} ${formatStatusPill(status)} ${descriptor}${runtime ? pc2.dim(` ${runtime}`) : ""}`;
|
|
1120
1259
|
}
|
|
1121
1260
|
|
|
1122
1261
|
// packages/cli/src/commands/inbox.ts
|
|
@@ -1250,7 +1389,7 @@ async function executeRun(context, args) {
|
|
|
1250
1389
|
switch (command) {
|
|
1251
1390
|
case "list": {
|
|
1252
1391
|
requireNoExtraArgs(rest, "rig run list");
|
|
1253
|
-
const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
|
|
1392
|
+
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 });
|
|
1254
1393
|
if (context.outputMode === "text") {
|
|
1255
1394
|
printFormattedOutput(formatRunList(runs, { source }));
|
|
1256
1395
|
await printPendingInboxFooter(context);
|
|
@@ -1323,7 +1462,7 @@ async function executeRun(context, args) {
|
|
|
1323
1462
|
if (!runId) {
|
|
1324
1463
|
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>`." });
|
|
1325
1464
|
}
|
|
1326
|
-
const record = readAuthorityRun2(context.projectRoot, runId) ?? normalizeRemoteRunDetails(await getRunDetailsViaServer(context, runId).catch(() => ({})));
|
|
1465
|
+
const record = readAuthorityRun2(context.projectRoot, runId) ?? normalizeRemoteRunDetails(await withSpinner(`Reading run ${runId} from server\u2026`, () => getRunDetailsViaServer(context, runId).catch(() => ({})), { outputMode: context.outputMode }));
|
|
1327
1466
|
if (!record) {
|
|
1328
1467
|
throw new CliError(`Run not found: ${runId}`, 2, { hint: "Run `rig run list` to see recorded runs." });
|
|
1329
1468
|
}
|
|
@@ -1344,7 +1483,8 @@ async function executeRun(context, args) {
|
|
|
1344
1483
|
}
|
|
1345
1484
|
const renderer = createPiRunStreamRenderer();
|
|
1346
1485
|
let cursor = null;
|
|
1347
|
-
const
|
|
1486
|
+
const timelineRunId = run.value;
|
|
1487
|
+
const page = await withSpinner(`Reading timeline for ${timelineRunId}\u2026`, () => getRunTimelineViaServer(context, timelineRunId, { limit: 500 }), { outputMode: context.outputMode });
|
|
1348
1488
|
const events = Array.isArray(page.entries) ? page.entries.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))) : [];
|
|
1349
1489
|
cursor = typeof page.nextCursor === "string" ? page.nextCursor : null;
|
|
1350
1490
|
if (context.outputMode === "text") {
|
|
@@ -1421,8 +1561,9 @@ async function executeRun(context, args) {
|
|
|
1421
1561
|
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`." });
|
|
1422
1562
|
}
|
|
1423
1563
|
let steered = false;
|
|
1424
|
-
|
|
1425
|
-
|
|
1564
|
+
const steerMessage = messageOption.value?.trim();
|
|
1565
|
+
if (steerMessage) {
|
|
1566
|
+
await withSpinner("Queueing steering message\u2026", () => steerRunViaServer(context, runId, steerMessage), { outputMode: context.outputMode });
|
|
1426
1567
|
steered = true;
|
|
1427
1568
|
}
|
|
1428
1569
|
const attached = await attachRunOperatorView(context, {
|
|
@@ -1442,7 +1583,7 @@ async function executeRun(context, args) {
|
|
|
1442
1583
|
}
|
|
1443
1584
|
return { ok: true, group: "run", command };
|
|
1444
1585
|
}
|
|
1445
|
-
const summary = isRemoteConnectionSelected(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
|
|
1586
|
+
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);
|
|
1446
1587
|
const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
1447
1588
|
const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
1448
1589
|
if (context.outputMode === "text") {
|
|
@@ -1577,7 +1718,8 @@ async function executeRun(context, args) {
|
|
|
1577
1718
|
}
|
|
1578
1719
|
return { ok: true, group: "run", command, details: { runId, dryRun: true } };
|
|
1579
1720
|
}
|
|
1580
|
-
|
|
1721
|
+
const trimmedMessage = message.trim();
|
|
1722
|
+
await withSpinner("Queueing steering message\u2026", () => steerRunViaServer(context, runId, trimmedMessage), { outputMode: context.outputMode });
|
|
1581
1723
|
if (context.outputMode === "text") {
|
|
1582
1724
|
console.log(`Steering message queued for ${runId}.`);
|
|
1583
1725
|
}
|
|
@@ -1598,7 +1740,7 @@ async function executeRun(context, args) {
|
|
|
1598
1740
|
};
|
|
1599
1741
|
}
|
|
1600
1742
|
if (runId) {
|
|
1601
|
-
const stopped = await stopRunViaServer(context, runId);
|
|
1743
|
+
const stopped = await withSpinner(`Requesting stop for ${runId}\u2026`, () => stopRunViaServer(context, runId), { outputMode: context.outputMode });
|
|
1602
1744
|
if (context.outputMode === "text")
|
|
1603
1745
|
console.log(`Stop requested: ${runId}`);
|
|
1604
1746
|
return { ok: true, group: "run", command, details: stopped };
|
|
@@ -361,6 +361,10 @@ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
|
361
361
|
import { resolve as resolve2 } from "path";
|
|
362
362
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
363
363
|
var scopedGitHubBearerTokens = new Map;
|
|
364
|
+
var serverPhaseListener = null;
|
|
365
|
+
function reportServerPhase(label) {
|
|
366
|
+
serverPhaseListener?.(label);
|
|
367
|
+
}
|
|
364
368
|
function cleanToken(value) {
|
|
365
369
|
const trimmed = value?.trim();
|
|
366
370
|
return trimmed ? trimmed : null;
|
|
@@ -403,6 +407,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
403
407
|
try {
|
|
404
408
|
const selected = resolveSelectedConnection(projectRoot);
|
|
405
409
|
if (selected?.connection.kind === "remote") {
|
|
410
|
+
reportServerPhase(`Connecting to ${selected.alias}\u2026`);
|
|
406
411
|
const authToken = readGitHubBearerTokenForRemote(projectRoot);
|
|
407
412
|
const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
|
|
408
413
|
return {
|
|
@@ -412,6 +417,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
412
417
|
serverProjectRoot
|
|
413
418
|
};
|
|
414
419
|
}
|
|
420
|
+
reportServerPhase("Starting local Rig server\u2026");
|
|
415
421
|
const connection = await ensureLocalRigServerConnection(projectRoot);
|
|
416
422
|
return {
|
|
417
423
|
baseUrl: connection.baseUrl,
|
|
@@ -518,6 +524,7 @@ async function requestServerJson(context, pathname, init = {}) {
|
|
|
518
524
|
const headers = mergeHeaders(init.headers, server.authToken);
|
|
519
525
|
if (server.serverProjectRoot)
|
|
520
526
|
headers.set("x-rig-project-root", server.serverProjectRoot);
|
|
527
|
+
reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
|
|
521
528
|
let response;
|
|
522
529
|
try {
|
|
523
530
|
response = await fetch(`${server.baseUrl}${pathname}`, {
|