@h-rig/cli 0.0.6-alpha.67 → 0.0.6-alpha.69

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.
@@ -0,0 +1,152 @@
1
+ // @bun
2
+ // packages/cli/src/commands/_async-ui.ts
3
+ import pc from "picocolors";
4
+
5
+ // packages/cli/src/commands/_spinner.ts
6
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
7
+ function createTtySpinner(input) {
8
+ const output = input.output ?? process.stdout;
9
+ const isTty = output.isTTY === true;
10
+ const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
11
+ let label = input.label;
12
+ let frame = 0;
13
+ let paused = false;
14
+ let stopped = false;
15
+ let lastPrintedLabel = "";
16
+ const render = () => {
17
+ if (stopped || paused)
18
+ return;
19
+ if (!isTty) {
20
+ if (label !== lastPrintedLabel) {
21
+ output.write(`${label}
22
+ `);
23
+ lastPrintedLabel = label;
24
+ }
25
+ return;
26
+ }
27
+ frame = (frame + 1) % frames.length;
28
+ const glyph = frames[frame] ?? frames[0] ?? "";
29
+ output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
30
+ };
31
+ const clearLine = () => {
32
+ if (isTty)
33
+ output.write("\r\x1B[2K");
34
+ };
35
+ render();
36
+ const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
37
+ return {
38
+ setLabel(next) {
39
+ label = next;
40
+ render();
41
+ },
42
+ pause() {
43
+ paused = true;
44
+ clearLine();
45
+ },
46
+ resume() {
47
+ if (stopped)
48
+ return;
49
+ paused = false;
50
+ render();
51
+ },
52
+ stop(finalLine) {
53
+ if (stopped)
54
+ return;
55
+ stopped = true;
56
+ if (timer)
57
+ clearInterval(timer);
58
+ clearLine();
59
+ if (finalLine)
60
+ output.write(`${finalLine}
61
+ `);
62
+ }
63
+ };
64
+ }
65
+
66
+ // packages/cli/src/runner.ts
67
+ import { EventBus } from "@rig/runtime/control-plane/runtime/events";
68
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
69
+ import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
70
+ import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
71
+
72
+ // packages/cli/src/commands/_server-client.ts
73
+ import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
74
+ var scopedGitHubBearerTokens = new Map;
75
+ var serverPhaseListener = null;
76
+ function setServerPhaseListener(listener) {
77
+ const previous = serverPhaseListener;
78
+ serverPhaseListener = listener;
79
+ return previous;
80
+ }
81
+ var serverReachabilityCache = new Map;
82
+ var RESUMABLE_RUN_STATUSES = new Set([
83
+ "created",
84
+ "preparing",
85
+ "running",
86
+ "validating",
87
+ "reviewing",
88
+ "stopped",
89
+ "failed",
90
+ "needs-attention",
91
+ "needs_attention"
92
+ ]);
93
+
94
+ // packages/cli/src/commands/_async-ui.ts
95
+ var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
96
+ var DONE_SYMBOL = pc.green("\u25C7");
97
+ var FAIL_SYMBOL = pc.red("\u25A0");
98
+ var activeUpdate = null;
99
+ async function withSpinner(label, work, options = {}) {
100
+ if (options.outputMode === "json") {
101
+ return work(() => {});
102
+ }
103
+ if (activeUpdate) {
104
+ const outer = activeUpdate;
105
+ outer(label);
106
+ return work(outer);
107
+ }
108
+ const output = options.output ?? process.stderr;
109
+ const isTty = output.isTTY === true;
110
+ let lastLabel = label;
111
+ if (!isTty) {
112
+ output.write(`${label}
113
+ `);
114
+ const update2 = (next) => {
115
+ lastLabel = next;
116
+ };
117
+ activeUpdate = update2;
118
+ const previousListener2 = setServerPhaseListener(update2);
119
+ try {
120
+ return await work(update2);
121
+ } finally {
122
+ activeUpdate = null;
123
+ setServerPhaseListener(previousListener2);
124
+ }
125
+ }
126
+ const spinner = createTtySpinner({
127
+ label,
128
+ output,
129
+ frames: CLACK_SPINNER_FRAMES,
130
+ styleFrame: (frame) => pc.magenta(frame)
131
+ });
132
+ const update = (next) => {
133
+ lastLabel = next;
134
+ spinner.setLabel(next);
135
+ };
136
+ activeUpdate = update;
137
+ const previousListener = setServerPhaseListener(update);
138
+ try {
139
+ const result = await work(update);
140
+ spinner.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
141
+ return result;
142
+ } catch (error) {
143
+ spinner.stop(`${FAIL_SYMBOL} ${lastLabel}`);
144
+ throw error;
145
+ } finally {
146
+ activeUpdate = null;
147
+ setServerPhaseListener(previousListener);
148
+ }
149
+ }
150
+ export {
151
+ withSpinner
152
+ };
@@ -126,6 +126,10 @@ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
126
126
  import { resolve as resolve2 } from "path";
127
127
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
128
128
  var scopedGitHubBearerTokens = new Map;
129
+ var serverPhaseListener = null;
130
+ function reportServerPhase(label) {
131
+ serverPhaseListener?.(label);
132
+ }
129
133
  function cleanToken(value) {
130
134
  const trimmed = value?.trim();
131
135
  return trimmed ? trimmed : null;
@@ -168,6 +172,7 @@ async function ensureServerForCli(projectRoot) {
168
172
  try {
169
173
  const selected = resolveSelectedConnection(projectRoot);
170
174
  if (selected?.connection.kind === "remote") {
175
+ reportServerPhase(`Connecting to ${selected.alias}\u2026`);
171
176
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
172
177
  const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
173
178
  return {
@@ -177,6 +182,7 @@ async function ensureServerForCli(projectRoot) {
177
182
  serverProjectRoot
178
183
  };
179
184
  }
185
+ reportServerPhase("Starting local Rig server\u2026");
180
186
  const connection = await ensureLocalRigServerConnection(projectRoot);
181
187
  return {
182
188
  baseUrl: connection.baseUrl,
@@ -283,6 +289,7 @@ async function requestServerJson(context, pathname, init = {}) {
283
289
  const headers = mergeHeaders(init.headers, server.authToken);
284
290
  if (server.serverProjectRoot)
285
291
  headers.set("x-rig-project-root", server.serverProjectRoot);
292
+ reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
286
293
  let response;
287
294
  try {
288
295
  response = await fetch(`${server.baseUrl}${pathname}`, {
@@ -311,6 +318,17 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
311
318
  }
312
319
  return payload;
313
320
  }
321
+ var RESUMABLE_RUN_STATUSES = new Set([
322
+ "created",
323
+ "preparing",
324
+ "running",
325
+ "validating",
326
+ "reviewing",
327
+ "stopped",
328
+ "failed",
329
+ "needs-attention",
330
+ "needs_attention"
331
+ ]);
314
332
 
315
333
  // packages/cli/src/commands/_parsers.ts
316
334
  async function loadRigConfigOrNull(projectRoot) {
@@ -514,7 +532,10 @@ async function runRigDoctorChecks(options) {
514
532
  const bunVersion = options.bunVersion ?? Bun.version;
515
533
  const request = options.requestJson ?? ((pathname, init) => requestServerJson({ projectRoot }, pathname, init));
516
534
  const loadConfig = options.loadConfig ?? loadRigConfigOrNull;
535
+ const progress = options.onProgress ?? (() => {});
536
+ progress("Checking local toolchain\u2026");
517
537
  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`)."));
538
+ progress("Loading rig.config\u2026");
518
539
  const loadedConfig = await loadConfig(projectRoot).catch(() => null);
519
540
  const config = loadedConfig ?? loadFallbackConfig(projectRoot);
520
541
  const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync4(resolve4(projectRoot, name)));
@@ -533,6 +554,7 @@ async function runRigDoctorChecks(options) {
533
554
  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));
534
555
  let server = null;
535
556
  try {
557
+ progress("Connecting to the selected Rig server\u2026");
536
558
  server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
537
559
  checks.push(check("server", "Rig server reachable", "pass", `${server.connectionKind} ${server.baseUrl}`));
538
560
  } catch (error) {
@@ -540,18 +562,21 @@ async function runRigDoctorChecks(options) {
540
562
  }
541
563
  if (server || options.requestJson) {
542
564
  try {
565
+ progress("Checking server status\u2026");
543
566
  const status = await request("/api/server/status");
544
567
  checks.push(check("server-status", "server project status", "pass", JSON.stringify(status).slice(0, 180)));
545
568
  } catch (error) {
546
569
  checks.push(check("server-status", "server project status", "fail", errorMessage(error), "Run `rig doctor` after the selected server is reachable."));
547
570
  }
548
571
  try {
572
+ progress("Checking GitHub auth\u2026");
549
573
  const auth = await request("/api/github/auth/status");
550
574
  checks.push(isAuthenticated(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>`."));
551
575
  } catch (error) {
552
576
  checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig and ensure the server exposes auth status."));
553
577
  }
554
578
  try {
579
+ progress("Checking GitHub repo permissions\u2026");
555
580
  const permissions = await request("/api/github/repo/permissions");
556
581
  const allowed = permissionAllowsPr(permissions);
557
582
  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."));
@@ -559,6 +584,7 @@ async function runRigDoctorChecks(options) {
559
584
  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."));
560
585
  }
561
586
  try {
587
+ progress("Checking GitHub issue labels\u2026");
562
588
  const labels = await request("/api/workspace/task-labels");
563
589
  const ready = labelsReady(labels);
564
590
  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."));
@@ -566,6 +592,7 @@ async function runRigDoctorChecks(options) {
566
592
  checks.push(check("task-labels", "GitHub issue labels", "warn", errorMessage(error), "Run `rig init`/`rig doctor` after label setup is wired on the server."));
567
593
  }
568
594
  try {
595
+ progress("Checking task projection\u2026");
569
596
  const projection = await request("/api/workspace/task-projection");
570
597
  checks.push(check("task-projection", "task projection", "pass", JSON.stringify(projection).slice(0, 180)));
571
598
  } catch (error) {
@@ -574,6 +601,7 @@ async function runRigDoctorChecks(options) {
574
601
  const slug = projectStatusSlug(projectRoot, config);
575
602
  if (slug) {
576
603
  try {
604
+ progress("Checking server project checkout\u2026");
577
605
  const project = await request(`/api/projects/${encodeURIComponent(slug)}`);
578
606
  checks.push(check("remote-checkout", "server project checkout", "pass", JSON.stringify(project).slice(0, 180)));
579
607
  } catch (error) {
@@ -588,6 +616,7 @@ async function runRigDoctorChecks(options) {
588
616
  }
589
617
  checks.push(githubProjectsCheck(config));
590
618
  checks.push(prMergeCheck(config));
619
+ progress("Checking Pi installation\u2026");
591
620
  const piChecks = await (options.piChecks ?? (() => buildPiSetupChecks()))().catch((error) => [{
592
621
  ok: false,
593
622
  label: "pi/pi-rig checks",
@@ -121,6 +121,15 @@ function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
121
121
 
122
122
  // packages/cli/src/commands/_server-client.ts
123
123
  var scopedGitHubBearerTokens = new Map;
124
+ var serverPhaseListener = null;
125
+ function setServerPhaseListener(listener) {
126
+ const previous = serverPhaseListener;
127
+ serverPhaseListener = listener;
128
+ return previous;
129
+ }
130
+ function reportServerPhase(label) {
131
+ serverPhaseListener?.(label);
132
+ }
124
133
  function cleanToken(value) {
125
134
  const trimmed = value?.trim();
126
135
  return trimmed ? trimmed : null;
@@ -163,6 +172,7 @@ async function ensureServerForCli(projectRoot) {
163
172
  try {
164
173
  const selected = resolveSelectedConnection(projectRoot);
165
174
  if (selected?.connection.kind === "remote") {
175
+ reportServerPhase(`Connecting to ${selected.alias}\u2026`);
166
176
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
167
177
  const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
168
178
  return {
@@ -172,6 +182,7 @@ async function ensureServerForCli(projectRoot) {
172
182
  serverProjectRoot
173
183
  };
174
184
  }
185
+ reportServerPhase("Starting local Rig server\u2026");
175
186
  const connection = await ensureLocalRigServerConnection(projectRoot);
176
187
  return {
177
188
  baseUrl: connection.baseUrl,
@@ -278,6 +289,7 @@ async function requestServerJson(context, pathname, init = {}) {
278
289
  const headers = mergeHeaders(init.headers, server.authToken);
279
290
  if (server.serverProjectRoot)
280
291
  headers.set("x-rig-project-root", server.serverProjectRoot);
292
+ reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
281
293
  let response;
282
294
  try {
283
295
  response = await fetch(`${server.baseUrl}${pathname}`, {
@@ -328,6 +340,17 @@ async function getRunTimelineViaServer(context, runId, options = {}) {
328
340
  const payload = await requestServerJson(context, `${url.pathname}${url.search}`);
329
341
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : { entries: [] };
330
342
  }
343
+ var RESUMABLE_RUN_STATUSES = new Set([
344
+ "created",
345
+ "preparing",
346
+ "running",
347
+ "validating",
348
+ "reviewing",
349
+ "stopped",
350
+ "failed",
351
+ "needs-attention",
352
+ "needs_attention"
353
+ ]);
331
354
  async function stopRunViaServer(context, runId) {
332
355
  const payload = await requestServerJson(context, "/api/runs/stop", {
333
356
  method: "POST",
@@ -592,7 +615,12 @@ async function attachRunBundledPiFrontend(context, input) {
592
615
  };
593
616
  let detached = false;
594
617
  try {
595
- await runPiMain([], {
618
+ await runPiMain([
619
+ "--no-extensions",
620
+ "--no-skills",
621
+ "--no-prompt-templates",
622
+ "--no-context-files"
623
+ ], {
596
624
  extensionFactories: [piRigExtensionFactory]
597
625
  });
598
626
  detached = true;
@@ -615,6 +643,127 @@ async function attachRunBundledPiFrontend(context, input) {
615
643
  };
616
644
  }
617
645
 
646
+ // packages/cli/src/commands/_async-ui.ts
647
+ import pc from "picocolors";
648
+
649
+ // packages/cli/src/commands/_spinner.ts
650
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
651
+ function createTtySpinner(input) {
652
+ const output = input.output ?? process.stdout;
653
+ const isTty = output.isTTY === true;
654
+ const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
655
+ let label = input.label;
656
+ let frame = 0;
657
+ let paused = false;
658
+ let stopped = false;
659
+ let lastPrintedLabel = "";
660
+ const render = () => {
661
+ if (stopped || paused)
662
+ return;
663
+ if (!isTty) {
664
+ if (label !== lastPrintedLabel) {
665
+ output.write(`${label}
666
+ `);
667
+ lastPrintedLabel = label;
668
+ }
669
+ return;
670
+ }
671
+ frame = (frame + 1) % frames.length;
672
+ const glyph = frames[frame] ?? frames[0] ?? "";
673
+ output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
674
+ };
675
+ const clearLine = () => {
676
+ if (isTty)
677
+ output.write("\r\x1B[2K");
678
+ };
679
+ render();
680
+ const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
681
+ return {
682
+ setLabel(next) {
683
+ label = next;
684
+ render();
685
+ },
686
+ pause() {
687
+ paused = true;
688
+ clearLine();
689
+ },
690
+ resume() {
691
+ if (stopped)
692
+ return;
693
+ paused = false;
694
+ render();
695
+ },
696
+ stop(finalLine) {
697
+ if (stopped)
698
+ return;
699
+ stopped = true;
700
+ if (timer)
701
+ clearInterval(timer);
702
+ clearLine();
703
+ if (finalLine)
704
+ output.write(`${finalLine}
705
+ `);
706
+ }
707
+ };
708
+ }
709
+
710
+ // packages/cli/src/commands/_async-ui.ts
711
+ var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
712
+ var DONE_SYMBOL = pc.green("\u25C7");
713
+ var FAIL_SYMBOL = pc.red("\u25A0");
714
+ var activeUpdate = null;
715
+ async function withSpinner(label, work, options = {}) {
716
+ if (options.outputMode === "json") {
717
+ return work(() => {});
718
+ }
719
+ if (activeUpdate) {
720
+ const outer = activeUpdate;
721
+ outer(label);
722
+ return work(outer);
723
+ }
724
+ const output = options.output ?? process.stderr;
725
+ const isTty = output.isTTY === true;
726
+ let lastLabel = label;
727
+ if (!isTty) {
728
+ output.write(`${label}
729
+ `);
730
+ const update2 = (next) => {
731
+ lastLabel = next;
732
+ };
733
+ activeUpdate = update2;
734
+ const previousListener2 = setServerPhaseListener(update2);
735
+ try {
736
+ return await work(update2);
737
+ } finally {
738
+ activeUpdate = null;
739
+ setServerPhaseListener(previousListener2);
740
+ }
741
+ }
742
+ const spinner = createTtySpinner({
743
+ label,
744
+ output,
745
+ frames: CLACK_SPINNER_FRAMES,
746
+ styleFrame: (frame) => pc.magenta(frame)
747
+ });
748
+ const update = (next) => {
749
+ lastLabel = next;
750
+ spinner.setLabel(next);
751
+ };
752
+ activeUpdate = update;
753
+ const previousListener = setServerPhaseListener(update);
754
+ try {
755
+ const result = await work(update);
756
+ spinner.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
757
+ return result;
758
+ } catch (error) {
759
+ spinner.stop(`${FAIL_SYMBOL} ${lastLabel}`);
760
+ throw error;
761
+ } finally {
762
+ activeUpdate = null;
763
+ setServerPhaseListener(previousListener);
764
+ }
765
+ }
766
+
618
767
  // packages/cli/src/commands/_operator-view.ts
619
768
  var TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
620
769
  function runStatusFromPayload(payload) {
@@ -657,8 +806,9 @@ async function readOperatorSnapshot(context, runId, options = {}) {
657
806
  }
658
807
  async function attachRunOperatorView(context, input) {
659
808
  let steered = false;
660
- if (input.message?.trim()) {
661
- await sendRunPiPromptViaServer(context, input.runId, input.message.trim(), "steer").catch(() => steerRunViaServer(context, input.runId, input.message.trim()));
809
+ const attachMessage = input.message?.trim();
810
+ if (attachMessage) {
811
+ await withSpinner("Queueing steering message\u2026", () => sendRunPiPromptViaServer(context, input.runId, attachMessage, "steer").catch(() => steerRunViaServer(context, input.runId, attachMessage)), { outputMode: context.outputMode });
662
812
  steered = true;
663
813
  }
664
814
  if (input.follow && !input.once && input.interactive !== false && context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY)) {
@@ -668,7 +818,7 @@ async function attachRunOperatorView(context, input) {
668
818
  });
669
819
  }
670
820
  const surface = createOperatorSurface({ interactive: input.interactive !== false });
671
- let snapshot = await readOperatorSnapshot(context, input.runId);
821
+ let snapshot = await withSpinner(`Connecting to run ${input.runId}\u2026`, () => readOperatorSnapshot(context, input.runId), { outputMode: context.outputMode });
672
822
  if (context.outputMode === "text") {
673
823
  surface.renderSnapshot(snapshot);
674
824
  surface.renderTimeline(snapshot.timeline);
@@ -128,6 +128,10 @@ function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
128
128
 
129
129
  // packages/cli/src/commands/_server-client.ts
130
130
  var scopedGitHubBearerTokens = new Map;
131
+ var serverPhaseListener = null;
132
+ function reportServerPhase(label) {
133
+ serverPhaseListener?.(label);
134
+ }
131
135
  function cleanToken(value) {
132
136
  const trimmed = value?.trim();
133
137
  return trimmed ? trimmed : null;
@@ -170,6 +174,7 @@ async function ensureServerForCli(projectRoot) {
170
174
  try {
171
175
  const selected = resolveSelectedConnection(projectRoot);
172
176
  if (selected?.connection.kind === "remote") {
177
+ reportServerPhase(`Connecting to ${selected.alias}\u2026`);
173
178
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
174
179
  const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
175
180
  return {
@@ -179,6 +184,7 @@ async function ensureServerForCli(projectRoot) {
179
184
  serverProjectRoot
180
185
  };
181
186
  }
187
+ reportServerPhase("Starting local Rig server\u2026");
182
188
  const connection = await ensureLocalRigServerConnection(projectRoot);
183
189
  return {
184
190
  baseUrl: connection.baseUrl,
@@ -285,6 +291,7 @@ async function requestServerJson(context, pathname, init = {}) {
285
291
  const headers = mergeHeaders(init.headers, server.authToken);
286
292
  if (server.serverProjectRoot)
287
293
  headers.set("x-rig-project-root", server.serverProjectRoot);
294
+ reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
288
295
  let response;
289
296
  try {
290
297
  response = await fetch(`${server.baseUrl}${pathname}`, {
@@ -317,6 +324,17 @@ async function getRunDetailsViaServer(context, runId) {
317
324
  const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}`);
318
325
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
319
326
  }
327
+ var RESUMABLE_RUN_STATUSES = new Set([
328
+ "created",
329
+ "preparing",
330
+ "running",
331
+ "validating",
332
+ "reviewing",
333
+ "stopped",
334
+ "failed",
335
+ "needs-attention",
336
+ "needs_attention"
337
+ ]);
320
338
 
321
339
  // packages/cli/src/commands/_pi-frontend.ts
322
340
  function setTemporaryEnv(updates) {
@@ -360,7 +378,12 @@ async function attachRunBundledPiFrontend(context, input) {
360
378
  };
361
379
  let detached = false;
362
380
  try {
363
- await runPiMain([], {
381
+ await runPiMain([
382
+ "--no-extensions",
383
+ "--no-skills",
384
+ "--no-prompt-templates",
385
+ "--no-context-files"
386
+ ], {
364
387
  extensionFactories: [piRigExtensionFactory]
365
388
  });
366
389
  detached = true;
@@ -120,6 +120,10 @@ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
120
120
  import { resolve as resolve2 } from "path";
121
121
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
122
122
  var scopedGitHubBearerTokens = new Map;
123
+ var serverPhaseListener = null;
124
+ function reportServerPhase(label) {
125
+ serverPhaseListener?.(label);
126
+ }
123
127
  function cleanToken(value) {
124
128
  const trimmed = value?.trim();
125
129
  return trimmed ? trimmed : null;
@@ -162,6 +166,7 @@ async function ensureServerForCli(projectRoot) {
162
166
  try {
163
167
  const selected = resolveSelectedConnection(projectRoot);
164
168
  if (selected?.connection.kind === "remote") {
169
+ reportServerPhase(`Connecting to ${selected.alias}\u2026`);
165
170
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
166
171
  const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
167
172
  return {
@@ -171,6 +176,7 @@ async function ensureServerForCli(projectRoot) {
171
176
  serverProjectRoot
172
177
  };
173
178
  }
179
+ reportServerPhase("Starting local Rig server\u2026");
174
180
  const connection = await ensureLocalRigServerConnection(projectRoot);
175
181
  return {
176
182
  baseUrl: connection.baseUrl,
@@ -277,6 +283,7 @@ async function requestServerJson(context, pathname, init = {}) {
277
283
  const headers = mergeHeaders(init.headers, server.authToken);
278
284
  if (server.serverProjectRoot)
279
285
  headers.set("x-rig-project-root", server.serverProjectRoot);
286
+ reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
280
287
  let response;
281
288
  try {
282
289
  response = await fetch(`${server.baseUrl}${pathname}`, {
@@ -305,6 +312,17 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
305
312
  }
306
313
  return payload;
307
314
  }
315
+ var RESUMABLE_RUN_STATUSES = new Set([
316
+ "created",
317
+ "preparing",
318
+ "running",
319
+ "validating",
320
+ "reviewing",
321
+ "stopped",
322
+ "failed",
323
+ "needs-attention",
324
+ "needs_attention"
325
+ ]);
308
326
 
309
327
  // packages/cli/src/commands/_preflight.ts
310
328
  function preflightCheck(id, label, status, detail, remediation) {