@h-rig/cli 0.0.6-alpha.76 → 0.0.6-alpha.78

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 (32) hide show
  1. package/dist/bin/rig.js +10130 -9246
  2. package/dist/src/app/board.js +1783 -0
  3. package/dist/src/app/drone-ui.js +294 -0
  4. package/dist/src/{commands/_tui-theme.js → app/theme.js} +16 -1
  5. package/dist/src/commands/_async-ui.js +74 -3
  6. package/dist/src/commands/_cli-format.js +107 -29
  7. package/dist/src/commands/_doctor-checks.js +3 -1
  8. package/dist/src/commands/_help-catalog.js +8 -70
  9. package/dist/src/commands/_operator-view.js +184 -7
  10. package/dist/src/commands/_pi-frontend.js +184 -7
  11. package/dist/src/commands/_preflight.js +3 -1
  12. package/dist/src/commands/_server-client.js +3 -1
  13. package/dist/src/commands/_snapshot-upload.js +3 -1
  14. package/dist/src/commands/_task-picker.js +132 -7
  15. package/dist/src/commands/browser.js +306 -30
  16. package/dist/src/commands/connect.js +146 -20
  17. package/dist/src/commands/doctor.js +77 -4
  18. package/dist/src/commands/github.js +77 -4
  19. package/dist/src/commands/inbox.js +171 -88
  20. package/dist/src/commands/init.js +349 -9
  21. package/dist/src/commands/inspect.js +77 -4
  22. package/dist/src/commands/run.js +214 -28
  23. package/dist/src/commands/server.js +149 -21
  24. package/dist/src/commands/setup.js +77 -4
  25. package/dist/src/commands/stats.js +109 -107
  26. package/dist/src/commands/task-report-bug.js +231 -40
  27. package/dist/src/commands/task-run-driver.js +3 -1
  28. package/dist/src/commands/task.js +355 -184
  29. package/dist/src/commands.js +10126 -9242
  30. package/dist/src/index.js +10131 -9247
  31. package/package.json +8 -9
  32. package/dist/src/commands/_operator-board.js +0 -730
@@ -1,7 +1,9 @@
1
1
  // @bun
2
2
  // packages/cli/src/commands/_help-catalog.ts
3
- import { intro, log, note, outro } from "@clack/prompts";
4
3
  import pc from "picocolors";
4
+ function helpCatalog() {
5
+ return { sections: TOP_LEVEL_SECTIONS, groups: ALL_GROUPS };
6
+ }
5
7
  var TOP_LEVEL_SECTIONS = [
6
8
  {
7
9
  title: "Pi console",
@@ -416,79 +418,14 @@ function suggestGroupCommandForWord(word) {
416
418
  }
417
419
  return null;
418
420
  }
419
- function shouldUseClackOutput() {
420
- return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
421
- }
422
421
  function printTopLevelHelp(state = {}) {
423
- if (!shouldUseClackOutput()) {
424
- console.log(renderTopLevelHelp());
425
- return;
426
- }
427
- console.log(renderRigBanner(state.version));
428
- console.log("");
429
- if (state.projectInitialized === false) {
430
- intro("no rig project in this directory");
431
- note([
432
- commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
433
- commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
434
- commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
435
- ].join(`
436
- `), "Get started");
437
- outro("After init: rig task run --next puts an agent on your next task.");
438
- return;
439
- }
440
- intro(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
441
- for (const section of TOP_LEVEL_SECTIONS) {
442
- note(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
443
- }
444
- log.info("More: rig help --advanced \xB7 rig <group> --help \xB7 rig --version");
445
- note([
446
- commandLine("--project <path>", "Use a project root instead of auto-discovery."),
447
- commandLine("--json", "Emit structured output for scripts/agents."),
448
- commandLine("--dry-run", "Print the command plan without mutating state.")
449
- ].join(`
450
- `), "Global options");
451
- outro("init \u2192 task run \u2192 attach (Pi console: watch + steer live) \u2192 inbox \u2192 merged.");
422
+ console.log(renderTopLevelHelp());
452
423
  }
453
424
  function printAdvancedHelp() {
454
- if (!shouldUseClackOutput()) {
455
- console.log(renderAdvancedHelp());
456
- return;
457
- }
458
- intro("rig advanced");
459
- note(ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)).join(`
460
- `), "Advanced commands");
461
- note(ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)).join(`
462
- `), "Advanced groups");
463
- outro("Primary daily flow: rig server \xB7 rig task \xB7 rig run \xB7 rig inbox.");
425
+ console.log(renderAdvancedHelp());
464
426
  }
465
427
  function printGroupHelpDocument(groupName) {
466
- const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
467
- if (!shouldUseClackOutput()) {
468
- console.log(rendered);
469
- return;
470
- }
471
- const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
472
- if (!group) {
473
- printTopLevelHelp();
474
- return;
475
- }
476
- intro(`rig ${group.name}`);
477
- note(group.summary, "Purpose");
478
- note(group.usage.join(`
479
- `), "Usage");
480
- note(group.commands.map((entry) => commandLine(entry.command, entry.description)).join(`
481
- `), "Commands");
482
- if (group.examples?.length)
483
- note(group.examples.map((line) => `$ ${line}`).join(`
484
- `), "Examples");
485
- if (group.next?.length)
486
- note(group.next.map((line) => `\u203A ${line}`).join(`
487
- `), "Next steps");
488
- if (group.advanced?.length)
489
- log.info(group.advanced.join(`
490
- `));
491
- outro("Run with --json when scripts need structured output.");
428
+ console.log(renderGroupHelp(groupName) ?? renderTopLevelHelp());
492
429
  }
493
430
  export {
494
431
  suggestGroupCommandForWord,
@@ -499,5 +436,6 @@ export {
499
436
  printTopLevelHelp,
500
437
  printGroupHelpDocument,
501
438
  printAdvancedHelp,
502
- listHelpGroups
439
+ listHelpGroups,
440
+ helpCatalog
503
441
  };
@@ -311,7 +311,9 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
311
311
  })() : null;
312
312
  if (!response.ok) {
313
313
  const diagnostics = diagnosticMessage(payload);
314
- const detail = diagnostics ?? (text || response.statusText);
314
+ const rawDetail = diagnostics ?? (text || response.statusText);
315
+ const detail = diagnostics ? rawDetail : rawDetail.split(`
316
+ `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
315
317
  const failure = await buildServerFailureContext(context.projectRoot, server);
316
318
  throw new CliError(`Rig server request failed (${response.status}): ${detail}
317
319
  ${failure.contextLine}`, 1, { hint: failure.hint });
@@ -569,8 +571,8 @@ function createOperatorSurface(options = {}) {
569
571
  }
570
572
 
571
573
  // packages/cli/src/commands/_pi-frontend.ts
572
- import { mkdtempSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
573
- import { tmpdir } from "os";
574
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, mkdtempSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "fs";
575
+ import { homedir as homedir2, tmpdir } from "os";
574
576
  import { join } from "path";
575
577
  import { main as runPiMain } from "@earendil-works/pi-coding-agent";
576
578
  import createPiRigExtension from "@rig/pi-rig";
@@ -639,8 +641,79 @@ function createTtySpinner(input) {
639
641
  };
640
642
  }
641
643
 
644
+ // packages/cli/src/app/theme.ts
645
+ var RIG_PALETTE = {
646
+ ink: "#f2f3f6",
647
+ ink2: "#aeb0ba",
648
+ ink3: "#6c6e79",
649
+ ink4: "#44464f",
650
+ accent: "#ccff4d",
651
+ accentDim: "#a9d63f",
652
+ cyan: "#56d8ff",
653
+ red: "#ff5d5d",
654
+ yellow: "#ffd24d"
655
+ };
656
+ function hexToRgb(hex) {
657
+ const value = hex.replace("#", "");
658
+ return [
659
+ Number.parseInt(value.slice(0, 2), 16),
660
+ Number.parseInt(value.slice(2, 4), 16),
661
+ Number.parseInt(value.slice(4, 6), 16)
662
+ ];
663
+ }
664
+ function fg(hex) {
665
+ const [r, g, b] = hexToRgb(hex);
666
+ return (text) => `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
667
+ }
668
+ var ink = fg(RIG_PALETTE.ink);
669
+ var ink2 = fg(RIG_PALETTE.ink2);
670
+ var ink3 = fg(RIG_PALETTE.ink3);
671
+ var ink4 = fg(RIG_PALETTE.ink4);
672
+ var accent = fg(RIG_PALETTE.accent);
673
+ var accentDim = fg(RIG_PALETTE.accentDim);
674
+ var cyan = fg(RIG_PALETTE.cyan);
675
+ var red = fg(RIG_PALETTE.red);
676
+ var yellow = fg(RIG_PALETTE.yellow);
677
+ function bold(text) {
678
+ return `\x1B[1m${text}\x1B[22m`;
679
+ }
680
+ var DRONE_ART = [
681
+ " .-=-. .-=-. ",
682
+ " ( !!! ) ( !!! ) ",
683
+ " '-=-'._ _.'-=-' ",
684
+ " '._ _.' ",
685
+ " '=$$$$$$$=.' ",
686
+ " =$$$$$$$$$$$= ",
687
+ " $$$@@@@@@@@@@$$$ ",
688
+ " $$$@@ @@$$$ ",
689
+ " $$@ ? @$$$ ",
690
+ " $$$@ '-' @$$$ ",
691
+ " $$$@@ @@$$$ ",
692
+ " $$$@@@@@@@@@@$$$ ",
693
+ " =$$$$$$$$$$$= ",
694
+ " '=$$$$$$$=.' ",
695
+ " _.' '._ ",
696
+ " .-=-.' '.-=-. ",
697
+ " ( !!! ) ( !!! ) ",
698
+ " '-=-' '-=-' "
699
+ ];
700
+ var EYE_FRAMES = ["@", "o", "."];
701
+ var DRONE_WIDTH = DRONE_ART[0].length;
702
+ var DRONE_HEIGHT = DRONE_ART.length;
703
+ var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
704
+ function microDroneFrame(tick) {
705
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
706
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
707
+ return `(${blade})${eye}(${blade})`;
708
+ }
709
+ var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
710
+ function renderMicroDroneFrame(tick) {
711
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
712
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
713
+ return `${ink4("(")}${cyan(blade)}${ink4(")")}${bold(accent(eye))}${ink4("(")}${cyan(blade)}${ink4(")")}`;
714
+ }
715
+
642
716
  // packages/cli/src/commands/_async-ui.ts
643
- var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
644
717
  var DONE_SYMBOL = pc.green("\u25C7");
645
718
  var FAIL_SYMBOL = pc.red("\u25A0");
646
719
  var activeUpdate = null;
@@ -674,8 +747,8 @@ async function withSpinner(label, work, options = {}) {
674
747
  const spinner = createTtySpinner({
675
748
  label,
676
749
  output,
677
- frames: CLACK_SPINNER_FRAMES,
678
- styleFrame: (frame) => pc.magenta(frame)
750
+ frames: MICRO_DRONE_FRAMES,
751
+ styleFrame: (frame) => renderMicroDroneFrame(Math.max(0, MICRO_DRONE_FRAMES.indexOf(frame)))
679
752
  });
680
753
  const update = (next) => {
681
754
  lastLabel = next;
@@ -716,6 +789,7 @@ function buildOperatorPiEnv(input) {
716
789
  return {
717
790
  PI_CODING_AGENT_SESSION_DIR: input.sessionDir,
718
791
  PI_SKIP_VERSION_CHECK: "1",
792
+ PI_HIDDEN_COMMANDS: "import,fork,clone,tree,new,resume,trust",
719
793
  RIG_PI_OPERATOR_SESSION: "1",
720
794
  RIG_RUN_ID: input.runId,
721
795
  RIG_SERVER_URL: input.serverUrl,
@@ -725,6 +799,10 @@ function buildOperatorPiEnv(input) {
725
799
  }
726
800
  async function prepareOperatorConsole(context, runId, tempSessionDir) {
727
801
  const server = await ensureServerForCli(context.projectRoot);
802
+ const localCwd = join(homedir2(), ".rig", "drones", runId.slice(0, 8));
803
+ mkdirSync2(localCwd, { recursive: true });
804
+ trustDroneCwd(localCwd);
805
+ installRigPiTheme();
728
806
  let sessionFileArg = [];
729
807
  try {
730
808
  const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}/session-file`);
@@ -738,7 +816,7 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
738
816
  try {
739
817
  const header = JSON.parse(line);
740
818
  if (header.type === "session" && typeof header.cwd === "string") {
741
- return JSON.stringify({ ...header, cwd: process.cwd() });
819
+ return JSON.stringify({ ...header, cwd: localCwd });
742
820
  }
743
821
  } catch {}
744
822
  return line;
@@ -750,6 +828,105 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
750
828
  } catch {}
751
829
  return { server, sessionFileArg };
752
830
  }
831
+ var RIG_PI_THEME = {
832
+ $schema: "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
833
+ name: "rig",
834
+ vars: {
835
+ acid: "#ccff4d",
836
+ acidDim: "#a9d63f",
837
+ cyan: "#56d8ff",
838
+ red: "#ff5d5d",
839
+ yellow: "#ffd24d",
840
+ ink: "#f2f3f6",
841
+ ink2: "#aeb0ba",
842
+ ink3: "#6c6e79",
843
+ ink4: "#44464f",
844
+ panel: "#101115",
845
+ panelUser: "#14161b",
846
+ toolPending: "#0e1013",
847
+ toolSuccess: "#10150c",
848
+ toolError: "#1a0f0f",
849
+ customMsg: "#0f1410"
850
+ },
851
+ colors: {
852
+ accent: "acid",
853
+ border: "ink4",
854
+ borderAccent: "acid",
855
+ borderMuted: "ink4",
856
+ success: "acid",
857
+ error: "red",
858
+ warning: "yellow",
859
+ muted: "ink3",
860
+ dim: "ink4",
861
+ text: "ink",
862
+ thinkingText: "ink3",
863
+ selectedBg: "panel",
864
+ userMessageBg: "panelUser",
865
+ userMessageText: "ink",
866
+ customMessageBg: "customMsg",
867
+ customMessageText: "ink2",
868
+ customMessageLabel: "acidDim",
869
+ toolPendingBg: "toolPending",
870
+ toolSuccessBg: "toolSuccess",
871
+ toolErrorBg: "toolError",
872
+ toolTitle: "ink",
873
+ toolOutput: "ink3",
874
+ mdHeading: "acid",
875
+ mdLink: "cyan",
876
+ mdLinkUrl: "ink4",
877
+ mdCode: "acidDim",
878
+ mdCodeBlock: "ink2",
879
+ mdCodeBlockBorder: "ink4",
880
+ mdQuote: "ink3",
881
+ mdQuoteBorder: "ink4",
882
+ mdHr: "ink4",
883
+ mdListBullet: "acid",
884
+ toolDiffAdded: "acid",
885
+ toolDiffRemoved: "red",
886
+ toolDiffContext: "ink3",
887
+ syntaxComment: "ink3",
888
+ syntaxKeyword: "cyan",
889
+ syntaxFunction: "acid",
890
+ syntaxVariable: "ink",
891
+ syntaxString: "acidDim",
892
+ syntaxNumber: "yellow",
893
+ syntaxType: "cyan",
894
+ syntaxOperator: "ink2",
895
+ syntaxPunctuation: "ink3",
896
+ thinkingOff: "ink4",
897
+ thinkingMinimal: "ink3",
898
+ thinkingLow: "ink2",
899
+ thinkingMedium: "cyan",
900
+ thinkingHigh: "acidDim",
901
+ thinkingXhigh: "acid",
902
+ bashMode: "cyan"
903
+ }
904
+ };
905
+ function trustDroneCwd(localCwd) {
906
+ try {
907
+ const agentDir = join(homedir2(), ".pi", "agent");
908
+ mkdirSync2(agentDir, { recursive: true });
909
+ const trustPath = join(agentDir, "trust.json");
910
+ const store = existsSync3(trustPath) ? JSON.parse(readFileSync3(trustPath, "utf8")) : {};
911
+ if (store[localCwd] !== true) {
912
+ store[localCwd] = true;
913
+ writeFileSync2(trustPath, `${JSON.stringify(store, null, "\t")}
914
+ `);
915
+ }
916
+ } catch {}
917
+ }
918
+ function installRigPiTheme() {
919
+ try {
920
+ const themesDir = join(homedir2(), ".pi", "agent", "themes");
921
+ mkdirSync2(themesDir, { recursive: true });
922
+ const themePath = join(themesDir, "rig.json");
923
+ const next = `${JSON.stringify(RIG_PI_THEME, null, "\t")}
924
+ `;
925
+ if (!existsSync3(themePath) || readFileSync3(themePath, "utf8") !== next) {
926
+ writeFileSync2(themePath, next);
927
+ }
928
+ } catch {}
929
+ }
753
930
  async function attachRunBundledPiFrontend(context, input) {
754
931
  const tempSessionDir = mkdtempSync(join(tmpdir(), "rig-pi-frontend-sessions-"));
755
932
  const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  // packages/cli/src/commands/_pi-frontend.ts
3
- import { mkdtempSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
4
- import { tmpdir } from "os";
3
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, mkdtempSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "fs";
4
+ import { homedir as homedir2, tmpdir } from "os";
5
5
  import { join } from "path";
6
6
  import { main as runPiMain } from "@earendil-works/pi-coding-agent";
7
7
  import createPiRigExtension from "@rig/pi-rig";
@@ -318,7 +318,9 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
318
318
  })() : null;
319
319
  if (!response.ok) {
320
320
  const diagnostics = diagnosticMessage(payload);
321
- const detail = diagnostics ?? (text || response.statusText);
321
+ const rawDetail = diagnostics ?? (text || response.statusText);
322
+ const detail = diagnostics ? rawDetail : rawDetail.split(`
323
+ `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
322
324
  const failure = await buildServerFailureContext(context.projectRoot, server);
323
325
  throw new CliError(`Rig server request failed (${response.status}): ${detail}
324
326
  ${failure.contextLine}`, 1, { hint: failure.hint });
@@ -405,8 +407,79 @@ function createTtySpinner(input) {
405
407
  };
406
408
  }
407
409
 
410
+ // packages/cli/src/app/theme.ts
411
+ var RIG_PALETTE = {
412
+ ink: "#f2f3f6",
413
+ ink2: "#aeb0ba",
414
+ ink3: "#6c6e79",
415
+ ink4: "#44464f",
416
+ accent: "#ccff4d",
417
+ accentDim: "#a9d63f",
418
+ cyan: "#56d8ff",
419
+ red: "#ff5d5d",
420
+ yellow: "#ffd24d"
421
+ };
422
+ function hexToRgb(hex) {
423
+ const value = hex.replace("#", "");
424
+ return [
425
+ Number.parseInt(value.slice(0, 2), 16),
426
+ Number.parseInt(value.slice(2, 4), 16),
427
+ Number.parseInt(value.slice(4, 6), 16)
428
+ ];
429
+ }
430
+ function fg(hex) {
431
+ const [r, g, b] = hexToRgb(hex);
432
+ return (text) => `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
433
+ }
434
+ var ink = fg(RIG_PALETTE.ink);
435
+ var ink2 = fg(RIG_PALETTE.ink2);
436
+ var ink3 = fg(RIG_PALETTE.ink3);
437
+ var ink4 = fg(RIG_PALETTE.ink4);
438
+ var accent = fg(RIG_PALETTE.accent);
439
+ var accentDim = fg(RIG_PALETTE.accentDim);
440
+ var cyan = fg(RIG_PALETTE.cyan);
441
+ var red = fg(RIG_PALETTE.red);
442
+ var yellow = fg(RIG_PALETTE.yellow);
443
+ function bold(text) {
444
+ return `\x1B[1m${text}\x1B[22m`;
445
+ }
446
+ var DRONE_ART = [
447
+ " .-=-. .-=-. ",
448
+ " ( !!! ) ( !!! ) ",
449
+ " '-=-'._ _.'-=-' ",
450
+ " '._ _.' ",
451
+ " '=$$$$$$$=.' ",
452
+ " =$$$$$$$$$$$= ",
453
+ " $$$@@@@@@@@@@$$$ ",
454
+ " $$$@@ @@$$$ ",
455
+ " $$@ ? @$$$ ",
456
+ " $$$@ '-' @$$$ ",
457
+ " $$$@@ @@$$$ ",
458
+ " $$$@@@@@@@@@@$$$ ",
459
+ " =$$$$$$$$$$$= ",
460
+ " '=$$$$$$$=.' ",
461
+ " _.' '._ ",
462
+ " .-=-.' '.-=-. ",
463
+ " ( !!! ) ( !!! ) ",
464
+ " '-=-' '-=-' "
465
+ ];
466
+ var EYE_FRAMES = ["@", "o", "."];
467
+ var DRONE_WIDTH = DRONE_ART[0].length;
468
+ var DRONE_HEIGHT = DRONE_ART.length;
469
+ var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
470
+ function microDroneFrame(tick) {
471
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
472
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
473
+ return `(${blade})${eye}(${blade})`;
474
+ }
475
+ var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
476
+ function renderMicroDroneFrame(tick) {
477
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
478
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
479
+ return `${ink4("(")}${cyan(blade)}${ink4(")")}${bold(accent(eye))}${ink4("(")}${cyan(blade)}${ink4(")")}`;
480
+ }
481
+
408
482
  // packages/cli/src/commands/_async-ui.ts
409
- var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
410
483
  var DONE_SYMBOL = pc.green("\u25C7");
411
484
  var FAIL_SYMBOL = pc.red("\u25A0");
412
485
  var activeUpdate = null;
@@ -440,8 +513,8 @@ async function withSpinner(label, work, options = {}) {
440
513
  const spinner = createTtySpinner({
441
514
  label,
442
515
  output,
443
- frames: CLACK_SPINNER_FRAMES,
444
- styleFrame: (frame) => pc.magenta(frame)
516
+ frames: MICRO_DRONE_FRAMES,
517
+ styleFrame: (frame) => renderMicroDroneFrame(Math.max(0, MICRO_DRONE_FRAMES.indexOf(frame)))
445
518
  });
446
519
  const update = (next) => {
447
520
  lastLabel = next;
@@ -482,6 +555,7 @@ function buildOperatorPiEnv(input) {
482
555
  return {
483
556
  PI_CODING_AGENT_SESSION_DIR: input.sessionDir,
484
557
  PI_SKIP_VERSION_CHECK: "1",
558
+ PI_HIDDEN_COMMANDS: "import,fork,clone,tree,new,resume,trust",
485
559
  RIG_PI_OPERATOR_SESSION: "1",
486
560
  RIG_RUN_ID: input.runId,
487
561
  RIG_SERVER_URL: input.serverUrl,
@@ -491,6 +565,10 @@ function buildOperatorPiEnv(input) {
491
565
  }
492
566
  async function prepareOperatorConsole(context, runId, tempSessionDir) {
493
567
  const server = await ensureServerForCli(context.projectRoot);
568
+ const localCwd = join(homedir2(), ".rig", "drones", runId.slice(0, 8));
569
+ mkdirSync2(localCwd, { recursive: true });
570
+ trustDroneCwd(localCwd);
571
+ installRigPiTheme();
494
572
  let sessionFileArg = [];
495
573
  try {
496
574
  const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}/session-file`);
@@ -504,7 +582,7 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
504
582
  try {
505
583
  const header = JSON.parse(line);
506
584
  if (header.type === "session" && typeof header.cwd === "string") {
507
- return JSON.stringify({ ...header, cwd: process.cwd() });
585
+ return JSON.stringify({ ...header, cwd: localCwd });
508
586
  }
509
587
  } catch {}
510
588
  return line;
@@ -516,6 +594,105 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
516
594
  } catch {}
517
595
  return { server, sessionFileArg };
518
596
  }
597
+ var RIG_PI_THEME = {
598
+ $schema: "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
599
+ name: "rig",
600
+ vars: {
601
+ acid: "#ccff4d",
602
+ acidDim: "#a9d63f",
603
+ cyan: "#56d8ff",
604
+ red: "#ff5d5d",
605
+ yellow: "#ffd24d",
606
+ ink: "#f2f3f6",
607
+ ink2: "#aeb0ba",
608
+ ink3: "#6c6e79",
609
+ ink4: "#44464f",
610
+ panel: "#101115",
611
+ panelUser: "#14161b",
612
+ toolPending: "#0e1013",
613
+ toolSuccess: "#10150c",
614
+ toolError: "#1a0f0f",
615
+ customMsg: "#0f1410"
616
+ },
617
+ colors: {
618
+ accent: "acid",
619
+ border: "ink4",
620
+ borderAccent: "acid",
621
+ borderMuted: "ink4",
622
+ success: "acid",
623
+ error: "red",
624
+ warning: "yellow",
625
+ muted: "ink3",
626
+ dim: "ink4",
627
+ text: "ink",
628
+ thinkingText: "ink3",
629
+ selectedBg: "panel",
630
+ userMessageBg: "panelUser",
631
+ userMessageText: "ink",
632
+ customMessageBg: "customMsg",
633
+ customMessageText: "ink2",
634
+ customMessageLabel: "acidDim",
635
+ toolPendingBg: "toolPending",
636
+ toolSuccessBg: "toolSuccess",
637
+ toolErrorBg: "toolError",
638
+ toolTitle: "ink",
639
+ toolOutput: "ink3",
640
+ mdHeading: "acid",
641
+ mdLink: "cyan",
642
+ mdLinkUrl: "ink4",
643
+ mdCode: "acidDim",
644
+ mdCodeBlock: "ink2",
645
+ mdCodeBlockBorder: "ink4",
646
+ mdQuote: "ink3",
647
+ mdQuoteBorder: "ink4",
648
+ mdHr: "ink4",
649
+ mdListBullet: "acid",
650
+ toolDiffAdded: "acid",
651
+ toolDiffRemoved: "red",
652
+ toolDiffContext: "ink3",
653
+ syntaxComment: "ink3",
654
+ syntaxKeyword: "cyan",
655
+ syntaxFunction: "acid",
656
+ syntaxVariable: "ink",
657
+ syntaxString: "acidDim",
658
+ syntaxNumber: "yellow",
659
+ syntaxType: "cyan",
660
+ syntaxOperator: "ink2",
661
+ syntaxPunctuation: "ink3",
662
+ thinkingOff: "ink4",
663
+ thinkingMinimal: "ink3",
664
+ thinkingLow: "ink2",
665
+ thinkingMedium: "cyan",
666
+ thinkingHigh: "acidDim",
667
+ thinkingXhigh: "acid",
668
+ bashMode: "cyan"
669
+ }
670
+ };
671
+ function trustDroneCwd(localCwd) {
672
+ try {
673
+ const agentDir = join(homedir2(), ".pi", "agent");
674
+ mkdirSync2(agentDir, { recursive: true });
675
+ const trustPath = join(agentDir, "trust.json");
676
+ const store = existsSync3(trustPath) ? JSON.parse(readFileSync3(trustPath, "utf8")) : {};
677
+ if (store[localCwd] !== true) {
678
+ store[localCwd] = true;
679
+ writeFileSync2(trustPath, `${JSON.stringify(store, null, "\t")}
680
+ `);
681
+ }
682
+ } catch {}
683
+ }
684
+ function installRigPiTheme() {
685
+ try {
686
+ const themesDir = join(homedir2(), ".pi", "agent", "themes");
687
+ mkdirSync2(themesDir, { recursive: true });
688
+ const themePath = join(themesDir, "rig.json");
689
+ const next = `${JSON.stringify(RIG_PI_THEME, null, "\t")}
690
+ `;
691
+ if (!existsSync3(themePath) || readFileSync3(themePath, "utf8") !== next) {
692
+ writeFileSync2(themePath, next);
693
+ }
694
+ } catch {}
695
+ }
519
696
  async function attachRunBundledPiFrontend(context, input) {
520
697
  const tempSessionDir = mkdtempSync(join(tmpdir(), "rig-pi-frontend-sessions-"));
521
698
  const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
@@ -305,7 +305,9 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
305
305
  })() : null;
306
306
  if (!response.ok) {
307
307
  const diagnostics = diagnosticMessage(payload);
308
- const detail = diagnostics ?? (text || response.statusText);
308
+ const rawDetail = diagnostics ?? (text || response.statusText);
309
+ const detail = diagnostics ? rawDetail : rawDetail.split(`
310
+ `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
309
311
  const failure = await buildServerFailureContext(context.projectRoot, server);
310
312
  throw new CliError(`Rig server request failed (${response.status}): ${detail}
311
313
  ${failure.contextLine}`, 1, { hint: failure.hint });
@@ -325,7 +325,9 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
325
325
  })() : null;
326
326
  if (!response.ok) {
327
327
  const diagnostics = diagnosticMessage(payload);
328
- const detail = diagnostics ?? (text || response.statusText);
328
+ const rawDetail = diagnostics ?? (text || response.statusText);
329
+ const detail = diagnostics ? rawDetail : rawDetail.split(`
330
+ `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
329
331
  const failure = await buildServerFailureContext(context.projectRoot, server);
330
332
  throw new CliError(`Rig server request failed (${response.status}): ${detail}
331
333
  ${failure.contextLine}`, 1, { hint: failure.hint });
@@ -310,7 +310,9 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
310
310
  })() : null;
311
311
  if (!response.ok) {
312
312
  const diagnostics = diagnosticMessage(payload);
313
- const detail = diagnostics ?? (text || response.statusText);
313
+ const rawDetail = diagnostics ?? (text || response.statusText);
314
+ const detail = diagnostics ? rawDetail : rawDetail.split(`
315
+ `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
314
316
  const failure = await buildServerFailureContext(context.projectRoot, server);
315
317
  throw new CliError(`Rig server request failed (${response.status}): ${detail}
316
318
  ${failure.contextLine}`, 1, { hint: failure.hint });