@h-rig/cli 0.0.6-alpha.7 → 0.0.6-alpha.71

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.
Files changed (53) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/rig.js +4507 -1506
  3. package/dist/src/commands/_async-ui.js +152 -0
  4. package/dist/src/commands/_authority-runs.js +2 -3
  5. package/dist/src/commands/_cli-format.js +369 -0
  6. package/dist/src/commands/_connection-state.js +30 -11
  7. package/dist/src/commands/_doctor-checks.js +177 -43
  8. package/dist/src/commands/_help-catalog.js +485 -0
  9. package/dist/src/commands/_json-output.js +56 -0
  10. package/dist/src/commands/_operator-surface.js +220 -0
  11. package/dist/src/commands/_operator-view.js +595 -72
  12. package/dist/src/commands/_parsers.js +18 -11
  13. package/dist/src/commands/_pi-frontend.js +411 -0
  14. package/dist/src/commands/_pi-install.js +4 -3
  15. package/dist/src/commands/_policy.js +12 -5
  16. package/dist/src/commands/_preflight.js +187 -127
  17. package/dist/src/commands/_run-driver-helpers.js +75 -22
  18. package/dist/src/commands/_run-replay.js +142 -0
  19. package/dist/src/commands/_server-client.js +343 -60
  20. package/dist/src/commands/_snapshot-upload.js +160 -38
  21. package/dist/src/commands/_spinner.js +65 -0
  22. package/dist/src/commands/_task-picker.js +44 -16
  23. package/dist/src/commands/agent.js +39 -20
  24. package/dist/src/commands/browser.js +28 -21
  25. package/dist/src/commands/connect.js +146 -33
  26. package/dist/src/commands/dist.js +19 -12
  27. package/dist/src/commands/doctor.js +304 -44
  28. package/dist/src/commands/github.js +301 -52
  29. package/dist/src/commands/inbox.js +679 -72
  30. package/dist/src/commands/init.js +622 -118
  31. package/dist/src/commands/inspect.js +515 -32
  32. package/dist/src/commands/inspector.js +20 -13
  33. package/dist/src/commands/pi.js +177 -0
  34. package/dist/src/commands/plugin.js +95 -27
  35. package/dist/src/commands/profile-and-review.js +26 -19
  36. package/dist/src/commands/queue.js +32 -12
  37. package/dist/src/commands/remote.js +43 -36
  38. package/dist/src/commands/repo-git-harness.js +22 -15
  39. package/dist/src/commands/run.js +1162 -158
  40. package/dist/src/commands/server.js +373 -56
  41. package/dist/src/commands/setup.js +316 -62
  42. package/dist/src/commands/stats.js +1030 -0
  43. package/dist/src/commands/task-report-bug.js +29 -22
  44. package/dist/src/commands/task-run-driver.js +862 -129
  45. package/dist/src/commands/task.js +1423 -311
  46. package/dist/src/commands/test.js +15 -8
  47. package/dist/src/commands/workspace.js +18 -11
  48. package/dist/src/commands.js +4446 -1499
  49. package/dist/src/index.js +4502 -1504
  50. package/dist/src/launcher.js +77 -13
  51. package/dist/src/report-bug.js +3 -3
  52. package/dist/src/runner.js +16 -22
  53. package/package.json +10 -5
@@ -1,15 +1,22 @@
1
1
  // @bun
2
2
  // packages/cli/src/commands/github.ts
3
- import { spawnSync as spawnSync2 } from "child_process";
3
+ import { spawnSync } from "child_process";
4
4
 
5
5
  // packages/cli/src/runner.ts
6
6
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
7
- import { CliError } from "@rig/runtime/control-plane/errors";
7
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
8
8
  import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
9
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
10
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
11
9
  import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
12
- import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
10
+
11
+ class CliError extends RuntimeCliError {
12
+ hint;
13
+ constructor(message, exitCode = 1, options = {}) {
14
+ super(message, exitCode);
15
+ if (options.hint?.trim()) {
16
+ this.hint = options.hint.trim();
17
+ }
18
+ }
19
+ }
13
20
  function takeOption(args, option) {
14
21
  const rest = [];
15
22
  let value;
@@ -18,7 +25,7 @@ function takeOption(args, option) {
18
25
  if (current === option) {
19
26
  const next = args[index + 1];
20
27
  if (!next || next.startsWith("-")) {
21
- throw new CliError(`Missing value for ${option}`);
28
+ throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
22
29
  }
23
30
  value = next;
24
31
  index += 1;
@@ -32,7 +39,6 @@ function takeOption(args, option) {
32
39
  }
33
40
 
34
41
  // packages/cli/src/commands/_server-client.ts
35
- import { spawnSync } from "child_process";
36
42
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
37
43
  import { resolve as resolve2 } from "path";
38
44
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
@@ -59,9 +65,14 @@ function readJsonFile(path) {
59
65
  try {
60
66
  return JSON.parse(readFileSync(path, "utf8"));
61
67
  } catch (error) {
62
- throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
68
+ throw new CliError(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1, { hint: "Fix or delete that file, then re-select a server with `rig server use <alias|local>`." });
63
69
  }
64
70
  }
71
+ function writeJsonFile(path, value) {
72
+ mkdirSync(dirname(path), { recursive: true });
73
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}
74
+ `, "utf8");
75
+ }
65
76
  function normalizeConnection(value) {
66
77
  if (!value || typeof value !== "object" || Array.isArray(value))
67
78
  return null;
@@ -102,25 +113,44 @@ function readRepoConnection(projectRoot) {
102
113
  return {
103
114
  selected,
104
115
  project: typeof record.project === "string" ? record.project : undefined,
105
- linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
116
+ linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
117
+ serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
106
118
  };
107
119
  }
120
+ function writeRepoConnection(projectRoot, state) {
121
+ writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
122
+ }
108
123
  function resolveSelectedConnection(projectRoot, options = {}) {
109
124
  const repo = readRepoConnection(projectRoot);
110
125
  if (!repo)
111
126
  return null;
112
127
  if (repo.selected === "local")
113
- return { alias: "local", connection: { kind: "local", mode: "auto" } };
128
+ return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
114
129
  const global = readGlobalConnections(options);
115
130
  const connection = global.connections[repo.selected];
116
131
  if (!connection) {
117
- throw new CliError2(`Selected Rig connection "${repo.selected}" was not found. Run \`rig connect list\` or \`rig connect use local\`.`, 1);
132
+ throw new CliError(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
118
133
  }
119
- return { alias: repo.selected, connection };
134
+ return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
135
+ }
136
+ function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
137
+ const repo = readRepoConnection(projectRoot);
138
+ if (!repo)
139
+ return;
140
+ writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
120
141
  }
121
142
 
122
143
  // packages/cli/src/commands/_server-client.ts
123
- var cachedGitHubBearerToken;
144
+ var scopedGitHubBearerTokens = new Map;
145
+ var serverPhaseListener = null;
146
+ function setServerPhaseListener(listener) {
147
+ const previous = serverPhaseListener;
148
+ serverPhaseListener = listener;
149
+ return previous;
150
+ }
151
+ function reportServerPhase(label) {
152
+ serverPhaseListener?.(label);
153
+ }
124
154
  function cleanToken(value) {
125
155
  const trimmed = value?.trim();
126
156
  return trimmed ? trimmed : null;
@@ -137,49 +167,80 @@ function readPrivateRemoteSessionToken(projectRoot) {
137
167
  }
138
168
  }
139
169
  function readGitHubBearerTokenForRemote(projectRoot) {
140
- if (cachedGitHubBearerToken !== undefined)
141
- return cachedGitHubBearerToken;
170
+ const scopedKey = resolve2(projectRoot);
171
+ if (scopedGitHubBearerTokens.has(scopedKey))
172
+ return scopedGitHubBearerTokens.get(scopedKey) ?? null;
142
173
  const privateSession = readPrivateRemoteSessionToken(projectRoot);
143
- if (privateSession) {
144
- cachedGitHubBearerToken = privateSession;
145
- return cachedGitHubBearerToken;
146
- }
147
- const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
148
- if (envToken) {
149
- cachedGitHubBearerToken = envToken;
150
- return cachedGitHubBearerToken;
174
+ if (privateSession)
175
+ return privateSession;
176
+ return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
177
+ }
178
+ function readStoredGitHubAuthToken(projectRoot) {
179
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
180
+ if (!existsSync2(path))
181
+ return null;
182
+ try {
183
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
184
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
185
+ } catch {
186
+ return null;
151
187
  }
152
- const result = spawnSync("gh", ["auth", "token"], {
153
- encoding: "utf8",
154
- timeout: 5000,
155
- stdio: ["ignore", "pipe", "ignore"]
156
- });
157
- cachedGitHubBearerToken = result.status === 0 ? cleanToken(result.stdout) : null;
158
- return cachedGitHubBearerToken;
188
+ }
189
+ function readLocalConnectionFallbackToken(projectRoot) {
190
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
159
191
  }
160
192
  async function ensureServerForCli(projectRoot) {
161
193
  try {
162
194
  const selected = resolveSelectedConnection(projectRoot);
163
195
  if (selected?.connection.kind === "remote") {
196
+ reportServerPhase(`Connecting to ${selected.alias}\u2026`);
197
+ const authToken = readGitHubBearerTokenForRemote(projectRoot);
198
+ const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
164
199
  return {
165
200
  baseUrl: selected.connection.baseUrl,
166
- authToken: readGitHubBearerTokenForRemote(projectRoot),
167
- connectionKind: "remote"
201
+ authToken,
202
+ connectionKind: "remote",
203
+ serverProjectRoot
168
204
  };
169
205
  }
206
+ reportServerPhase("Starting local Rig server\u2026");
170
207
  const connection = await ensureLocalRigServerConnection(projectRoot);
171
208
  return {
172
209
  baseUrl: connection.baseUrl,
173
- authToken: connection.authToken,
174
- connectionKind: "local"
210
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
211
+ connectionKind: "local",
212
+ serverProjectRoot: resolve2(projectRoot)
175
213
  };
176
214
  } catch (error) {
177
215
  if (error instanceof Error) {
178
- throw new CliError2(error.message, 1);
216
+ throw new CliError(error.message, 1);
179
217
  }
180
218
  throw error;
181
219
  }
182
220
  }
221
+ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
222
+ const repo = readRepoConnection(projectRoot);
223
+ const slug = repo?.project?.trim();
224
+ if (!slug)
225
+ return null;
226
+ try {
227
+ const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
228
+ headers: mergeHeaders(undefined, authToken)
229
+ });
230
+ if (!response.ok)
231
+ return null;
232
+ const payload = await response.json();
233
+ const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
234
+ const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
235
+ const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
236
+ const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
237
+ if (path)
238
+ writeRepoServerProjectRoot(projectRoot, path);
239
+ return path;
240
+ } catch {
241
+ return null;
242
+ }
243
+ }
183
244
  function mergeHeaders(headers, authToken) {
184
245
  const merged = new Headers(headers);
185
246
  if (authToken) {
@@ -202,12 +263,65 @@ function diagnosticMessage(payload) {
202
263
  });
203
264
  return messages.length > 0 ? messages.join("; ") : null;
204
265
  }
266
+ var serverReachabilityCache = new Map;
267
+ async function probeServerReachability(baseUrl, authToken) {
268
+ try {
269
+ const response = await fetch(`${baseUrl.replace(/\/+$/, "")}/api/server/status`, {
270
+ headers: mergeHeaders(undefined, authToken),
271
+ signal: AbortSignal.timeout(1500)
272
+ });
273
+ return response.ok;
274
+ } catch {
275
+ return false;
276
+ }
277
+ }
278
+ function cachedServerReachability(projectRoot, baseUrl, authToken) {
279
+ const key = resolve2(projectRoot);
280
+ const cached = serverReachabilityCache.get(key);
281
+ if (cached)
282
+ return cached;
283
+ const probe = probeServerReachability(baseUrl, authToken);
284
+ serverReachabilityCache.set(key, probe);
285
+ return probe;
286
+ }
287
+ function describeSelectedServer(projectRoot, server) {
288
+ try {
289
+ const selected = resolveSelectedConnection(projectRoot);
290
+ if (selected) {
291
+ return {
292
+ alias: selected.alias,
293
+ target: selected.connection.kind === "remote" ? selected.connection.baseUrl : server.baseUrl
294
+ };
295
+ }
296
+ } catch {}
297
+ return { alias: server.connectionKind === "remote" ? "remote" : "local", target: server.baseUrl };
298
+ }
299
+ async function buildServerFailureContext(projectRoot, server) {
300
+ const { alias, target } = describeSelectedServer(projectRoot, server);
301
+ const reachable = await cachedServerReachability(projectRoot, server.baseUrl, server.authToken);
302
+ const reachability = reachable ? "server is reachable" : "server is unreachable";
303
+ return {
304
+ contextLine: `Currently connected to: ${alias} at ${target} (${reachability}).`,
305
+ hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
306
+ };
307
+ }
205
308
  async function requestServerJson(context, pathname, init = {}) {
206
309
  const server = await ensureServerForCli(context.projectRoot);
207
- const response = await fetch(`${server.baseUrl}${pathname}`, {
208
- ...init,
209
- headers: mergeHeaders(init.headers, server.authToken)
210
- });
310
+ const headers = mergeHeaders(init.headers, server.authToken);
311
+ if (server.serverProjectRoot)
312
+ headers.set("x-rig-project-root", server.serverProjectRoot);
313
+ reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
314
+ let response;
315
+ try {
316
+ response = await fetch(`${server.baseUrl}${pathname}`, {
317
+ ...init,
318
+ headers
319
+ });
320
+ } catch (error) {
321
+ const failure = await buildServerFailureContext(context.projectRoot, server);
322
+ throw new CliError(`Rig server request failed: ${error instanceof Error ? error.message : String(error)}
323
+ ${failure.contextLine}`, 1, { hint: failure.hint });
324
+ }
211
325
  const text = await response.text();
212
326
  const payload = text.trim().length > 0 ? (() => {
213
327
  try {
@@ -219,7 +333,9 @@ async function requestServerJson(context, pathname, init = {}) {
219
333
  if (!response.ok) {
220
334
  const diagnostics = diagnosticMessage(payload);
221
335
  const detail = diagnostics ?? (text || response.statusText);
222
- throw new CliError2(`Rig server request failed (${response.status}): ${detail}`, 1);
336
+ const failure = await buildServerFailureContext(context.projectRoot, server);
337
+ throw new CliError(`Rig server request failed (${response.status}): ${detail}
338
+ ${failure.contextLine}`, 1, { hint: failure.hint });
223
339
  }
224
340
  return payload;
225
341
  }
@@ -235,6 +351,138 @@ async function postGitHubTokenViaServer(context, token, options = {}) {
235
351
  });
236
352
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
237
353
  }
354
+ var RESUMABLE_RUN_STATUSES = new Set([
355
+ "created",
356
+ "preparing",
357
+ "running",
358
+ "validating",
359
+ "reviewing",
360
+ "stopped",
361
+ "failed",
362
+ "needs-attention",
363
+ "needs_attention"
364
+ ]);
365
+
366
+ // packages/cli/src/commands/_async-ui.ts
367
+ import pc from "picocolors";
368
+
369
+ // packages/cli/src/commands/_spinner.ts
370
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
371
+ function createTtySpinner(input) {
372
+ const output = input.output ?? process.stdout;
373
+ const isTty = output.isTTY === true;
374
+ const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
375
+ let label = input.label;
376
+ let frame = 0;
377
+ let paused = false;
378
+ let stopped = false;
379
+ let lastPrintedLabel = "";
380
+ const render = () => {
381
+ if (stopped || paused)
382
+ return;
383
+ if (!isTty) {
384
+ if (label !== lastPrintedLabel) {
385
+ output.write(`${label}
386
+ `);
387
+ lastPrintedLabel = label;
388
+ }
389
+ return;
390
+ }
391
+ frame = (frame + 1) % frames.length;
392
+ const glyph = frames[frame] ?? frames[0] ?? "";
393
+ output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
394
+ };
395
+ const clearLine = () => {
396
+ if (isTty)
397
+ output.write("\r\x1B[2K");
398
+ };
399
+ render();
400
+ const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
401
+ return {
402
+ setLabel(next) {
403
+ label = next;
404
+ render();
405
+ },
406
+ pause() {
407
+ paused = true;
408
+ clearLine();
409
+ },
410
+ resume() {
411
+ if (stopped)
412
+ return;
413
+ paused = false;
414
+ render();
415
+ },
416
+ stop(finalLine) {
417
+ if (stopped)
418
+ return;
419
+ stopped = true;
420
+ if (timer)
421
+ clearInterval(timer);
422
+ clearLine();
423
+ if (finalLine)
424
+ output.write(`${finalLine}
425
+ `);
426
+ }
427
+ };
428
+ }
429
+
430
+ // packages/cli/src/commands/_async-ui.ts
431
+ var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
432
+ var DONE_SYMBOL = pc.green("\u25C7");
433
+ var FAIL_SYMBOL = pc.red("\u25A0");
434
+ var activeUpdate = null;
435
+ async function withSpinner(label, work, options = {}) {
436
+ if (options.outputMode === "json") {
437
+ return work(() => {});
438
+ }
439
+ if (activeUpdate) {
440
+ const outer = activeUpdate;
441
+ outer(label);
442
+ return work(outer);
443
+ }
444
+ const output = options.output ?? process.stderr;
445
+ const isTty = output.isTTY === true;
446
+ let lastLabel = label;
447
+ if (!isTty) {
448
+ output.write(`${label}
449
+ `);
450
+ const update2 = (next) => {
451
+ lastLabel = next;
452
+ };
453
+ activeUpdate = update2;
454
+ const previousListener2 = setServerPhaseListener(update2);
455
+ try {
456
+ return await work(update2);
457
+ } finally {
458
+ activeUpdate = null;
459
+ setServerPhaseListener(previousListener2);
460
+ }
461
+ }
462
+ const spinner = createTtySpinner({
463
+ label,
464
+ output,
465
+ frames: CLACK_SPINNER_FRAMES,
466
+ styleFrame: (frame) => pc.magenta(frame)
467
+ });
468
+ const update = (next) => {
469
+ lastLabel = next;
470
+ spinner.setLabel(next);
471
+ };
472
+ activeUpdate = update;
473
+ const previousListener = setServerPhaseListener(update);
474
+ try {
475
+ const result = await work(update);
476
+ spinner.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
477
+ return result;
478
+ } catch (error) {
479
+ spinner.stop(`${FAIL_SYMBOL} ${lastLabel}`);
480
+ throw error;
481
+ } finally {
482
+ activeUpdate = null;
483
+ setServerPhaseListener(previousListener);
484
+ }
485
+ }
238
486
 
239
487
  // packages/cli/src/commands/github.ts
240
488
  function printPayload(context, payload, fallback) {
@@ -244,49 +492,50 @@ function printPayload(context, payload, fallback) {
244
492
  console.log(fallback);
245
493
  }
246
494
  function readGhToken() {
247
- const result = spawnSync2("gh", ["auth", "token"], { encoding: "utf8" });
495
+ const result = spawnSync("gh", ["auth", "token"], { encoding: "utf8" });
248
496
  if (result.status !== 0) {
249
497
  const detail = result.stderr?.trim() || result.stdout?.trim() || "gh auth token failed";
250
- throw new CliError2(`Could not import GitHub token from gh: ${detail}`, 1);
498
+ throw new CliError(`Could not import GitHub token from gh: ${detail}`, 1, { hint: "Sign in first with `gh auth login`, or store a token directly: `rig github auth token --token <token>`." });
251
499
  }
252
500
  const token = result.stdout.trim();
253
501
  if (!token)
254
- throw new CliError2("gh auth token returned an empty token.", 1);
502
+ throw new CliError("gh auth token returned an empty token.", 1, { hint: "Sign in with `gh auth login`, then re-run `rig github auth import-gh`." });
255
503
  return token;
256
504
  }
257
505
  async function executeGithub(context, args) {
258
506
  const [group, command, ...rest] = args;
259
507
  if (group !== "auth") {
260
- throw new CliError2("Usage: rig github auth <status|import-gh|token>", 1);
508
+ throw new CliError("Usage: rig github auth <status|import-gh|token>", 1);
261
509
  }
262
510
  switch (command) {
263
511
  case "status": {
264
512
  if (rest.length > 0)
265
- throw new CliError2("Usage: rig github auth status", 1);
266
- const status = await getGitHubAuthStatusViaServer(context);
513
+ throw new CliError("Usage: rig github auth status", 1);
514
+ const status = await withSpinner("Checking GitHub auth on the server\u2026", () => getGitHubAuthStatusViaServer(context), { outputMode: context.outputMode });
267
515
  printPayload(context, status, `GitHub auth: ${status.authenticated ? "authenticated" : "unauthenticated"}`);
268
516
  return { ok: true, group: "github", command: "auth status", details: status };
269
517
  }
270
518
  case "token": {
271
519
  const parsed = takeOption(rest, "--token");
272
520
  if (parsed.rest.length > 0)
273
- throw new CliError2("Usage: rig github auth token --token <token>", 1);
521
+ throw new CliError("Usage: rig github auth token --token <token>", 1);
274
522
  const token = parsed.value?.trim();
275
523
  if (!token)
276
- throw new CliError2("Missing --token value.", 1);
277
- const result = await postGitHubTokenViaServer(context, token);
524
+ throw new CliError("Missing --token value.", 1, { hint: "Re-run as `rig github auth token --token <token>`." });
525
+ const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token), { outputMode: context.outputMode });
278
526
  printPayload(context, result, "GitHub token stored on the selected Rig server.");
279
527
  return { ok: true, group: "github", command: "auth token", details: result };
280
528
  }
281
529
  case "import-gh": {
282
530
  if (rest.length > 0)
283
- throw new CliError2("Usage: rig github auth import-gh", 1);
284
- const result = await postGitHubTokenViaServer(context, readGhToken());
531
+ throw new CliError("Usage: rig github auth import-gh", 1);
532
+ const importedToken = readGhToken();
533
+ const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken), { outputMode: context.outputMode });
285
534
  printPayload(context, result, "GitHub token imported from gh and stored on the selected Rig server.");
286
535
  return { ok: true, group: "github", command: "auth import-gh", details: result };
287
536
  }
288
537
  default:
289
- throw new CliError2("Usage: rig github auth <status|import-gh|token>", 1);
538
+ throw new CliError("Usage: rig github auth <status|import-gh|token>", 1);
290
539
  }
291
540
  }
292
541
  export {