@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.
- package/dist/bin/rig.js +10165 -9284
- package/dist/src/app/board.js +1783 -0
- package/dist/src/app/drone-ui.js +294 -0
- package/dist/src/{commands/_tui-theme.js → app/theme.js} +16 -1
- package/dist/src/commands/_async-ui.js +74 -3
- package/dist/src/commands/_cli-format.js +26 -8
- package/dist/src/commands/_doctor-checks.js +3 -1
- package/dist/src/commands/_help-catalog.js +8 -70
- package/dist/src/commands/_operator-view.js +184 -7
- package/dist/src/commands/_pi-frontend.js +184 -7
- package/dist/src/commands/_preflight.js +3 -1
- package/dist/src/commands/_server-client.js +3 -1
- package/dist/src/commands/_snapshot-upload.js +3 -1
- package/dist/src/commands/_task-picker.js +132 -7
- package/dist/src/commands/browser.js +306 -30
- package/dist/src/commands/connect.js +130 -64
- package/dist/src/commands/doctor.js +77 -4
- package/dist/src/commands/github.js +77 -4
- package/dist/src/commands/inbox.js +101 -78
- package/dist/src/commands/init.js +349 -9
- package/dist/src/commands/inspect.js +77 -4
- package/dist/src/commands/run.js +195 -69
- package/dist/src/commands/server.js +133 -65
- package/dist/src/commands/setup.js +77 -4
- package/dist/src/commands/stats.js +56 -113
- package/dist/src/commands/task-report-bug.js +231 -40
- package/dist/src/commands/task-run-driver.js +3 -1
- package/dist/src/commands/task.js +340 -229
- package/dist/src/commands.js +10159 -9278
- package/dist/src/index.js +10161 -9280
- package/package.json +8 -9
- package/dist/src/commands/_operator-board.js +0 -730
|
@@ -342,7 +342,9 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
|
|
|
342
342
|
})() : null;
|
|
343
343
|
if (!response.ok) {
|
|
344
344
|
const diagnostics = diagnosticMessage(payload);
|
|
345
|
-
const
|
|
345
|
+
const rawDetail = diagnostics ?? (text || response.statusText);
|
|
346
|
+
const detail = diagnostics ? rawDetail : rawDetail.split(`
|
|
347
|
+
`).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
|
|
346
348
|
const failure = await buildServerFailureContext(context.projectRoot, server);
|
|
347
349
|
throw new CliError(`Rig server request failed (${response.status}): ${detail}
|
|
348
350
|
${failure.contextLine}`, 1, { hint: failure.hint });
|
|
@@ -361,11 +363,10 @@ var RESUMABLE_RUN_STATUSES = new Set([
|
|
|
361
363
|
"needs_attention"
|
|
362
364
|
]);
|
|
363
365
|
|
|
364
|
-
// packages/cli/src/
|
|
365
|
-
import {
|
|
366
|
-
import pc from "picocolors";
|
|
366
|
+
// packages/cli/src/app/drone-ui.ts
|
|
367
|
+
import { ProcessTerminal, TUI, Text, Input, SelectList, matchesKey } from "@earendil-works/pi-tui";
|
|
367
368
|
|
|
368
|
-
// packages/cli/src/
|
|
369
|
+
// packages/cli/src/app/theme.ts
|
|
369
370
|
var RIG_PALETTE = {
|
|
370
371
|
ink: "#f2f3f6",
|
|
371
372
|
ink2: "#aeb0ba",
|
|
@@ -398,6 +399,9 @@ var accentDim = fg(RIG_PALETTE.accentDim);
|
|
|
398
399
|
var cyan = fg(RIG_PALETTE.cyan);
|
|
399
400
|
var red = fg(RIG_PALETTE.red);
|
|
400
401
|
var yellow = fg(RIG_PALETTE.yellow);
|
|
402
|
+
function bold(text) {
|
|
403
|
+
return `\x1B[1m${text}\x1B[22m`;
|
|
404
|
+
}
|
|
401
405
|
var DRONE_ART = [
|
|
402
406
|
" .-=-. .-=-. ",
|
|
403
407
|
" ( !!! ) ( !!! ) ",
|
|
@@ -418,36 +422,22 @@ var DRONE_ART = [
|
|
|
418
422
|
" ( !!! ) ( !!! ) ",
|
|
419
423
|
" '-=-' '-=-' "
|
|
420
424
|
];
|
|
425
|
+
var EYE_FRAMES = ["@", "o", "."];
|
|
421
426
|
var DRONE_WIDTH = DRONE_ART[0].length;
|
|
422
427
|
var DRONE_HEIGHT = DRONE_ART.length;
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
return
|
|
428
|
-
}
|
|
429
|
-
function printFormattedOutput(message, options = {}) {
|
|
430
|
-
if (!shouldUseClackOutput()) {
|
|
431
|
-
console.log(message);
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
if (options.title)
|
|
435
|
-
note(message, options.title);
|
|
436
|
-
else
|
|
437
|
-
log.message(message);
|
|
428
|
+
var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
|
|
429
|
+
function microDroneFrame(tick) {
|
|
430
|
+
const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
|
|
431
|
+
const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
|
|
432
|
+
return `(${blade})${eye}(${blade})`;
|
|
438
433
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
return [];
|
|
445
|
-
return [pc.bold("Next"), ...steps.map((step) => `${accent("\u203A")} ${step}`)];
|
|
434
|
+
var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
|
|
435
|
+
function renderMicroDroneFrame(tick) {
|
|
436
|
+
const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
|
|
437
|
+
const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
|
|
438
|
+
return `${ink4("(")}${cyan(blade)}${ink4(")")}${bold(accent(eye))}${ink4("(")}${cyan(blade)}${ink4(")")}`;
|
|
446
439
|
}
|
|
447
440
|
|
|
448
|
-
// packages/cli/src/commands/_async-ui.ts
|
|
449
|
-
import pc2 from "picocolors";
|
|
450
|
-
|
|
451
441
|
// packages/cli/src/commands/_spinner.ts
|
|
452
442
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
453
443
|
function createTtySpinner(input) {
|
|
@@ -509,8 +499,40 @@ function createTtySpinner(input) {
|
|
|
509
499
|
};
|
|
510
500
|
}
|
|
511
501
|
|
|
502
|
+
// packages/cli/src/app/drone-ui.ts
|
|
503
|
+
function droneNote(message, title) {
|
|
504
|
+
if (title)
|
|
505
|
+
console.log(` ${accentDim("\u25C7")} ${bold(ink2(title))}`);
|
|
506
|
+
for (const line of message.split(`
|
|
507
|
+
`)) {
|
|
508
|
+
console.log(` ${ink4("\u2502")} ${line}`);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// packages/cli/src/commands/_cli-format.ts
|
|
513
|
+
import pc from "picocolors";
|
|
514
|
+
var themeDim = (value) => ink3(value);
|
|
515
|
+
function shouldUseClackOutput() {
|
|
516
|
+
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
517
|
+
}
|
|
518
|
+
function printFormattedOutput(message, options = {}) {
|
|
519
|
+
if (!shouldUseClackOutput()) {
|
|
520
|
+
console.log(message);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
droneNote(message, options.title);
|
|
524
|
+
}
|
|
525
|
+
function formatSection(title, subtitle) {
|
|
526
|
+
return `${pc.bold(accent("\u25C6"))} ${pc.bold(title)}${subtitle ? themeDim(` \u2014 ${subtitle}`) : ""}`;
|
|
527
|
+
}
|
|
528
|
+
function formatNextSteps(steps) {
|
|
529
|
+
if (steps.length === 0)
|
|
530
|
+
return [];
|
|
531
|
+
return [pc.bold("Next"), ...steps.map((step) => `${accent("\u203A")} ${step}`)];
|
|
532
|
+
}
|
|
533
|
+
|
|
512
534
|
// packages/cli/src/commands/_async-ui.ts
|
|
513
|
-
|
|
535
|
+
import pc2 from "picocolors";
|
|
514
536
|
var DONE_SYMBOL = pc2.green("\u25C7");
|
|
515
537
|
var FAIL_SYMBOL = pc2.red("\u25A0");
|
|
516
538
|
var activeUpdate = null;
|
|
@@ -544,8 +566,8 @@ async function withSpinner(label, work, options = {}) {
|
|
|
544
566
|
const spinner = createTtySpinner({
|
|
545
567
|
label,
|
|
546
568
|
output,
|
|
547
|
-
frames:
|
|
548
|
-
styleFrame: (frame) =>
|
|
569
|
+
frames: MICRO_DRONE_FRAMES,
|
|
570
|
+
styleFrame: (frame) => renderMicroDroneFrame(Math.max(0, MICRO_DRONE_FRAMES.indexOf(frame)))
|
|
549
571
|
});
|
|
550
572
|
const update = (next) => {
|
|
551
573
|
lastLabel = next;
|
|
@@ -567,7 +589,6 @@ async function withSpinner(label, work, options = {}) {
|
|
|
567
589
|
}
|
|
568
590
|
|
|
569
591
|
// packages/cli/src/commands/_help-catalog.ts
|
|
570
|
-
import { intro, log as log2, note as note2, outro } from "@clack/prompts";
|
|
571
592
|
import pc3 from "picocolors";
|
|
572
593
|
var TOP_LEVEL_SECTIONS = [
|
|
573
594
|
{
|
|
@@ -870,25 +891,6 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
|
870
891
|
function heading(title) {
|
|
871
892
|
return pc3.bold(pc3.cyan(title));
|
|
872
893
|
}
|
|
873
|
-
function renderRigBanner(version) {
|
|
874
|
-
const m = (s) => pc3.bold(pc3.magenta(s));
|
|
875
|
-
const c = (s) => pc3.bold(pc3.cyan(s));
|
|
876
|
-
const y = (s) => pc3.yellow(s);
|
|
877
|
-
const d = (s) => pc3.dim(s);
|
|
878
|
-
const lines = [
|
|
879
|
-
m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
|
|
880
|
-
m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
|
|
881
|
-
c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
|
|
882
|
-
c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
|
|
883
|
-
y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
|
|
884
|
-
y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
|
|
885
|
-
"",
|
|
886
|
-
` ${c("\u25E2\u25E4")} ${pc3.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
|
|
887
|
-
version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
|
|
888
|
-
];
|
|
889
|
-
return lines.join(`
|
|
890
|
-
`);
|
|
891
|
-
}
|
|
892
894
|
function commandLine(command, description) {
|
|
893
895
|
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
894
896
|
return `${pc3.dim("\u2502")} ${pc3.bold(commandColumn)} ${description}`;
|
|
@@ -942,67 +944,8 @@ function renderGroupHelp(groupName) {
|
|
|
942
944
|
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
943
945
|
return group ? renderGroup(group) : null;
|
|
944
946
|
}
|
|
945
|
-
function shouldUseClackOutput2() {
|
|
946
|
-
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
947
|
-
}
|
|
948
|
-
function printTopLevelHelp(state = {}) {
|
|
949
|
-
if (!shouldUseClackOutput2()) {
|
|
950
|
-
console.log(renderTopLevelHelp());
|
|
951
|
-
return;
|
|
952
|
-
}
|
|
953
|
-
console.log(renderRigBanner(state.version));
|
|
954
|
-
console.log("");
|
|
955
|
-
if (state.projectInitialized === false) {
|
|
956
|
-
intro("no rig project in this directory");
|
|
957
|
-
note2([
|
|
958
|
-
commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
|
|
959
|
-
commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
|
|
960
|
-
commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
|
|
961
|
-
].join(`
|
|
962
|
-
`), "Get started");
|
|
963
|
-
outro("After init: rig task run --next puts an agent on your next task.");
|
|
964
|
-
return;
|
|
965
|
-
}
|
|
966
|
-
intro(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
|
|
967
|
-
for (const section of TOP_LEVEL_SECTIONS) {
|
|
968
|
-
note2(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
|
|
969
|
-
}
|
|
970
|
-
log2.info("More: rig help --advanced \xB7 rig <group> --help \xB7 rig --version");
|
|
971
|
-
note2([
|
|
972
|
-
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
973
|
-
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
974
|
-
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
975
|
-
].join(`
|
|
976
|
-
`), "Global options");
|
|
977
|
-
outro("init \u2192 task run \u2192 attach (Pi console: watch + steer live) \u2192 inbox \u2192 merged.");
|
|
978
|
-
}
|
|
979
947
|
function printGroupHelpDocument(groupName) {
|
|
980
|
-
|
|
981
|
-
if (!shouldUseClackOutput2()) {
|
|
982
|
-
console.log(rendered);
|
|
983
|
-
return;
|
|
984
|
-
}
|
|
985
|
-
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
986
|
-
if (!group) {
|
|
987
|
-
printTopLevelHelp();
|
|
988
|
-
return;
|
|
989
|
-
}
|
|
990
|
-
intro(`rig ${group.name}`);
|
|
991
|
-
note2(group.summary, "Purpose");
|
|
992
|
-
note2(group.usage.join(`
|
|
993
|
-
`), "Usage");
|
|
994
|
-
note2(group.commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
995
|
-
`), "Commands");
|
|
996
|
-
if (group.examples?.length)
|
|
997
|
-
note2(group.examples.map((line) => `$ ${line}`).join(`
|
|
998
|
-
`), "Examples");
|
|
999
|
-
if (group.next?.length)
|
|
1000
|
-
note2(group.next.map((line) => `\u203A ${line}`).join(`
|
|
1001
|
-
`), "Next steps");
|
|
1002
|
-
if (group.advanced?.length)
|
|
1003
|
-
log2.info(group.advanced.join(`
|
|
1004
|
-
`));
|
|
1005
|
-
outro("Run with --json when scripts need structured output.");
|
|
948
|
+
console.log(renderGroupHelp(groupName) ?? renderTopLevelHelp());
|
|
1006
949
|
}
|
|
1007
950
|
|
|
1008
951
|
// packages/cli/src/commands/stats.ts
|
|
@@ -2,7 +2,196 @@
|
|
|
2
2
|
// packages/cli/src/commands/task-report-bug.ts
|
|
3
3
|
import { existsSync as existsSync2, readFileSync, writeFileSync as writeFileSync2 } from "fs";
|
|
4
4
|
import { resolve as resolve3 } from "path";
|
|
5
|
-
|
|
5
|
+
|
|
6
|
+
// packages/cli/src/app/drone-ui.ts
|
|
7
|
+
import { ProcessTerminal, TUI, Text, Input, SelectList, matchesKey } from "@earendil-works/pi-tui";
|
|
8
|
+
|
|
9
|
+
// packages/cli/src/app/theme.ts
|
|
10
|
+
var RIG_PALETTE = {
|
|
11
|
+
ink: "#f2f3f6",
|
|
12
|
+
ink2: "#aeb0ba",
|
|
13
|
+
ink3: "#6c6e79",
|
|
14
|
+
ink4: "#44464f",
|
|
15
|
+
accent: "#ccff4d",
|
|
16
|
+
accentDim: "#a9d63f",
|
|
17
|
+
cyan: "#56d8ff",
|
|
18
|
+
red: "#ff5d5d",
|
|
19
|
+
yellow: "#ffd24d"
|
|
20
|
+
};
|
|
21
|
+
function hexToRgb(hex) {
|
|
22
|
+
const value = hex.replace("#", "");
|
|
23
|
+
return [
|
|
24
|
+
Number.parseInt(value.slice(0, 2), 16),
|
|
25
|
+
Number.parseInt(value.slice(2, 4), 16),
|
|
26
|
+
Number.parseInt(value.slice(4, 6), 16)
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
function fg(hex) {
|
|
30
|
+
const [r, g, b] = hexToRgb(hex);
|
|
31
|
+
return (text) => `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
|
|
32
|
+
}
|
|
33
|
+
var ink = fg(RIG_PALETTE.ink);
|
|
34
|
+
var ink2 = fg(RIG_PALETTE.ink2);
|
|
35
|
+
var ink3 = fg(RIG_PALETTE.ink3);
|
|
36
|
+
var ink4 = fg(RIG_PALETTE.ink4);
|
|
37
|
+
var accent = fg(RIG_PALETTE.accent);
|
|
38
|
+
var accentDim = fg(RIG_PALETTE.accentDim);
|
|
39
|
+
var cyan = fg(RIG_PALETTE.cyan);
|
|
40
|
+
var red = fg(RIG_PALETTE.red);
|
|
41
|
+
var yellow = fg(RIG_PALETTE.yellow);
|
|
42
|
+
function bold(text) {
|
|
43
|
+
return `\x1B[1m${text}\x1B[22m`;
|
|
44
|
+
}
|
|
45
|
+
var DRONE_ART = [
|
|
46
|
+
" .-=-. .-=-. ",
|
|
47
|
+
" ( !!! ) ( !!! ) ",
|
|
48
|
+
" '-=-'._ _.'-=-' ",
|
|
49
|
+
" '._ _.' ",
|
|
50
|
+
" '=$$$$$$$=.' ",
|
|
51
|
+
" =$$$$$$$$$$$= ",
|
|
52
|
+
" $$$@@@@@@@@@@$$$ ",
|
|
53
|
+
" $$$@@ @@$$$ ",
|
|
54
|
+
" $$@ ? @$$$ ",
|
|
55
|
+
" $$$@ '-' @$$$ ",
|
|
56
|
+
" $$$@@ @@$$$ ",
|
|
57
|
+
" $$$@@@@@@@@@@$$$ ",
|
|
58
|
+
" =$$$$$$$$$$$= ",
|
|
59
|
+
" '=$$$$$$$=.' ",
|
|
60
|
+
" _.' '._ ",
|
|
61
|
+
" .-=-.' '.-=-. ",
|
|
62
|
+
" ( !!! ) ( !!! ) ",
|
|
63
|
+
" '-=-' '-=-' "
|
|
64
|
+
];
|
|
65
|
+
var EYE_FRAMES = ["@", "o", "."];
|
|
66
|
+
var DRONE_WIDTH = DRONE_ART[0].length;
|
|
67
|
+
var DRONE_HEIGHT = DRONE_ART.length;
|
|
68
|
+
var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
|
|
69
|
+
function microDroneFrame(tick) {
|
|
70
|
+
const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
|
|
71
|
+
const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
|
|
72
|
+
return `(${blade})${eye}(${blade})`;
|
|
73
|
+
}
|
|
74
|
+
var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
|
|
75
|
+
|
|
76
|
+
// packages/cli/src/app/drone-ui.ts
|
|
77
|
+
var isTty = () => Boolean(process.stdout.isTTY);
|
|
78
|
+
function hairline(width = Math.min(process.stdout.columns ?? 80, 100)) {
|
|
79
|
+
return ink4("\u2500".repeat(Math.max(10, width)));
|
|
80
|
+
}
|
|
81
|
+
function droneIntro(title, subtitle) {
|
|
82
|
+
console.log("");
|
|
83
|
+
console.log(` ${accent("\u258D")}${bold(ink(title))}${subtitle ? ink3(` \u2014 ${subtitle}`) : ""}`);
|
|
84
|
+
console.log(hairline());
|
|
85
|
+
}
|
|
86
|
+
function droneOutro(text) {
|
|
87
|
+
console.log(hairline());
|
|
88
|
+
console.log(` ${accent("\u25C6")} ${ink2(text)}`);
|
|
89
|
+
console.log("");
|
|
90
|
+
}
|
|
91
|
+
function droneNote(message, title) {
|
|
92
|
+
if (title)
|
|
93
|
+
console.log(` ${accentDim("\u25C7")} ${bold(ink2(title))}`);
|
|
94
|
+
for (const line of message.split(`
|
|
95
|
+
`)) {
|
|
96
|
+
console.log(` ${ink4("\u2502")} ${line}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function droneStep(text) {
|
|
100
|
+
console.log(` ${accent("\u203A")} ${ink(text)}`);
|
|
101
|
+
}
|
|
102
|
+
function droneInfo(text) {
|
|
103
|
+
console.log(` ${cyan("\xB7")} ${ink2(text)}`);
|
|
104
|
+
}
|
|
105
|
+
function droneCancel(text) {
|
|
106
|
+
console.log(` ${red("\u2716")} ${ink3(text)}`);
|
|
107
|
+
}
|
|
108
|
+
var SELECT_THEME = {
|
|
109
|
+
selectedPrefix: (text) => accent(text),
|
|
110
|
+
selectedText: (text) => bold(ink(text)),
|
|
111
|
+
description: (text) => ink3(text),
|
|
112
|
+
scrollInfo: (text) => ink4(text),
|
|
113
|
+
noMatch: (text) => ink3(text)
|
|
114
|
+
};
|
|
115
|
+
async function runMiniTui(build) {
|
|
116
|
+
const terminal = new ProcessTerminal;
|
|
117
|
+
const tui = new TUI(terminal);
|
|
118
|
+
let settled = false;
|
|
119
|
+
return await new Promise((resolve) => {
|
|
120
|
+
const finish = (result) => {
|
|
121
|
+
if (settled)
|
|
122
|
+
return;
|
|
123
|
+
settled = true;
|
|
124
|
+
tui.stop();
|
|
125
|
+
resolve(result);
|
|
126
|
+
};
|
|
127
|
+
build(tui, finish);
|
|
128
|
+
tui.start();
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async function droneSelect(input) {
|
|
132
|
+
if (!isTty() || input.options.length === 0) {
|
|
133
|
+
return input.initialValue ?? input.options[0]?.value ?? null;
|
|
134
|
+
}
|
|
135
|
+
return runMiniTui((tui, finish) => {
|
|
136
|
+
tui.addChild(new Text(` ${accent("\u258D")}${bold(ink(input.message))}`));
|
|
137
|
+
const items = input.options.map((option) => ({
|
|
138
|
+
value: option.value,
|
|
139
|
+
label: option.label,
|
|
140
|
+
...option.hint ? { description: option.hint } : {}
|
|
141
|
+
}));
|
|
142
|
+
const list = new SelectList(items, Math.min(items.length, 12), SELECT_THEME);
|
|
143
|
+
const initialIndex = input.initialValue ? items.findIndex((item) => item.value === input.initialValue) : -1;
|
|
144
|
+
if (initialIndex > 0)
|
|
145
|
+
list.setSelectedIndex(initialIndex);
|
|
146
|
+
list.onSelect = (item) => finish(item.value);
|
|
147
|
+
list.onCancel = () => finish(null);
|
|
148
|
+
tui.addChild(list);
|
|
149
|
+
tui.addChild(new Text(ink4(" \u2191\u2193 navigate \xB7 enter select \xB7 esc cancel")));
|
|
150
|
+
tui.setFocus(list);
|
|
151
|
+
tui.addInputListener((data) => {
|
|
152
|
+
if (matchesKey(data, "ctrl+c") || matchesKey(data, "escape")) {
|
|
153
|
+
finish(null);
|
|
154
|
+
return { consume: true };
|
|
155
|
+
}
|
|
156
|
+
return;
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
async function droneText(input) {
|
|
161
|
+
if (!isTty())
|
|
162
|
+
return input.initialValue ?? null;
|
|
163
|
+
return runMiniTui((tui, finish) => {
|
|
164
|
+
tui.addChild(new Text(` ${accent("\u258D")}${bold(ink(input.message))}${input.placeholder ? ink4(` (${input.placeholder})`) : ""}`));
|
|
165
|
+
const field = new Input;
|
|
166
|
+
if (input.initialValue)
|
|
167
|
+
field.setValue(input.initialValue);
|
|
168
|
+
field.onSubmit = (value) => finish(value);
|
|
169
|
+
field.onEscape = () => finish(null);
|
|
170
|
+
tui.addChild(field);
|
|
171
|
+
tui.addChild(new Text(ink4(" enter submit \xB7 esc cancel")));
|
|
172
|
+
tui.setFocus(field);
|
|
173
|
+
tui.addInputListener((data) => {
|
|
174
|
+
if (matchesKey(data, "ctrl+c")) {
|
|
175
|
+
finish(null);
|
|
176
|
+
return { consume: true };
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
async function droneConfirm(input) {
|
|
183
|
+
const answer = await droneSelect({
|
|
184
|
+
message: input.message,
|
|
185
|
+
options: [
|
|
186
|
+
{ value: "yes", label: "Yes" },
|
|
187
|
+
{ value: "no", label: "No" }
|
|
188
|
+
],
|
|
189
|
+
initialValue: input.initialValue === false ? "no" : "yes"
|
|
190
|
+
});
|
|
191
|
+
return answer === null ? null : answer === "yes";
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// packages/cli/src/commands/task-report-bug.ts
|
|
6
195
|
import pc from "picocolors";
|
|
7
196
|
|
|
8
197
|
// packages/cli/src/runner.ts
|
|
@@ -804,14 +993,14 @@ ${result.stdout.trim() || String(error)}`
|
|
|
804
993
|
}
|
|
805
994
|
}
|
|
806
995
|
async function promptForBugReportDetails(initial) {
|
|
807
|
-
|
|
808
|
-
|
|
996
|
+
droneIntro("rig report-bug");
|
|
997
|
+
droneNote([
|
|
809
998
|
"Creates an agent-ready issue with copied evidence files.",
|
|
810
999
|
"When prompted for assets, drag screenshots/videos into the terminal and press Enter."
|
|
811
1000
|
].join(`
|
|
812
1001
|
`), "Bug report wizard");
|
|
813
|
-
|
|
814
|
-
|
|
1002
|
+
droneStep("1/5 Incident");
|
|
1003
|
+
droneNote(bugPromptExampleText("incident"), "Input examples");
|
|
815
1004
|
const title = await promptBugText("Bug title", initial.title, {
|
|
816
1005
|
required: true,
|
|
817
1006
|
placeholder: "Login page never leaves loading"
|
|
@@ -832,8 +1021,8 @@ async function promptForBugReportDetails(initial) {
|
|
|
832
1021
|
const summary = await promptBugText("Short summary", initial.summary, {
|
|
833
1022
|
placeholder: "Email field never appears after navigating from credentials."
|
|
834
1023
|
});
|
|
835
|
-
|
|
836
|
-
|
|
1024
|
+
droneStep("2/5 Reproduction");
|
|
1025
|
+
droneNote(bugPromptExampleText("reproduction"), "Input examples");
|
|
837
1026
|
const steps = splitPromptList(await promptBugText("Repro steps (semicolon-separated)", initial.steps.join("; "), {
|
|
838
1027
|
placeholder: "Open /login; Enter qa@example.com; Press Continue"
|
|
839
1028
|
}));
|
|
@@ -843,14 +1032,14 @@ async function promptForBugReportDetails(initial) {
|
|
|
843
1032
|
const actual = await promptBugText("Actual behavior", initial.actual, {
|
|
844
1033
|
placeholder: "Loading shell stays forever."
|
|
845
1034
|
});
|
|
846
|
-
|
|
847
|
-
|
|
1035
|
+
droneStep("3/5 Evidence");
|
|
1036
|
+
droneNote(bugPromptExampleText("evidence"), "Input examples");
|
|
848
1037
|
const evidence = splitPromptList(await promptBugText("Evidence notes (console/network/API; semicolon-separated)", initial.evidence.join("; "), {
|
|
849
1038
|
placeholder: "Console: ChunkLoadError for credentials route; Network: /assets/app.js 404"
|
|
850
1039
|
}));
|
|
851
1040
|
const assets = splitDroppedAssetList(await promptBugText("Drag screenshots/videos here (Enter to skip)", initial.assets.map(formatDroppedAssetDefault).join(" "), { placeholder: "/Users/me/Desktop/login-loading.png /Users/me/Desktop/otp-flow.webm" }));
|
|
852
|
-
|
|
853
|
-
|
|
1041
|
+
droneStep("4/5 Routing");
|
|
1042
|
+
droneNote(bugPromptExampleText("routing"), "Input examples");
|
|
854
1043
|
const priority = await promptBugSelect("Priority", [
|
|
855
1044
|
{ value: "P0", label: "P0", hint: "urgent / blocking" },
|
|
856
1045
|
{ value: "P1", label: "P1", hint: "high" },
|
|
@@ -864,13 +1053,13 @@ async function promptForBugReportDetails(initial) {
|
|
|
864
1053
|
const parent = await promptBugText("Parent task or epic id (optional)", initial.parent, {
|
|
865
1054
|
placeholder: "bd-auth-epic-123"
|
|
866
1055
|
});
|
|
867
|
-
|
|
868
|
-
|
|
1056
|
+
droneStep("5/5 Browser");
|
|
1057
|
+
droneNote(bugPromptExampleText("browser"), "Input examples");
|
|
869
1058
|
const browserRequired = await promptBugConfirm("Does this task need Rig Browser wiring?", initial.browserRequired);
|
|
870
1059
|
let viewport = initial.viewport || "1440x900";
|
|
871
1060
|
let profile = initial.profile;
|
|
872
1061
|
if (browserRequired) {
|
|
873
|
-
|
|
1062
|
+
droneNote([
|
|
874
1063
|
"A profile is the browser state bucket: cookies, localStorage, auth session, and cache.",
|
|
875
1064
|
"Use a bug-specific profile for clean login/OTP runs; use a shared profile only when saved auth matters."
|
|
876
1065
|
].join(`
|
|
@@ -878,11 +1067,11 @@ async function promptForBugReportDetails(initial) {
|
|
|
878
1067
|
viewport = await promptBugText("Viewport", viewport, { placeholder: "1440x900" });
|
|
879
1068
|
profile = await promptBugText("Rig Browser profile", initial.profile || (title ? defaultBrowserBugProfile(title) : undefined), { placeholder: "hp-next-login-loading-clean" });
|
|
880
1069
|
} else {
|
|
881
|
-
|
|
1070
|
+
droneInfo("Browser wiring skipped. The task will keep assets and steps, but no browser block or browser validation.");
|
|
882
1071
|
}
|
|
883
1072
|
const outputRoot = initial.createBeadsTask ? initial.outputRoot : await promptBugText("Output directory", initial.outputRoot || "docs/bug-reports");
|
|
884
1073
|
const overwrite = await promptBugConfirm("Overwrite if report exists?", initial.overwrite);
|
|
885
|
-
|
|
1074
|
+
droneOutro("Bug report input captured.");
|
|
886
1075
|
return {
|
|
887
1076
|
...initial,
|
|
888
1077
|
outputRoot,
|
|
@@ -909,13 +1098,21 @@ async function promptForBugReportDetails(initial) {
|
|
|
909
1098
|
};
|
|
910
1099
|
}
|
|
911
1100
|
async function promptBugText(message, defaultValue, options = {}) {
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
1101
|
+
for (;; ) {
|
|
1102
|
+
const result = await droneText({
|
|
1103
|
+
message,
|
|
1104
|
+
...options.placeholder ? { placeholder: options.placeholder } : {},
|
|
1105
|
+
...defaultValue?.trim() ? { initialValue: defaultValue } : {}
|
|
1106
|
+
});
|
|
1107
|
+
if (result === null) {
|
|
1108
|
+
droneCancel("Bug report cancelled.");
|
|
1109
|
+
throw new CliError("Bug report cancelled by user.");
|
|
1110
|
+
}
|
|
1111
|
+
const invalid = options.required ? validateRequiredBugPromptValue(result, message) : undefined;
|
|
1112
|
+
if (!invalid)
|
|
1113
|
+
return result.trim();
|
|
1114
|
+
droneInfo(invalid);
|
|
1115
|
+
}
|
|
919
1116
|
}
|
|
920
1117
|
function validateRequiredBugPromptValue(value, label) {
|
|
921
1118
|
return value?.trim() ? undefined : `${label} is required.`;
|
|
@@ -924,7 +1121,7 @@ function bugPromptExampleText(section, options = {}) {
|
|
|
924
1121
|
const c = pc.createColors(options.color ?? shouldColorizeCliOutput());
|
|
925
1122
|
const label = (value) => c.bold(c.cyan(value));
|
|
926
1123
|
const example = (value) => c.green(value);
|
|
927
|
-
const
|
|
1124
|
+
const note = (value) => c.dim(value);
|
|
928
1125
|
const rows = {
|
|
929
1126
|
incident: [
|
|
930
1127
|
["Bug title", "Login page never leaves loading", "short user-visible failure"],
|
|
@@ -953,29 +1150,23 @@ function bugPromptExampleText(section, options = {}) {
|
|
|
953
1150
|
]
|
|
954
1151
|
};
|
|
955
1152
|
return rows[section].map(([name, value, detail]) => {
|
|
956
|
-
const suffix = detail ? ` ${
|
|
1153
|
+
const suffix = detail ? ` ${note(`(${detail})`)}` : "";
|
|
957
1154
|
return `${label(name)}: ${example(value)}${suffix}`;
|
|
958
1155
|
}).join(`
|
|
959
1156
|
`);
|
|
960
1157
|
}
|
|
961
1158
|
async function promptBugConfirm(message, initialValue) {
|
|
962
|
-
const result = await
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1159
|
+
const result = await droneConfirm({ message, initialValue });
|
|
1160
|
+
if (result === null) {
|
|
1161
|
+
droneCancel("Bug report cancelled.");
|
|
1162
|
+
throw new CliError("Bug report cancelled by user.");
|
|
1163
|
+
}
|
|
1164
|
+
return result;
|
|
967
1165
|
}
|
|
968
1166
|
async function promptBugSelect(message, options, initialValue) {
|
|
969
|
-
const result = await
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
initialValue
|
|
973
|
-
});
|
|
974
|
-
return unwrapClackPrompt(result);
|
|
975
|
-
}
|
|
976
|
-
function unwrapClackPrompt(result) {
|
|
977
|
-
if (clack.isCancel(result)) {
|
|
978
|
-
clack.cancel("Bug report cancelled.");
|
|
1167
|
+
const result = await droneSelect({ message, options, initialValue });
|
|
1168
|
+
if (result === null) {
|
|
1169
|
+
droneCancel("Bug report cancelled.");
|
|
979
1170
|
throw new CliError("Bug report cancelled by user.");
|
|
980
1171
|
}
|
|
981
1172
|
return result;
|
|
@@ -728,7 +728,9 @@ ${failure.contextLine}`, 1, { hint: failure.hint });
|
|
|
728
728
|
})() : null;
|
|
729
729
|
if (!response.ok) {
|
|
730
730
|
const diagnostics = diagnosticMessage(payload);
|
|
731
|
-
const
|
|
731
|
+
const rawDetail = diagnostics ?? (text || response.statusText);
|
|
732
|
+
const detail = diagnostics ? rawDetail : rawDetail.split(`
|
|
733
|
+
`).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
|
|
732
734
|
const failure = await buildServerFailureContext(context.projectRoot, server);
|
|
733
735
|
throw new CliError(`Rig server request failed (${response.status}): ${detail}
|
|
734
736
|
${failure.contextLine}`, 1, { hint: failure.hint });
|