@h-rig/cli 0.0.6-alpha.77 → 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.
@@ -1,9 +1,221 @@
1
1
  // @bun
2
2
  // packages/cli/src/commands/task.ts
3
- import { readFileSync as readFileSync3 } from "fs";
3
+ import { readFileSync as readFileSync4 } from "fs";
4
4
  import { spawnSync } from "child_process";
5
5
  import { resolve as resolve3 } from "path";
6
- import { cancel as cancel2, confirm, isCancel as isCancel2 } from "@clack/prompts";
6
+
7
+ // packages/cli/src/app/drone-ui.ts
8
+ import { ProcessTerminal, TUI, Text, Input, SelectList, matchesKey } from "@earendil-works/pi-tui";
9
+
10
+ // packages/cli/src/app/theme.ts
11
+ var RIG_PALETTE = {
12
+ ink: "#f2f3f6",
13
+ ink2: "#aeb0ba",
14
+ ink3: "#6c6e79",
15
+ ink4: "#44464f",
16
+ accent: "#ccff4d",
17
+ accentDim: "#a9d63f",
18
+ cyan: "#56d8ff",
19
+ red: "#ff5d5d",
20
+ yellow: "#ffd24d"
21
+ };
22
+ function hexToRgb(hex) {
23
+ const value = hex.replace("#", "");
24
+ return [
25
+ Number.parseInt(value.slice(0, 2), 16),
26
+ Number.parseInt(value.slice(2, 4), 16),
27
+ Number.parseInt(value.slice(4, 6), 16)
28
+ ];
29
+ }
30
+ function fg(hex) {
31
+ const [r, g, b] = hexToRgb(hex);
32
+ return (text) => `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
33
+ }
34
+ var ink = fg(RIG_PALETTE.ink);
35
+ var ink2 = fg(RIG_PALETTE.ink2);
36
+ var ink3 = fg(RIG_PALETTE.ink3);
37
+ var ink4 = fg(RIG_PALETTE.ink4);
38
+ var accent = fg(RIG_PALETTE.accent);
39
+ var accentDim = fg(RIG_PALETTE.accentDim);
40
+ var cyan = fg(RIG_PALETTE.cyan);
41
+ var red = fg(RIG_PALETTE.red);
42
+ var yellow = fg(RIG_PALETTE.yellow);
43
+ function bold(text) {
44
+ return `\x1B[1m${text}\x1B[22m`;
45
+ }
46
+ var DRONE_ART = [
47
+ " .-=-. .-=-. ",
48
+ " ( !!! ) ( !!! ) ",
49
+ " '-=-'._ _.'-=-' ",
50
+ " '._ _.' ",
51
+ " '=$$$$$$$=.' ",
52
+ " =$$$$$$$$$$$= ",
53
+ " $$$@@@@@@@@@@$$$ ",
54
+ " $$$@@ @@$$$ ",
55
+ " $$@ ? @$$$ ",
56
+ " $$$@ '-' @$$$ ",
57
+ " $$$@@ @@$$$ ",
58
+ " $$$@@@@@@@@@@$$$ ",
59
+ " =$$$$$$$$$$$= ",
60
+ " '=$$$$$$$=.' ",
61
+ " _.' '._ ",
62
+ " .-=-.' '.-=-. ",
63
+ " ( !!! ) ( !!! ) ",
64
+ " '-=-' '-=-' "
65
+ ];
66
+ var EYE_FRAMES = ["@", "o", "."];
67
+ var DRONE_WIDTH = DRONE_ART[0].length;
68
+ var DRONE_HEIGHT = DRONE_ART.length;
69
+ var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
70
+ function microDroneFrame(tick) {
71
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
72
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
73
+ return `(${blade})${eye}(${blade})`;
74
+ }
75
+ var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
76
+ function renderMicroDroneFrame(tick) {
77
+ const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
78
+ const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
79
+ return `${ink4("(")}${cyan(blade)}${ink4(")")}${bold(accent(eye))}${ink4("(")}${cyan(blade)}${ink4(")")}`;
80
+ }
81
+
82
+ // packages/cli/src/commands/_spinner.ts
83
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
84
+ function createTtySpinner(input) {
85
+ const output = input.output ?? process.stdout;
86
+ const isTty = output.isTTY === true;
87
+ const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
88
+ let label = input.label;
89
+ let frame = 0;
90
+ let paused = false;
91
+ let stopped = false;
92
+ let lastPrintedLabel = "";
93
+ const render = () => {
94
+ if (stopped || paused)
95
+ return;
96
+ if (!isTty) {
97
+ if (label !== lastPrintedLabel) {
98
+ output.write(`${label}
99
+ `);
100
+ lastPrintedLabel = label;
101
+ }
102
+ return;
103
+ }
104
+ frame = (frame + 1) % frames.length;
105
+ const glyph = frames[frame] ?? frames[0] ?? "";
106
+ output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
107
+ };
108
+ const clearLine = () => {
109
+ if (isTty)
110
+ output.write("\r\x1B[2K");
111
+ };
112
+ render();
113
+ const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
114
+ return {
115
+ setLabel(next) {
116
+ label = next;
117
+ render();
118
+ },
119
+ pause() {
120
+ paused = true;
121
+ clearLine();
122
+ },
123
+ resume() {
124
+ if (stopped)
125
+ return;
126
+ paused = false;
127
+ render();
128
+ },
129
+ stop(finalLine) {
130
+ if (stopped)
131
+ return;
132
+ stopped = true;
133
+ if (timer)
134
+ clearInterval(timer);
135
+ clearLine();
136
+ if (finalLine)
137
+ output.write(`${finalLine}
138
+ `);
139
+ }
140
+ };
141
+ }
142
+
143
+ // packages/cli/src/app/drone-ui.ts
144
+ var isTty = () => Boolean(process.stdout.isTTY);
145
+ function droneNote(message, title) {
146
+ if (title)
147
+ console.log(` ${accentDim("\u25C7")} ${bold(ink2(title))}`);
148
+ for (const line of message.split(`
149
+ `)) {
150
+ console.log(` ${ink4("\u2502")} ${line}`);
151
+ }
152
+ }
153
+ function droneCancel(text) {
154
+ console.log(` ${red("\u2716")} ${ink3(text)}`);
155
+ }
156
+ var SELECT_THEME = {
157
+ selectedPrefix: (text) => accent(text),
158
+ selectedText: (text) => bold(ink(text)),
159
+ description: (text) => ink3(text),
160
+ scrollInfo: (text) => ink4(text),
161
+ noMatch: (text) => ink3(text)
162
+ };
163
+ async function runMiniTui(build) {
164
+ const terminal = new ProcessTerminal;
165
+ const tui = new TUI(terminal);
166
+ let settled = false;
167
+ return await new Promise((resolve) => {
168
+ const finish = (result) => {
169
+ if (settled)
170
+ return;
171
+ settled = true;
172
+ tui.stop();
173
+ resolve(result);
174
+ };
175
+ build(tui, finish);
176
+ tui.start();
177
+ });
178
+ }
179
+ async function droneSelect(input) {
180
+ if (!isTty() || input.options.length === 0) {
181
+ return input.initialValue ?? input.options[0]?.value ?? null;
182
+ }
183
+ return runMiniTui((tui, finish) => {
184
+ tui.addChild(new Text(` ${accent("\u258D")}${bold(ink(input.message))}`));
185
+ const items = input.options.map((option) => ({
186
+ value: option.value,
187
+ label: option.label,
188
+ ...option.hint ? { description: option.hint } : {}
189
+ }));
190
+ const list = new SelectList(items, Math.min(items.length, 12), SELECT_THEME);
191
+ const initialIndex = input.initialValue ? items.findIndex((item) => item.value === input.initialValue) : -1;
192
+ if (initialIndex > 0)
193
+ list.setSelectedIndex(initialIndex);
194
+ list.onSelect = (item) => finish(item.value);
195
+ list.onCancel = () => finish(null);
196
+ tui.addChild(list);
197
+ tui.addChild(new Text(ink4(" \u2191\u2193 navigate \xB7 enter select \xB7 esc cancel")));
198
+ tui.setFocus(list);
199
+ tui.addInputListener((data) => {
200
+ if (matchesKey(data, "ctrl+c") || matchesKey(data, "escape")) {
201
+ finish(null);
202
+ return { consume: true };
203
+ }
204
+ return;
205
+ });
206
+ });
207
+ }
208
+ async function droneConfirm(input) {
209
+ const answer = await droneSelect({
210
+ message: input.message,
211
+ options: [
212
+ { value: "yes", label: "Yes" },
213
+ { value: "no", label: "No" }
214
+ ],
215
+ initialValue: input.initialValue === false ? "no" : "yes"
216
+ });
217
+ return answer === null ? null : answer === "yes";
218
+ }
7
219
 
8
220
  // packages/cli/src/runner.ts
9
221
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
@@ -413,7 +625,9 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
413
625
  })() : null;
414
626
  if (!response.ok) {
415
627
  const diagnostics = diagnosticMessage(payload);
416
- const detail = diagnostics ?? (text || response.statusText);
628
+ const rawDetail = diagnostics ?? (text || response.statusText);
629
+ const detail = diagnostics ? rawDetail : rawDetail.split(`
630
+ `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
417
631
  const failure = await buildServerFailureContext(context.projectRoot, server);
418
632
  throw new CliError(`Rig server request failed (${response.status}): ${detail}
419
633
  ${failure.contextLine}`, 1, { hint: failure.hint });
@@ -786,9 +1000,6 @@ function withMutedConsole(mute, fn) {
786
1000
  }
787
1001
  }
788
1002
 
789
- // packages/cli/src/commands/_task-picker.ts
790
- import { cancel, isCancel, select } from "@clack/prompts";
791
-
792
1003
  // packages/cli/src/commands/_operator-surface.ts
793
1004
  import { createInterface } from "readline";
794
1005
  import { createInterface as createPromptInterface } from "readline/promises";
@@ -1011,8 +1222,8 @@ async function selectTaskWithTextPicker(tasks, io = {}) {
1011
1222
  return null;
1012
1223
  if (tasks.length === 1)
1013
1224
  return tasks[0];
1014
- const isTty = io.isTty ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
1015
- if (!isTty) {
1225
+ const isTty2 = io.isTty ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
1226
+ if (!isTty2) {
1016
1227
  throw new Error("task run requires an interactive terminal to pick a task; pass --task <id>, --next, or --detach with a task id.");
1017
1228
  }
1018
1229
  if (io.prompt || io.renderer) {
@@ -1036,12 +1247,12 @@ async function selectTaskWithTextPicker(tasks, io = {}) {
1036
1247
  label: `${taskId2(task)} \xB7 ${typeof task.title === "string" && task.title.trim() ? task.title.trim() : "Untitled task"}`,
1037
1248
  hint: typeof task.status === "string" && task.status.trim() ? task.status.trim() : undefined
1038
1249
  }));
1039
- const answer = await select({
1250
+ const answer = await droneSelect({
1040
1251
  message: "Select Rig task",
1041
1252
  options
1042
1253
  });
1043
- if (isCancel(answer)) {
1044
- cancel("No task selected.");
1254
+ if (answer === null) {
1255
+ droneCancel("No task selected.");
1045
1256
  return null;
1046
1257
  }
1047
1258
  const index = Number.parseInt(String(answer), 10);
@@ -1050,70 +1261,6 @@ async function selectTaskWithTextPicker(tasks, io = {}) {
1050
1261
 
1051
1262
  // packages/cli/src/commands/_async-ui.ts
1052
1263
  import pc from "picocolors";
1053
-
1054
- // packages/cli/src/commands/_spinner.ts
1055
- var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1056
- function createTtySpinner(input) {
1057
- const output = input.output ?? process.stdout;
1058
- const isTty = output.isTTY === true;
1059
- const frames = input.frames && input.frames.length > 0 ? input.frames : SPINNER_FRAMES;
1060
- let label = input.label;
1061
- let frame = 0;
1062
- let paused = false;
1063
- let stopped = false;
1064
- let lastPrintedLabel = "";
1065
- const render = () => {
1066
- if (stopped || paused)
1067
- return;
1068
- if (!isTty) {
1069
- if (label !== lastPrintedLabel) {
1070
- output.write(`${label}
1071
- `);
1072
- lastPrintedLabel = label;
1073
- }
1074
- return;
1075
- }
1076
- frame = (frame + 1) % frames.length;
1077
- const glyph = frames[frame] ?? frames[0] ?? "";
1078
- output.write(`\r\x1B[2K${input.styleFrame ? input.styleFrame(glyph) : glyph} ${label}`);
1079
- };
1080
- const clearLine = () => {
1081
- if (isTty)
1082
- output.write("\r\x1B[2K");
1083
- };
1084
- render();
1085
- const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
1086
- return {
1087
- setLabel(next) {
1088
- label = next;
1089
- render();
1090
- },
1091
- pause() {
1092
- paused = true;
1093
- clearLine();
1094
- },
1095
- resume() {
1096
- if (stopped)
1097
- return;
1098
- paused = false;
1099
- render();
1100
- },
1101
- stop(finalLine) {
1102
- if (stopped)
1103
- return;
1104
- stopped = true;
1105
- if (timer)
1106
- clearInterval(timer);
1107
- clearLine();
1108
- if (finalLine)
1109
- output.write(`${finalLine}
1110
- `);
1111
- }
1112
- };
1113
- }
1114
-
1115
- // packages/cli/src/commands/_async-ui.ts
1116
- var CLACK_SPINNER_FRAMES = ["\u25D2", "\u25D0", "\u25D3", "\u25D1"];
1117
1264
  var DONE_SYMBOL = pc.green("\u25C7");
1118
1265
  var FAIL_SYMBOL = pc.red("\u25A0");
1119
1266
  var activeUpdate = null;
@@ -1127,9 +1274,9 @@ async function withSpinner(label, work, options = {}) {
1127
1274
  return work(outer);
1128
1275
  }
1129
1276
  const output = options.output ?? process.stderr;
1130
- const isTty = output.isTTY === true;
1277
+ const isTty2 = output.isTTY === true;
1131
1278
  let lastLabel = label;
1132
- if (!isTty) {
1279
+ if (!isTty2) {
1133
1280
  output.write(`${label}
1134
1281
  `);
1135
1282
  const update2 = (next) => {
@@ -1147,8 +1294,8 @@ async function withSpinner(label, work, options = {}) {
1147
1294
  const spinner = createTtySpinner({
1148
1295
  label,
1149
1296
  output,
1150
- frames: CLACK_SPINNER_FRAMES,
1151
- styleFrame: (frame) => pc.magenta(frame)
1297
+ frames: MICRO_DRONE_FRAMES,
1298
+ styleFrame: (frame) => renderMicroDroneFrame(Math.max(0, MICRO_DRONE_FRAMES.indexOf(frame)))
1152
1299
  });
1153
1300
  const update = (next) => {
1154
1301
  lastLabel = next;
@@ -1170,8 +1317,8 @@ async function withSpinner(label, work, options = {}) {
1170
1317
  }
1171
1318
 
1172
1319
  // packages/cli/src/commands/_pi-frontend.ts
1173
- import { mkdtempSync, rmSync, writeFileSync as writeFileSync2 } from "fs";
1174
- import { tmpdir } from "os";
1320
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, mkdtempSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync2 } from "fs";
1321
+ import { homedir as homedir2, tmpdir } from "os";
1175
1322
  import { join } from "path";
1176
1323
  import { main as runPiMain } from "@earendil-works/pi-coding-agent";
1177
1324
  import createPiRigExtension from "@rig/pi-rig";
@@ -1194,6 +1341,7 @@ function buildOperatorPiEnv(input) {
1194
1341
  return {
1195
1342
  PI_CODING_AGENT_SESSION_DIR: input.sessionDir,
1196
1343
  PI_SKIP_VERSION_CHECK: "1",
1344
+ PI_HIDDEN_COMMANDS: "import,fork,clone,tree,new,resume,trust",
1197
1345
  RIG_PI_OPERATOR_SESSION: "1",
1198
1346
  RIG_RUN_ID: input.runId,
1199
1347
  RIG_SERVER_URL: input.serverUrl,
@@ -1203,6 +1351,10 @@ function buildOperatorPiEnv(input) {
1203
1351
  }
1204
1352
  async function prepareOperatorConsole(context, runId, tempSessionDir) {
1205
1353
  const server = await ensureServerForCli(context.projectRoot);
1354
+ const localCwd = join(homedir2(), ".rig", "drones", runId.slice(0, 8));
1355
+ mkdirSync2(localCwd, { recursive: true });
1356
+ trustDroneCwd(localCwd);
1357
+ installRigPiTheme();
1206
1358
  let sessionFileArg = [];
1207
1359
  try {
1208
1360
  const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}/session-file`);
@@ -1216,7 +1368,7 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
1216
1368
  try {
1217
1369
  const header = JSON.parse(line);
1218
1370
  if (header.type === "session" && typeof header.cwd === "string") {
1219
- return JSON.stringify({ ...header, cwd: process.cwd() });
1371
+ return JSON.stringify({ ...header, cwd: localCwd });
1220
1372
  }
1221
1373
  } catch {}
1222
1374
  return line;
@@ -1228,6 +1380,105 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
1228
1380
  } catch {}
1229
1381
  return { server, sessionFileArg };
1230
1382
  }
1383
+ var RIG_PI_THEME = {
1384
+ $schema: "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
1385
+ name: "rig",
1386
+ vars: {
1387
+ acid: "#ccff4d",
1388
+ acidDim: "#a9d63f",
1389
+ cyan: "#56d8ff",
1390
+ red: "#ff5d5d",
1391
+ yellow: "#ffd24d",
1392
+ ink: "#f2f3f6",
1393
+ ink2: "#aeb0ba",
1394
+ ink3: "#6c6e79",
1395
+ ink4: "#44464f",
1396
+ panel: "#101115",
1397
+ panelUser: "#14161b",
1398
+ toolPending: "#0e1013",
1399
+ toolSuccess: "#10150c",
1400
+ toolError: "#1a0f0f",
1401
+ customMsg: "#0f1410"
1402
+ },
1403
+ colors: {
1404
+ accent: "acid",
1405
+ border: "ink4",
1406
+ borderAccent: "acid",
1407
+ borderMuted: "ink4",
1408
+ success: "acid",
1409
+ error: "red",
1410
+ warning: "yellow",
1411
+ muted: "ink3",
1412
+ dim: "ink4",
1413
+ text: "ink",
1414
+ thinkingText: "ink3",
1415
+ selectedBg: "panel",
1416
+ userMessageBg: "panelUser",
1417
+ userMessageText: "ink",
1418
+ customMessageBg: "customMsg",
1419
+ customMessageText: "ink2",
1420
+ customMessageLabel: "acidDim",
1421
+ toolPendingBg: "toolPending",
1422
+ toolSuccessBg: "toolSuccess",
1423
+ toolErrorBg: "toolError",
1424
+ toolTitle: "ink",
1425
+ toolOutput: "ink3",
1426
+ mdHeading: "acid",
1427
+ mdLink: "cyan",
1428
+ mdLinkUrl: "ink4",
1429
+ mdCode: "acidDim",
1430
+ mdCodeBlock: "ink2",
1431
+ mdCodeBlockBorder: "ink4",
1432
+ mdQuote: "ink3",
1433
+ mdQuoteBorder: "ink4",
1434
+ mdHr: "ink4",
1435
+ mdListBullet: "acid",
1436
+ toolDiffAdded: "acid",
1437
+ toolDiffRemoved: "red",
1438
+ toolDiffContext: "ink3",
1439
+ syntaxComment: "ink3",
1440
+ syntaxKeyword: "cyan",
1441
+ syntaxFunction: "acid",
1442
+ syntaxVariable: "ink",
1443
+ syntaxString: "acidDim",
1444
+ syntaxNumber: "yellow",
1445
+ syntaxType: "cyan",
1446
+ syntaxOperator: "ink2",
1447
+ syntaxPunctuation: "ink3",
1448
+ thinkingOff: "ink4",
1449
+ thinkingMinimal: "ink3",
1450
+ thinkingLow: "ink2",
1451
+ thinkingMedium: "cyan",
1452
+ thinkingHigh: "acidDim",
1453
+ thinkingXhigh: "acid",
1454
+ bashMode: "cyan"
1455
+ }
1456
+ };
1457
+ function trustDroneCwd(localCwd) {
1458
+ try {
1459
+ const agentDir = join(homedir2(), ".pi", "agent");
1460
+ mkdirSync2(agentDir, { recursive: true });
1461
+ const trustPath = join(agentDir, "trust.json");
1462
+ const store = existsSync3(trustPath) ? JSON.parse(readFileSync3(trustPath, "utf8")) : {};
1463
+ if (store[localCwd] !== true) {
1464
+ store[localCwd] = true;
1465
+ writeFileSync2(trustPath, `${JSON.stringify(store, null, "\t")}
1466
+ `);
1467
+ }
1468
+ } catch {}
1469
+ }
1470
+ function installRigPiTheme() {
1471
+ try {
1472
+ const themesDir = join(homedir2(), ".pi", "agent", "themes");
1473
+ mkdirSync2(themesDir, { recursive: true });
1474
+ const themePath = join(themesDir, "rig.json");
1475
+ const next = `${JSON.stringify(RIG_PI_THEME, null, "\t")}
1476
+ `;
1477
+ if (!existsSync3(themePath) || readFileSync3(themePath, "utf8") !== next) {
1478
+ writeFileSync2(themePath, next);
1479
+ }
1480
+ } catch {}
1481
+ }
1231
1482
  async function attachRunBundledPiFrontend(context, input) {
1232
1483
  const tempSessionDir = mkdtempSync(join(tmpdir(), "rig-pi-frontend-sessions-"));
1233
1484
  const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
@@ -1365,66 +1616,7 @@ async function attachRunOperatorView(context, input) {
1365
1616
  }
1366
1617
 
1367
1618
  // packages/cli/src/commands/_cli-format.ts
1368
- import { log, note } from "@clack/prompts";
1369
1619
  import pc2 from "picocolors";
1370
-
1371
- // packages/cli/src/commands/_tui-theme.ts
1372
- var RIG_PALETTE = {
1373
- ink: "#f2f3f6",
1374
- ink2: "#aeb0ba",
1375
- ink3: "#6c6e79",
1376
- ink4: "#44464f",
1377
- accent: "#ccff4d",
1378
- accentDim: "#a9d63f",
1379
- cyan: "#56d8ff",
1380
- red: "#ff5d5d",
1381
- yellow: "#ffd24d"
1382
- };
1383
- function hexToRgb(hex) {
1384
- const value = hex.replace("#", "");
1385
- return [
1386
- Number.parseInt(value.slice(0, 2), 16),
1387
- Number.parseInt(value.slice(2, 4), 16),
1388
- Number.parseInt(value.slice(4, 6), 16)
1389
- ];
1390
- }
1391
- function fg(hex) {
1392
- const [r, g, b] = hexToRgb(hex);
1393
- return (text) => `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
1394
- }
1395
- var ink = fg(RIG_PALETTE.ink);
1396
- var ink2 = fg(RIG_PALETTE.ink2);
1397
- var ink3 = fg(RIG_PALETTE.ink3);
1398
- var ink4 = fg(RIG_PALETTE.ink4);
1399
- var accent = fg(RIG_PALETTE.accent);
1400
- var accentDim = fg(RIG_PALETTE.accentDim);
1401
- var cyan = fg(RIG_PALETTE.cyan);
1402
- var red = fg(RIG_PALETTE.red);
1403
- var yellow = fg(RIG_PALETTE.yellow);
1404
- var DRONE_ART = [
1405
- " .-=-. .-=-. ",
1406
- " ( !!! ) ( !!! ) ",
1407
- " '-=-'._ _.'-=-' ",
1408
- " '._ _.' ",
1409
- " '=$$$$$$$=.' ",
1410
- " =$$$$$$$$$$$= ",
1411
- " $$$@@@@@@@@@@$$$ ",
1412
- " $$$@@ @@$$$ ",
1413
- " $$@ ? @$$$ ",
1414
- " $$$@ '-' @$$$ ",
1415
- " $$$@@ @@$$$ ",
1416
- " $$$@@@@@@@@@@$$$ ",
1417
- " =$$$$$$$$$$$= ",
1418
- " '=$$$$$$$=.' ",
1419
- " _.' '._ ",
1420
- " .-=-.' '.-=-. ",
1421
- " ( !!! ) ( !!! ) ",
1422
- " '-=-' '-=-' "
1423
- ];
1424
- var DRONE_WIDTH = DRONE_ART[0].length;
1425
- var DRONE_HEIGHT = DRONE_ART.length;
1426
-
1427
- // packages/cli/src/commands/_cli-format.ts
1428
1620
  var themeDim = (value) => ink3(value);
1429
1621
  var themeFaint = (value) => ink4(value);
1430
1622
  function stringField(record, key, fallback = "") {
@@ -1484,10 +1676,7 @@ function printFormattedOutput(message2, options = {}) {
1484
1676
  console.log(message2);
1485
1677
  return;
1486
1678
  }
1487
- if (options.title)
1488
- note(message2, options.title);
1489
- else
1490
- log.message(message2);
1679
+ droneNote(message2, options.title);
1491
1680
  }
1492
1681
  function formatStatusPill(status) {
1493
1682
  const label = status || "unknown";
@@ -1632,7 +1821,6 @@ async function printPendingInboxFooter(context) {
1632
1821
  }
1633
1822
 
1634
1823
  // packages/cli/src/commands/_help-catalog.ts
1635
- import { intro, log as log2, note as note2, outro } from "@clack/prompts";
1636
1824
  import pc3 from "picocolors";
1637
1825
  var TOP_LEVEL_SECTIONS = [
1638
1826
  {
@@ -1935,25 +2123,6 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
1935
2123
  function heading(title) {
1936
2124
  return pc3.bold(pc3.cyan(title));
1937
2125
  }
1938
- function renderRigBanner(version) {
1939
- const m = (s) => pc3.bold(pc3.magenta(s));
1940
- const c = (s) => pc3.bold(pc3.cyan(s));
1941
- const y = (s) => pc3.yellow(s);
1942
- const d = (s) => pc3.dim(s);
1943
- const lines = [
1944
- m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
1945
- m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
1946
- c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
1947
- c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
1948
- y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
1949
- y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
1950
- "",
1951
- ` ${c("\u25E2\u25E4")} ${pc3.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
1952
- version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
1953
- ];
1954
- return lines.join(`
1955
- `);
1956
- }
1957
2126
  function commandLine(command, description) {
1958
2127
  const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
1959
2128
  return `${pc3.dim("\u2502")} ${pc3.bold(commandColumn)} ${description}`;
@@ -2007,67 +2176,8 @@ function renderGroupHelp(groupName) {
2007
2176
  const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
2008
2177
  return group ? renderGroup(group) : null;
2009
2178
  }
2010
- function shouldUseClackOutput2() {
2011
- return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
2012
- }
2013
- function printTopLevelHelp(state = {}) {
2014
- if (!shouldUseClackOutput2()) {
2015
- console.log(renderTopLevelHelp());
2016
- return;
2017
- }
2018
- console.log(renderRigBanner(state.version));
2019
- console.log("");
2020
- if (state.projectInitialized === false) {
2021
- intro("no rig project in this directory");
2022
- note2([
2023
- commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
2024
- commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
2025
- commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
2026
- ].join(`
2027
- `), "Get started");
2028
- outro("After init: rig task run --next puts an agent on your next task.");
2029
- return;
2030
- }
2031
- intro(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
2032
- for (const section of TOP_LEVEL_SECTIONS) {
2033
- note2(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
2034
- }
2035
- log2.info("More: rig help --advanced \xB7 rig <group> --help \xB7 rig --version");
2036
- note2([
2037
- commandLine("--project <path>", "Use a project root instead of auto-discovery."),
2038
- commandLine("--json", "Emit structured output for scripts/agents."),
2039
- commandLine("--dry-run", "Print the command plan without mutating state.")
2040
- ].join(`
2041
- `), "Global options");
2042
- outro("init \u2192 task run \u2192 attach (Pi console: watch + steer live) \u2192 inbox \u2192 merged.");
2043
- }
2044
2179
  function printGroupHelpDocument(groupName) {
2045
- const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
2046
- if (!shouldUseClackOutput2()) {
2047
- console.log(rendered);
2048
- return;
2049
- }
2050
- const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
2051
- if (!group) {
2052
- printTopLevelHelp();
2053
- return;
2054
- }
2055
- intro(`rig ${group.name}`);
2056
- note2(group.summary, "Purpose");
2057
- note2(group.usage.join(`
2058
- `), "Usage");
2059
- note2(group.commands.map((entry) => commandLine(entry.command, entry.description)).join(`
2060
- `), "Commands");
2061
- if (group.examples?.length)
2062
- note2(group.examples.map((line) => `$ ${line}`).join(`
2063
- `), "Examples");
2064
- if (group.next?.length)
2065
- note2(group.next.map((line) => `\u203A ${line}`).join(`
2066
- `), "Next steps");
2067
- if (group.advanced?.length)
2068
- log2.info(group.advanced.join(`
2069
- `));
2070
- outro("Run with --json when scripts need structured output.");
2180
+ console.log(renderGroupHelp(groupName) ?? renderTopLevelHelp());
2071
2181
  }
2072
2182
 
2073
2183
  // packages/cli/src/commands/task.ts
@@ -2173,12 +2283,12 @@ async function resolveDirtyBaselineForTaskRun(context, explicit) {
2173
2283
  if (explicit)
2174
2284
  return { mode: explicit, state };
2175
2285
  if (context.outputMode === "text" && process.stdin.isTTY && process.stdout.isTTY) {
2176
- const answer = await confirm({
2286
+ const answer = await droneConfirm({
2177
2287
  message: "Include current uncommitted changes in run baseline?",
2178
2288
  initialValue: false
2179
2289
  });
2180
- if (isCancel2(answer)) {
2181
- cancel2("Run cancelled.");
2290
+ if (answer === null) {
2291
+ droneCancel("Run cancelled.");
2182
2292
  throw new CliError("Run cancelled by user.", 1);
2183
2293
  }
2184
2294
  return { mode: answer ? "dirty-snapshot" : "head", state };
@@ -2333,7 +2443,7 @@ async function executeTask(context, args, options) {
2333
2443
  const fileFlag = takeOption(rest.slice(1), "--file");
2334
2444
  let content;
2335
2445
  if (fileFlag.value) {
2336
- content = readFileSync3(resolve3(context.projectRoot, fileFlag.value), "utf-8");
2446
+ content = readFileSync4(resolve3(context.projectRoot, fileFlag.value), "utf-8");
2337
2447
  } else {
2338
2448
  content = await readStdin();
2339
2449
  }
@@ -2557,5 +2667,6 @@ async function executeTask(context, args, options) {
2557
2667
  }
2558
2668
  }
2559
2669
  export {
2670
+ loadTaskRunProjectDefaults,
2560
2671
  executeTask
2561
2672
  };