@h-rig/cli 0.0.6-alpha.35 → 0.0.6-alpha.37
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 +158 -41
- package/dist/src/commands/_help-catalog.js +63 -32
- package/dist/src/commands/_operator-view.js +35 -4
- package/dist/src/commands/_pi-frontend.js +35 -4
- package/dist/src/commands/_pi-worker-bridge-extension.js +35 -2
- package/dist/src/commands/_run-driver-helpers.js +21 -0
- package/dist/src/commands/_server-client.js +0 -9
- package/dist/src/commands/inspect.js +227 -11
- package/dist/src/commands/run.js +35 -4
- package/dist/src/commands/server.js +7 -2
- package/dist/src/commands/task-run-driver.js +21 -0
- package/dist/src/commands/task.js +97 -36
- package/dist/src/commands.js +158 -41
- package/dist/src/index.js +158 -41
- package/package.json +6 -6
package/dist/bin/rig.js
CHANGED
|
@@ -531,7 +531,8 @@ import { loadPolicy as loadPolicy3 } from "@rig/runtime/control-plane/runtime/gu
|
|
|
531
531
|
// packages/cli/src/commands.ts
|
|
532
532
|
init_runner();
|
|
533
533
|
import {
|
|
534
|
-
existsSync as existsSync16
|
|
534
|
+
existsSync as existsSync16,
|
|
535
|
+
readFileSync as readFileSync12
|
|
535
536
|
} from "fs";
|
|
536
537
|
import { resolve as resolve25 } from "path";
|
|
537
538
|
import { readBuildConfig } from "@rig/runtime/build-time-config";
|
|
@@ -6305,6 +6306,7 @@ ${acceptance}` : null,
|
|
|
6305
6306
|
${sourceContractLines.join(`
|
|
6306
6307
|
`)}` : null,
|
|
6307
6308
|
scopeText || renderSourceScopeValidation(sourceTask, sourceValidation) || null,
|
|
6309
|
+
readPriorPrProgressForPrompt(input.projectRoot, input.taskId),
|
|
6308
6310
|
initialPrompt ? `Additional operator guidance:
|
|
6309
6311
|
${initialPrompt}` : null,
|
|
6310
6312
|
providerLines.length > 0 ? `Provider-specific runtime tooling:
|
|
@@ -6314,6 +6316,26 @@ ${providerLines.join(" ")}` : null,
|
|
|
6314
6316
|
|
|
6315
6317
|
`);
|
|
6316
6318
|
}
|
|
6319
|
+
function readPriorPrProgressForPrompt(projectRoot, taskId) {
|
|
6320
|
+
for (const candidate of [
|
|
6321
|
+
resolve20(projectRoot, ".worktrees", taskId, "artifacts", taskId, "pr-state.json"),
|
|
6322
|
+
resolve20(projectRoot, "artifacts", taskId, "pr-state.json")
|
|
6323
|
+
]) {
|
|
6324
|
+
try {
|
|
6325
|
+
const raw = JSON.parse(readFileSync8(candidate, "utf8"));
|
|
6326
|
+
const entries = Array.isArray(raw) ? raw : [raw];
|
|
6327
|
+
const first = entries.find((entry) => entry && typeof entry === "object" && typeof entry.url === "string");
|
|
6328
|
+
if (!first)
|
|
6329
|
+
continue;
|
|
6330
|
+
return [
|
|
6331
|
+
`Prior progress exists for this task: PR ${first.url}${first.branch ? ` (branch ${first.branch})` : ""} was opened by an earlier run.`,
|
|
6332
|
+
"Check its current state first (diff, checks, review). If the work is already complete and checks are green,",
|
|
6333
|
+
"run `rig-agent completion-verification` to merge and close instead of re-implementing anything."
|
|
6334
|
+
].join(" ");
|
|
6335
|
+
} catch {}
|
|
6336
|
+
}
|
|
6337
|
+
return null;
|
|
6338
|
+
}
|
|
6317
6339
|
function firstPromptString(...values) {
|
|
6318
6340
|
for (const value of values) {
|
|
6319
6341
|
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
@@ -6398,7 +6420,24 @@ async function executeInspect(context, args) {
|
|
|
6398
6420
|
const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
|
|
6399
6421
|
const latestRun = listAuthorityRuns2(context.projectRoot).map((entry) => readAuthorityRun3(context.projectRoot, entry.runId)).filter((run) => Boolean(run)).filter((run) => run.taskId === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
|
|
6400
6422
|
if (!latestRun) {
|
|
6401
|
-
|
|
6423
|
+
const serverRuns = await listRunsViaServer(context, { limit: 200 }).catch(() => []);
|
|
6424
|
+
const serverRun = serverRuns.filter((run) => String(run.taskId ?? "") === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
|
|
6425
|
+
if (!serverRun || typeof serverRun.runId !== "string") {
|
|
6426
|
+
throw new CliError2(`No runs found for ${requiredTask} (local or on the selected server).`);
|
|
6427
|
+
}
|
|
6428
|
+
const page = await getRunLogsViaServer(context, serverRun.runId, { limit: 500 });
|
|
6429
|
+
const entries = Array.isArray(page.entries) ? page.entries : [];
|
|
6430
|
+
if (context.outputMode === "text") {
|
|
6431
|
+
for (const entry of entries) {
|
|
6432
|
+
const record = entry && typeof entry === "object" ? entry : {};
|
|
6433
|
+
const title = String(record.title ?? "");
|
|
6434
|
+
const detail = String(record.detail ?? "");
|
|
6435
|
+
console.log([title, detail].filter(Boolean).join(" \u2014 "));
|
|
6436
|
+
}
|
|
6437
|
+
if (entries.length === 0)
|
|
6438
|
+
console.log(`(no log entries for run ${serverRun.runId})`);
|
|
6439
|
+
}
|
|
6440
|
+
return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: serverRun.runId, source: "server", entries } };
|
|
6402
6441
|
}
|
|
6403
6442
|
const logsPath = resolve21(resolveAuthorityRunDir4(context.projectRoot, latestRun.runId), "logs.jsonl");
|
|
6404
6443
|
if (!existsSync13(logsPath)) {
|
|
@@ -7683,7 +7722,38 @@ function parseWsPayload(message2) {
|
|
|
7683
7722
|
return JSON.parse(message2.data);
|
|
7684
7723
|
return JSON.parse(Buffer.from(message2.data).toString("utf8"));
|
|
7685
7724
|
}
|
|
7686
|
-
|
|
7725
|
+
var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
|
|
7726
|
+
function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
|
|
7727
|
+
for (const command of commands) {
|
|
7728
|
+
const record = recordOf(command);
|
|
7729
|
+
const name = typeof record?.name === "string" ? record.name : "";
|
|
7730
|
+
if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
|
|
7731
|
+
continue;
|
|
7732
|
+
registered.add(name);
|
|
7733
|
+
const description = typeof record?.description === "string" ? record.description : undefined;
|
|
7734
|
+
const source = typeof record?.source === "string" ? record.source : "worker";
|
|
7735
|
+
try {
|
|
7736
|
+
pi.registerCommand(name, {
|
|
7737
|
+
description: `[worker ${source}] ${description ?? ""}`.trim(),
|
|
7738
|
+
handler: async (args) => {
|
|
7739
|
+
const text2 = `/${name}${args ? ` ${args}` : ""}`;
|
|
7740
|
+
appendTranscript(state, "You", text2);
|
|
7741
|
+
try {
|
|
7742
|
+
const result = await runRunPiCommandViaServer(options.context, options.runId, text2);
|
|
7743
|
+
const message2 = typeof result.message === "string" ? result.message : "worker command accepted";
|
|
7744
|
+
appendTranscript(state, "System", message2);
|
|
7745
|
+
if (state.nativeStream)
|
|
7746
|
+
ctx.ui.notify(message2, "info");
|
|
7747
|
+
} catch (error) {
|
|
7748
|
+
reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
|
|
7749
|
+
}
|
|
7750
|
+
updatePiUi(ctx, state);
|
|
7751
|
+
}
|
|
7752
|
+
});
|
|
7753
|
+
} catch {}
|
|
7754
|
+
}
|
|
7755
|
+
}
|
|
7756
|
+
async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
|
|
7687
7757
|
const ready = await waitForWorkerReady(options, ctx, state);
|
|
7688
7758
|
if (!ready)
|
|
7689
7759
|
return;
|
|
@@ -7738,6 +7808,7 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
7738
7808
|
const record = recordOf(command);
|
|
7739
7809
|
return typeof record?.name === "string" ? [`/${record.name}`] : [];
|
|
7740
7810
|
});
|
|
7811
|
+
registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
|
|
7741
7812
|
catchupDone = true;
|
|
7742
7813
|
for (const payload of buffered.splice(0))
|
|
7743
7814
|
applyEnvelope(ctx, state, payload);
|
|
@@ -7865,6 +7936,7 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
7865
7936
|
};
|
|
7866
7937
|
if (options.initialMessageSent)
|
|
7867
7938
|
appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
|
|
7939
|
+
const registeredDaemonCommands = new Set;
|
|
7868
7940
|
let nativePiUiContextAvailable = false;
|
|
7869
7941
|
pi.on("user_bash", (event) => {
|
|
7870
7942
|
state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
|
|
@@ -7897,7 +7969,7 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
7897
7969
|
});
|
|
7898
7970
|
return { consume: true };
|
|
7899
7971
|
});
|
|
7900
|
-
connectWorkerStream(options, ctx, state).catch((error) => {
|
|
7972
|
+
connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
|
|
7901
7973
|
appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
|
|
7902
7974
|
updatePiUi(ctx, state);
|
|
7903
7975
|
});
|
|
@@ -7944,8 +8016,6 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
7944
8016
|
"--no-tools",
|
|
7945
8017
|
"--no-builtin-tools",
|
|
7946
8018
|
"--no-skills",
|
|
7947
|
-
"--no-prompt-templates",
|
|
7948
|
-
"--no-themes",
|
|
7949
8019
|
"--no-context-files",
|
|
7950
8020
|
"--no-approve"
|
|
7951
8021
|
], {
|
|
@@ -8490,6 +8560,7 @@ async function executeRun(context, args) {
|
|
|
8490
8560
|
|
|
8491
8561
|
// packages/cli/src/commands/server.ts
|
|
8492
8562
|
init_runner();
|
|
8563
|
+
import { resolveRigServerCommand } from "@rig/runtime/local-server";
|
|
8493
8564
|
async function executeServer(context, args, options) {
|
|
8494
8565
|
const [command = "status", ...rest] = args;
|
|
8495
8566
|
if (["status", "list", "add", "use"].includes(command)) {
|
|
@@ -8507,7 +8578,8 @@ async function executeServer(context, args, options) {
|
|
|
8507
8578
|
const authTokenResult = takeOption(pending, "--auth-token");
|
|
8508
8579
|
pending = authTokenResult.rest;
|
|
8509
8580
|
requireNoExtraArgs(pending, "rig server start [--host <host>] [--port <n>] [--poll-ms <n>] [--auth-token <token>]");
|
|
8510
|
-
const
|
|
8581
|
+
const serverCommand = resolveRigServerCommand(context.projectRoot);
|
|
8582
|
+
const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "start"];
|
|
8511
8583
|
if (hostResult.value) {
|
|
8512
8584
|
commandParts.push("--host", hostResult.value);
|
|
8513
8585
|
}
|
|
@@ -8530,7 +8602,8 @@ async function executeServer(context, args, options) {
|
|
|
8530
8602
|
const eventResult = takeOption(pending, "--event");
|
|
8531
8603
|
pending = eventResult.rest;
|
|
8532
8604
|
requireNoExtraArgs(pending, "rig server notify-test [--event <type>]");
|
|
8533
|
-
const
|
|
8605
|
+
const serverCommand = resolveRigServerCommand(context.projectRoot);
|
|
8606
|
+
const commandParts = [serverCommand.command, ...serverCommand.commandArgs, "notify-test"];
|
|
8534
8607
|
if (eventResult.value) {
|
|
8535
8608
|
commandParts.push("--event", eventResult.value);
|
|
8536
8609
|
}
|
|
@@ -8664,52 +8737,50 @@ import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@c
|
|
|
8664
8737
|
import pc4 from "picocolors";
|
|
8665
8738
|
var TOP_LEVEL_SECTIONS = [
|
|
8666
8739
|
{
|
|
8667
|
-
title: "
|
|
8668
|
-
subtitle: "
|
|
8740
|
+
title: "Start here",
|
|
8741
|
+
subtitle: "one-time setup for a repo",
|
|
8669
8742
|
commands: [
|
|
8670
|
-
{ command: "rig
|
|
8671
|
-
{ command: "rig
|
|
8672
|
-
{ command: "rig server
|
|
8673
|
-
{ command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
|
|
8674
|
-
{ command: "rig server list", description: "Show saved server aliases, including local." }
|
|
8743
|
+
{ command: "rig init", description: "Wizard: config, GitHub auth, task source, server, Pi wiring." },
|
|
8744
|
+
{ command: "rig doctor", description: "Check every part of the wiring \u2014 run this when anything feels off." },
|
|
8745
|
+
{ command: "rig server use <alias|local>", description: "Pick which Rig server owns this repo (`rig server list` to see them)." }
|
|
8675
8746
|
]
|
|
8676
8747
|
},
|
|
8677
8748
|
{
|
|
8678
|
-
title: "
|
|
8679
|
-
subtitle: "find
|
|
8749
|
+
title: "Work",
|
|
8750
|
+
subtitle: "find a task and put an agent on it",
|
|
8680
8751
|
commands: [
|
|
8681
|
-
{ command: "rig task list", description: "
|
|
8682
|
-
{ command: "rig task next", description: "
|
|
8683
|
-
{ command: "rig task
|
|
8684
|
-
{ command: "rig task run <id
|
|
8752
|
+
{ command: "rig task list", description: "What's on the board (from the selected source/server)." },
|
|
8753
|
+
{ command: "rig task next", description: "The next ready task, as a card." },
|
|
8754
|
+
{ command: "rig task run --next", description: "Dispatch an agent; interactive mode opens the native Pi session." },
|
|
8755
|
+
{ command: "rig task run <id> --detach", description: "Fire-and-forget a specific task." }
|
|
8685
8756
|
]
|
|
8686
8757
|
},
|
|
8687
8758
|
{
|
|
8688
|
-
title: "
|
|
8689
|
-
subtitle: "
|
|
8759
|
+
title: "Watch & steer",
|
|
8760
|
+
subtitle: "live runs are observable and steerable, attached or not",
|
|
8690
8761
|
commands: [
|
|
8691
|
-
{ command: "rig run
|
|
8692
|
-
{ command: "rig run
|
|
8693
|
-
{ command: "rig run
|
|
8694
|
-
{ command: "rig run stop <id>", description: "
|
|
8762
|
+
{ command: "rig run status", description: "Active and recent runs at a glance." },
|
|
8763
|
+
{ command: "rig run attach <id> --follow", description: "Join the live Pi session (worker keeps running if you /detach)." },
|
|
8764
|
+
{ command: "rig run steer <id> -m <text>", description: "Drop a message into a live worker without attaching." },
|
|
8765
|
+
{ command: "rig run stop <id>", description: "Cancel a running worker." }
|
|
8695
8766
|
]
|
|
8696
8767
|
},
|
|
8697
8768
|
{
|
|
8698
|
-
title: "
|
|
8699
|
-
subtitle: "
|
|
8769
|
+
title: "Unblock & gate",
|
|
8770
|
+
subtitle: "answer what workers ask; control what merges",
|
|
8700
8771
|
commands: [
|
|
8701
|
-
{ command: "rig inbox approvals", description: "
|
|
8702
|
-
{ command: "rig inbox inputs", description: "
|
|
8703
|
-
{ command: "rig review show|set", description: "
|
|
8772
|
+
{ command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." },
|
|
8773
|
+
{ command: "rig inbox inputs", description: "Questions workers asked (then `rig inbox respond \u2026`)." },
|
|
8774
|
+
{ command: "rig review show|set", description: "The completion review gate (Greptile is mandatory on merges)." }
|
|
8704
8775
|
]
|
|
8705
8776
|
},
|
|
8706
8777
|
{
|
|
8707
|
-
title: "
|
|
8708
|
-
subtitle: "
|
|
8778
|
+
title: "Extend",
|
|
8779
|
+
subtitle: "more Pi, more plugins",
|
|
8709
8780
|
commands: [
|
|
8710
|
-
{ command: "rig
|
|
8711
|
-
{ command: "rig
|
|
8712
|
-
{ command: "rig
|
|
8781
|
+
{ command: "rig pi search <term>", description: "Discover community Pi extensions on npm." },
|
|
8782
|
+
{ command: "rig pi add <pkg>", description: "Add a Pi extension to this project (workers pick it up too)." },
|
|
8783
|
+
{ command: "rig plugin list", description: "What the rig.config.ts plugins contribute." }
|
|
8713
8784
|
]
|
|
8714
8785
|
}
|
|
8715
8786
|
];
|
|
@@ -8917,6 +8988,25 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
|
8917
8988
|
function heading(title) {
|
|
8918
8989
|
return pc4.bold(pc4.cyan(title));
|
|
8919
8990
|
}
|
|
8991
|
+
function renderRigBanner(version) {
|
|
8992
|
+
const m = (s) => pc4.bold(pc4.magenta(s));
|
|
8993
|
+
const c = (s) => pc4.bold(pc4.cyan(s));
|
|
8994
|
+
const y = (s) => pc4.yellow(s);
|
|
8995
|
+
const d = (s) => pc4.dim(s);
|
|
8996
|
+
const lines = [
|
|
8997
|
+
m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
|
|
8998
|
+
m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
|
|
8999
|
+
c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
|
|
9000
|
+
c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
|
|
9001
|
+
y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
|
|
9002
|
+
y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
|
|
9003
|
+
"",
|
|
9004
|
+
` ${c("\u25E2\u25E4")} ${pc4.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
|
|
9005
|
+
version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
|
|
9006
|
+
];
|
|
9007
|
+
return lines.join(`
|
|
9008
|
+
`);
|
|
9009
|
+
}
|
|
8920
9010
|
function commandLine(command, description) {
|
|
8921
9011
|
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
8922
9012
|
return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
|
|
@@ -8990,12 +9080,25 @@ function renderGroupHelp(groupName) {
|
|
|
8990
9080
|
function shouldUseClackOutput2() {
|
|
8991
9081
|
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
8992
9082
|
}
|
|
8993
|
-
function printTopLevelHelp() {
|
|
9083
|
+
function printTopLevelHelp(state = {}) {
|
|
8994
9084
|
if (!shouldUseClackOutput2()) {
|
|
8995
9085
|
console.log(renderTopLevelHelp());
|
|
8996
9086
|
return;
|
|
8997
9087
|
}
|
|
8998
|
-
|
|
9088
|
+
console.log(renderRigBanner(state.version));
|
|
9089
|
+
console.log("");
|
|
9090
|
+
if (state.projectInitialized === false) {
|
|
9091
|
+
intro3("no rig project in this directory");
|
|
9092
|
+
note4([
|
|
9093
|
+
commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
|
|
9094
|
+
commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
|
|
9095
|
+
commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
|
|
9096
|
+
].join(`
|
|
9097
|
+
`), "Get started");
|
|
9098
|
+
outro3("After init: rig task run --next puts an agent on your next task.");
|
|
9099
|
+
return;
|
|
9100
|
+
}
|
|
9101
|
+
intro3(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
|
|
8999
9102
|
for (const section of TOP_LEVEL_SECTIONS) {
|
|
9000
9103
|
note4(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
|
|
9001
9104
|
}
|
|
@@ -9006,7 +9109,7 @@ function printTopLevelHelp() {
|
|
|
9006
9109
|
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
9007
9110
|
].join(`
|
|
9008
9111
|
`), "Global options");
|
|
9009
|
-
outro3("
|
|
9112
|
+
outro3("init \u2192 task run \u2192 watch/steer \u2192 inbox/review \u2192 merged.");
|
|
9010
9113
|
}
|
|
9011
9114
|
function printAdvancedHelp() {
|
|
9012
9115
|
if (!shouldUseClackOutput2()) {
|
|
@@ -11872,9 +11975,23 @@ function isHelpArg(arg) {
|
|
|
11872
11975
|
function helpText() {
|
|
11873
11976
|
return renderTopLevelHelp();
|
|
11874
11977
|
}
|
|
11978
|
+
function resolveTopLevelLaunchState(context) {
|
|
11979
|
+
const projectInitialized = hasInitializedRigProject(context.projectRoot);
|
|
11980
|
+
let selectedServer = null;
|
|
11981
|
+
if (projectInitialized) {
|
|
11982
|
+
try {
|
|
11983
|
+
const statePath = resolve25(context.projectRoot, ".rig", "state", "connection.json");
|
|
11984
|
+
if (existsSync16(statePath)) {
|
|
11985
|
+
const parsed = JSON.parse(readFileSync12(statePath, "utf-8"));
|
|
11986
|
+
selectedServer = parsed.remoteUrl || parsed.url || parsed.selected || null;
|
|
11987
|
+
}
|
|
11988
|
+
} catch {}
|
|
11989
|
+
}
|
|
11990
|
+
return { projectInitialized, selectedServer, version: process.env.RIG_CLI_VERSION || readBuildConfig().RIG_CLI_VERSION || undefined };
|
|
11991
|
+
}
|
|
11875
11992
|
async function execute(context, args) {
|
|
11876
11993
|
if (args.length === 0) {
|
|
11877
|
-
printTopLevelHelp();
|
|
11994
|
+
printTopLevelHelp(resolveTopLevelLaunchState(context));
|
|
11878
11995
|
return { ok: true, group: "help", command: "show" };
|
|
11879
11996
|
}
|
|
11880
11997
|
const [first, ...rest] = args;
|
|
@@ -4,52 +4,50 @@ import { intro, log, note, outro } from "@clack/prompts";
|
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
var TOP_LEVEL_SECTIONS = [
|
|
6
6
|
{
|
|
7
|
-
title: "
|
|
8
|
-
subtitle: "
|
|
7
|
+
title: "Start here",
|
|
8
|
+
subtitle: "one-time setup for a repo",
|
|
9
9
|
commands: [
|
|
10
|
-
{ command: "rig
|
|
11
|
-
{ command: "rig
|
|
12
|
-
{ command: "rig server
|
|
13
|
-
{ command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
|
|
14
|
-
{ command: "rig server list", description: "Show saved server aliases, including local." }
|
|
10
|
+
{ command: "rig init", description: "Wizard: config, GitHub auth, task source, server, Pi wiring." },
|
|
11
|
+
{ command: "rig doctor", description: "Check every part of the wiring \u2014 run this when anything feels off." },
|
|
12
|
+
{ command: "rig server use <alias|local>", description: "Pick which Rig server owns this repo (`rig server list` to see them)." }
|
|
15
13
|
]
|
|
16
14
|
},
|
|
17
15
|
{
|
|
18
|
-
title: "
|
|
19
|
-
subtitle: "find
|
|
16
|
+
title: "Work",
|
|
17
|
+
subtitle: "find a task and put an agent on it",
|
|
20
18
|
commands: [
|
|
21
|
-
{ command: "rig task list", description: "
|
|
22
|
-
{ command: "rig task next", description: "
|
|
23
|
-
{ command: "rig task
|
|
24
|
-
{ command: "rig task run <id
|
|
19
|
+
{ command: "rig task list", description: "What's on the board (from the selected source/server)." },
|
|
20
|
+
{ command: "rig task next", description: "The next ready task, as a card." },
|
|
21
|
+
{ command: "rig task run --next", description: "Dispatch an agent; interactive mode opens the native Pi session." },
|
|
22
|
+
{ command: "rig task run <id> --detach", description: "Fire-and-forget a specific task." }
|
|
25
23
|
]
|
|
26
24
|
},
|
|
27
25
|
{
|
|
28
|
-
title: "
|
|
29
|
-
subtitle: "
|
|
26
|
+
title: "Watch & steer",
|
|
27
|
+
subtitle: "live runs are observable and steerable, attached or not",
|
|
30
28
|
commands: [
|
|
31
|
-
{ command: "rig run
|
|
32
|
-
{ command: "rig run
|
|
33
|
-
{ command: "rig run
|
|
34
|
-
{ command: "rig run stop <id>", description: "
|
|
29
|
+
{ command: "rig run status", description: "Active and recent runs at a glance." },
|
|
30
|
+
{ command: "rig run attach <id> --follow", description: "Join the live Pi session (worker keeps running if you /detach)." },
|
|
31
|
+
{ command: "rig run steer <id> -m <text>", description: "Drop a message into a live worker without attaching." },
|
|
32
|
+
{ command: "rig run stop <id>", description: "Cancel a running worker." }
|
|
35
33
|
]
|
|
36
34
|
},
|
|
37
35
|
{
|
|
38
|
-
title: "
|
|
39
|
-
subtitle: "
|
|
36
|
+
title: "Unblock & gate",
|
|
37
|
+
subtitle: "answer what workers ask; control what merges",
|
|
40
38
|
commands: [
|
|
41
|
-
{ command: "rig inbox approvals", description: "
|
|
42
|
-
{ command: "rig inbox inputs", description: "
|
|
43
|
-
{ command: "rig review show|set", description: "
|
|
39
|
+
{ command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." },
|
|
40
|
+
{ command: "rig inbox inputs", description: "Questions workers asked (then `rig inbox respond \u2026`)." },
|
|
41
|
+
{ command: "rig review show|set", description: "The completion review gate (Greptile is mandatory on merges)." }
|
|
44
42
|
]
|
|
45
43
|
},
|
|
46
44
|
{
|
|
47
|
-
title: "
|
|
48
|
-
subtitle: "
|
|
45
|
+
title: "Extend",
|
|
46
|
+
subtitle: "more Pi, more plugins",
|
|
49
47
|
commands: [
|
|
50
|
-
{ command: "rig
|
|
51
|
-
{ command: "rig
|
|
52
|
-
{ command: "rig
|
|
48
|
+
{ command: "rig pi search <term>", description: "Discover community Pi extensions on npm." },
|
|
49
|
+
{ command: "rig pi add <pkg>", description: "Add a Pi extension to this project (workers pick it up too)." },
|
|
50
|
+
{ command: "rig plugin list", description: "What the rig.config.ts plugins contribute." }
|
|
53
51
|
]
|
|
54
52
|
}
|
|
55
53
|
];
|
|
@@ -257,6 +255,25 @@ var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
|
257
255
|
function heading(title) {
|
|
258
256
|
return pc.bold(pc.cyan(title));
|
|
259
257
|
}
|
|
258
|
+
function renderRigBanner(version) {
|
|
259
|
+
const m = (s) => pc.bold(pc.magenta(s));
|
|
260
|
+
const c = (s) => pc.bold(pc.cyan(s));
|
|
261
|
+
const y = (s) => pc.yellow(s);
|
|
262
|
+
const d = (s) => pc.dim(s);
|
|
263
|
+
const lines = [
|
|
264
|
+
m(" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ") + d(" \u2591\u2592\u2593\u2588 "),
|
|
265
|
+
m(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D ") + d("\u2593\u2592\u2591"),
|
|
266
|
+
c(" \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557") + d(" \u2591\u2592"),
|
|
267
|
+
c(" \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551") + d(" \u2588\u2593\u2591"),
|
|
268
|
+
y(" \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D") + d(" \u2592\u2591"),
|
|
269
|
+
y(" \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D "),
|
|
270
|
+
"",
|
|
271
|
+
` ${c("\u25E2\u25E4")} ${pc.bold("the control rig for autonomous coding agents")} ${m("//")} ${d("you are the operator")}`,
|
|
272
|
+
version ? ` ${d(`v${version} \xB7 jack in: rig task run --next`)}` : ` ${d("jack in: rig task run --next")}`
|
|
273
|
+
];
|
|
274
|
+
return lines.join(`
|
|
275
|
+
`);
|
|
276
|
+
}
|
|
260
277
|
function commandLine(command, description) {
|
|
261
278
|
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
262
279
|
return `${pc.dim("\u2502")} ${pc.bold(commandColumn)} ${description}`;
|
|
@@ -333,12 +350,25 @@ function listHelpGroups() {
|
|
|
333
350
|
function shouldUseClackOutput() {
|
|
334
351
|
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
335
352
|
}
|
|
336
|
-
function printTopLevelHelp() {
|
|
353
|
+
function printTopLevelHelp(state = {}) {
|
|
337
354
|
if (!shouldUseClackOutput()) {
|
|
338
355
|
console.log(renderTopLevelHelp());
|
|
339
356
|
return;
|
|
340
357
|
}
|
|
341
|
-
|
|
358
|
+
console.log(renderRigBanner(state.version));
|
|
359
|
+
console.log("");
|
|
360
|
+
if (state.projectInitialized === false) {
|
|
361
|
+
intro("no rig project in this directory");
|
|
362
|
+
note([
|
|
363
|
+
commandLine("rig init", "Set this repo up: config, GitHub auth, task source, server, Pi."),
|
|
364
|
+
commandLine("rig init --yes", "Same, non-interactive, sensible defaults."),
|
|
365
|
+
commandLine("rig doctor", "Already initialized somewhere else? Check the wiring.")
|
|
366
|
+
].join(`
|
|
367
|
+
`), "Get started");
|
|
368
|
+
outro("After init: rig task run --next puts an agent on your next task.");
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
intro(state.selectedServer ? `server: ${state.selectedServer}` : "rig");
|
|
342
372
|
for (const section of TOP_LEVEL_SECTIONS) {
|
|
343
373
|
note(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
|
|
344
374
|
}
|
|
@@ -349,7 +379,7 @@ function printTopLevelHelp() {
|
|
|
349
379
|
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
350
380
|
].join(`
|
|
351
381
|
`), "Global options");
|
|
352
|
-
outro("
|
|
382
|
+
outro("init \u2192 task run \u2192 watch/steer \u2192 inbox/review \u2192 merged.");
|
|
353
383
|
}
|
|
354
384
|
function printAdvancedHelp() {
|
|
355
385
|
if (!shouldUseClackOutput()) {
|
|
@@ -393,6 +423,7 @@ function printGroupHelpDocument(groupName) {
|
|
|
393
423
|
}
|
|
394
424
|
export {
|
|
395
425
|
renderTopLevelHelp,
|
|
426
|
+
renderRigBanner,
|
|
396
427
|
renderGroupHelp,
|
|
397
428
|
renderAdvancedHelp,
|
|
398
429
|
printTopLevelHelp,
|
|
@@ -802,7 +802,38 @@ function parseWsPayload(message) {
|
|
|
802
802
|
return JSON.parse(message.data);
|
|
803
803
|
return JSON.parse(Buffer.from(message.data).toString("utf8"));
|
|
804
804
|
}
|
|
805
|
-
|
|
805
|
+
var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
|
|
806
|
+
function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
|
|
807
|
+
for (const command of commands) {
|
|
808
|
+
const record = recordOf(command);
|
|
809
|
+
const name = typeof record?.name === "string" ? record.name : "";
|
|
810
|
+
if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
|
|
811
|
+
continue;
|
|
812
|
+
registered.add(name);
|
|
813
|
+
const description = typeof record?.description === "string" ? record.description : undefined;
|
|
814
|
+
const source = typeof record?.source === "string" ? record.source : "worker";
|
|
815
|
+
try {
|
|
816
|
+
pi.registerCommand(name, {
|
|
817
|
+
description: `[worker ${source}] ${description ?? ""}`.trim(),
|
|
818
|
+
handler: async (args) => {
|
|
819
|
+
const text = `/${name}${args ? ` ${args}` : ""}`;
|
|
820
|
+
appendTranscript(state, "You", text);
|
|
821
|
+
try {
|
|
822
|
+
const result = await runRunPiCommandViaServer(options.context, options.runId, text);
|
|
823
|
+
const message = typeof result.message === "string" ? result.message : "worker command accepted";
|
|
824
|
+
appendTranscript(state, "System", message);
|
|
825
|
+
if (state.nativeStream)
|
|
826
|
+
ctx.ui.notify(message, "info");
|
|
827
|
+
} catch (error) {
|
|
828
|
+
reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
|
|
829
|
+
}
|
|
830
|
+
updatePiUi(ctx, state);
|
|
831
|
+
}
|
|
832
|
+
});
|
|
833
|
+
} catch {}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
|
|
806
837
|
const ready = await waitForWorkerReady(options, ctx, state);
|
|
807
838
|
if (!ready)
|
|
808
839
|
return;
|
|
@@ -857,6 +888,7 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
857
888
|
const record = recordOf(command);
|
|
858
889
|
return typeof record?.name === "string" ? [`/${record.name}`] : [];
|
|
859
890
|
});
|
|
891
|
+
registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
|
|
860
892
|
catchupDone = true;
|
|
861
893
|
for (const payload of buffered.splice(0))
|
|
862
894
|
applyEnvelope(ctx, state, payload);
|
|
@@ -984,6 +1016,7 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
984
1016
|
};
|
|
985
1017
|
if (options.initialMessageSent)
|
|
986
1018
|
appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
|
|
1019
|
+
const registeredDaemonCommands = new Set;
|
|
987
1020
|
let nativePiUiContextAvailable = false;
|
|
988
1021
|
pi.on("user_bash", (event) => {
|
|
989
1022
|
state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
|
|
@@ -1016,7 +1049,7 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
1016
1049
|
});
|
|
1017
1050
|
return { consume: true };
|
|
1018
1051
|
});
|
|
1019
|
-
connectWorkerStream(options, ctx, state).catch((error) => {
|
|
1052
|
+
connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
|
|
1020
1053
|
appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
|
|
1021
1054
|
updatePiUi(ctx, state);
|
|
1022
1055
|
});
|
|
@@ -1063,8 +1096,6 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
1063
1096
|
"--no-tools",
|
|
1064
1097
|
"--no-builtin-tools",
|
|
1065
1098
|
"--no-skills",
|
|
1066
|
-
"--no-prompt-templates",
|
|
1067
|
-
"--no-themes",
|
|
1068
1099
|
"--no-context-files",
|
|
1069
1100
|
"--no-approve"
|
|
1070
1101
|
], {
|
|
@@ -576,7 +576,38 @@ function parseWsPayload(message) {
|
|
|
576
576
|
return JSON.parse(message.data);
|
|
577
577
|
return JSON.parse(Buffer.from(message.data).toString("utf8"));
|
|
578
578
|
}
|
|
579
|
-
|
|
579
|
+
var BRIDGE_LOCAL_COMMANDS = new Set(["detach", "quit", "q", "stop"]);
|
|
580
|
+
function registerDaemonCommandsNatively(pi, options, ctx, state, commands, registered) {
|
|
581
|
+
for (const command of commands) {
|
|
582
|
+
const record = recordOf(command);
|
|
583
|
+
const name = typeof record?.name === "string" ? record.name : "";
|
|
584
|
+
if (!name || registered.has(name) || BRIDGE_LOCAL_COMMANDS.has(name))
|
|
585
|
+
continue;
|
|
586
|
+
registered.add(name);
|
|
587
|
+
const description = typeof record?.description === "string" ? record.description : undefined;
|
|
588
|
+
const source = typeof record?.source === "string" ? record.source : "worker";
|
|
589
|
+
try {
|
|
590
|
+
pi.registerCommand(name, {
|
|
591
|
+
description: `[worker ${source}] ${description ?? ""}`.trim(),
|
|
592
|
+
handler: async (args) => {
|
|
593
|
+
const text = `/${name}${args ? ` ${args}` : ""}`;
|
|
594
|
+
appendTranscript(state, "You", text);
|
|
595
|
+
try {
|
|
596
|
+
const result = await runRunPiCommandViaServer(options.context, options.runId, text);
|
|
597
|
+
const message = typeof result.message === "string" ? result.message : "worker command accepted";
|
|
598
|
+
appendTranscript(state, "System", message);
|
|
599
|
+
if (state.nativeStream)
|
|
600
|
+
ctx.ui.notify(message, "info");
|
|
601
|
+
} catch (error) {
|
|
602
|
+
reportBridgeError(ctx, state, error instanceof Error ? error.message : String(error));
|
|
603
|
+
}
|
|
604
|
+
updatePiUi(ctx, state);
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
} catch {}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
async function connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands) {
|
|
580
611
|
const ready = await waitForWorkerReady(options, ctx, state);
|
|
581
612
|
if (!ready)
|
|
582
613
|
return;
|
|
@@ -631,6 +662,7 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
631
662
|
const record = recordOf(command);
|
|
632
663
|
return typeof record?.name === "string" ? [`/${record.name}`] : [];
|
|
633
664
|
});
|
|
665
|
+
registerDaemonCommandsNatively(pi, options, ctx, state, commands, registeredDaemonCommands);
|
|
634
666
|
catchupDone = true;
|
|
635
667
|
for (const payload of buffered.splice(0))
|
|
636
668
|
applyEnvelope(ctx, state, payload);
|
|
@@ -758,6 +790,7 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
758
790
|
};
|
|
759
791
|
if (options.initialMessageSent)
|
|
760
792
|
appendTranscript(state, "System", "Initial message sent to worker Pi daemon.");
|
|
793
|
+
const registeredDaemonCommands = new Set;
|
|
761
794
|
let nativePiUiContextAvailable = false;
|
|
762
795
|
pi.on("user_bash", (event) => {
|
|
763
796
|
state.nativeStream = Boolean(state.nativeStream || nativePiUiContextAvailable);
|
|
@@ -790,7 +823,7 @@ function createRigWorkerPiBridgeExtension(options) {
|
|
|
790
823
|
});
|
|
791
824
|
return { consume: true };
|
|
792
825
|
});
|
|
793
|
-
connectWorkerStream(options, ctx, state).catch((error) => {
|
|
826
|
+
connectWorkerStream(options, pi, ctx, state, registeredDaemonCommands).catch((error) => {
|
|
794
827
|
appendTranscript(state, "Error", error instanceof Error ? error.message : String(error));
|
|
795
828
|
updatePiUi(ctx, state);
|
|
796
829
|
});
|
|
@@ -837,8 +870,6 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
837
870
|
"--no-tools",
|
|
838
871
|
"--no-builtin-tools",
|
|
839
872
|
"--no-skills",
|
|
840
|
-
"--no-prompt-templates",
|
|
841
|
-
"--no-themes",
|
|
842
873
|
"--no-context-files",
|
|
843
874
|
"--no-approve"
|
|
844
875
|
], {
|