@h-rig/cli 0.0.6-alpha.74 → 0.0.6-alpha.75
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 +40 -18
- package/dist/src/commands/_help-catalog.js +32 -14
- package/dist/src/commands/_operator-view.js +98 -92
- package/dist/src/commands/_pi-frontend.js +134 -4
- package/dist/src/commands/run.js +98 -92
- package/dist/src/commands/stats.js +32 -14
- package/dist/src/commands/task.js +40 -18
- package/dist/src/commands.js +40 -18
- package/dist/src/index.js +40 -18
- package/package.json +9 -8
package/dist/src/commands/run.js
CHANGED
|
@@ -812,98 +812,6 @@ import { tmpdir } from "os";
|
|
|
812
812
|
import { join as join2 } from "path";
|
|
813
813
|
import { main as runPiMain } from "@earendil-works/pi-coding-agent";
|
|
814
814
|
import createPiRigExtension from "@rig/pi-rig";
|
|
815
|
-
function setTemporaryEnv(updates) {
|
|
816
|
-
const previous = new Map;
|
|
817
|
-
for (const [key, value] of Object.entries(updates)) {
|
|
818
|
-
previous.set(key, process.env[key]);
|
|
819
|
-
process.env[key] = value;
|
|
820
|
-
}
|
|
821
|
-
return () => {
|
|
822
|
-
for (const [key, value] of previous) {
|
|
823
|
-
if (value === undefined)
|
|
824
|
-
delete process.env[key];
|
|
825
|
-
else
|
|
826
|
-
process.env[key] = value;
|
|
827
|
-
}
|
|
828
|
-
};
|
|
829
|
-
}
|
|
830
|
-
function buildOperatorPiEnv(input) {
|
|
831
|
-
return {
|
|
832
|
-
PI_CODING_AGENT_SESSION_DIR: input.sessionDir,
|
|
833
|
-
PI_SKIP_VERSION_CHECK: "1",
|
|
834
|
-
RIG_PI_OPERATOR_SESSION: "1",
|
|
835
|
-
RIG_RUN_ID: input.runId,
|
|
836
|
-
RIG_SERVER_URL: input.serverUrl,
|
|
837
|
-
...input.authToken ? { RIG_AUTH_TOKEN: input.authToken } : {},
|
|
838
|
-
...input.serverProjectRoot ? { RIG_PROJECT_ROOT: input.serverProjectRoot } : {}
|
|
839
|
-
};
|
|
840
|
-
}
|
|
841
|
-
async function attachRunBundledPiFrontend(context, input) {
|
|
842
|
-
const tempSessionDir = mkdtempSync(join2(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
843
|
-
const server = await ensureServerForCli(context.projectRoot);
|
|
844
|
-
let sessionFileArg = [];
|
|
845
|
-
try {
|
|
846
|
-
const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(input.runId)}/session-file`);
|
|
847
|
-
if (payload?.ok && typeof payload.content === "string" && payload.content.trim()) {
|
|
848
|
-
const fileName = typeof payload.fileName === "string" && payload.fileName.trim() ? payload.fileName.replace(/[^A-Za-z0-9._-]/g, "_") : `rig-run-${input.runId}.jsonl`;
|
|
849
|
-
const localSessionPath = join2(tempSessionDir, fileName);
|
|
850
|
-
const content = payload.content.split(`
|
|
851
|
-
`).map((line, index) => {
|
|
852
|
-
if (index > 0 || !line.trim())
|
|
853
|
-
return line;
|
|
854
|
-
try {
|
|
855
|
-
const header = JSON.parse(line);
|
|
856
|
-
if (header.type === "session" && typeof header.cwd === "string") {
|
|
857
|
-
return JSON.stringify({ ...header, cwd: process.cwd() });
|
|
858
|
-
}
|
|
859
|
-
} catch {}
|
|
860
|
-
return line;
|
|
861
|
-
}).join(`
|
|
862
|
-
`);
|
|
863
|
-
writeFileSync2(localSessionPath, content);
|
|
864
|
-
sessionFileArg = ["--session", localSessionPath];
|
|
865
|
-
}
|
|
866
|
-
} catch {}
|
|
867
|
-
const restoreEnv = setTemporaryEnv(buildOperatorPiEnv({
|
|
868
|
-
runId: input.runId,
|
|
869
|
-
serverUrl: server.baseUrl,
|
|
870
|
-
authToken: server.authToken,
|
|
871
|
-
serverProjectRoot: server.serverProjectRoot,
|
|
872
|
-
sessionDir: tempSessionDir
|
|
873
|
-
}));
|
|
874
|
-
const piRigExtensionFactory = (pi) => {
|
|
875
|
-
createPiRigExtension(pi);
|
|
876
|
-
};
|
|
877
|
-
let detached = false;
|
|
878
|
-
try {
|
|
879
|
-
await runPiMain([
|
|
880
|
-
"--no-extensions",
|
|
881
|
-
"--no-skills",
|
|
882
|
-
"--no-prompt-templates",
|
|
883
|
-
"--no-context-files",
|
|
884
|
-
...sessionFileArg
|
|
885
|
-
], {
|
|
886
|
-
extensionFactories: [piRigExtensionFactory]
|
|
887
|
-
});
|
|
888
|
-
detached = true;
|
|
889
|
-
} finally {
|
|
890
|
-
restoreEnv();
|
|
891
|
-
rmSync(tempSessionDir, { recursive: true, force: true });
|
|
892
|
-
}
|
|
893
|
-
let run = { runId: input.runId, status: "unknown" };
|
|
894
|
-
try {
|
|
895
|
-
run = await getRunDetailsViaServer(context, input.runId);
|
|
896
|
-
} catch {}
|
|
897
|
-
return {
|
|
898
|
-
run,
|
|
899
|
-
logs: [],
|
|
900
|
-
timeline: [],
|
|
901
|
-
timelineCursor: null,
|
|
902
|
-
steered: input.steered === true,
|
|
903
|
-
detached,
|
|
904
|
-
rendered: "stock Pi operator console with the pi-rig extension"
|
|
905
|
-
};
|
|
906
|
-
}
|
|
907
815
|
|
|
908
816
|
// packages/cli/src/commands/_async-ui.ts
|
|
909
817
|
import pc from "picocolors";
|
|
@@ -1026,6 +934,104 @@ async function withSpinner(label, work, options = {}) {
|
|
|
1026
934
|
}
|
|
1027
935
|
}
|
|
1028
936
|
|
|
937
|
+
// packages/cli/src/commands/_pi-frontend.ts
|
|
938
|
+
function setTemporaryEnv(updates) {
|
|
939
|
+
const previous = new Map;
|
|
940
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
941
|
+
previous.set(key, process.env[key]);
|
|
942
|
+
process.env[key] = value;
|
|
943
|
+
}
|
|
944
|
+
return () => {
|
|
945
|
+
for (const [key, value] of previous) {
|
|
946
|
+
if (value === undefined)
|
|
947
|
+
delete process.env[key];
|
|
948
|
+
else
|
|
949
|
+
process.env[key] = value;
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
function buildOperatorPiEnv(input) {
|
|
954
|
+
return {
|
|
955
|
+
PI_CODING_AGENT_SESSION_DIR: input.sessionDir,
|
|
956
|
+
PI_SKIP_VERSION_CHECK: "1",
|
|
957
|
+
RIG_PI_OPERATOR_SESSION: "1",
|
|
958
|
+
RIG_RUN_ID: input.runId,
|
|
959
|
+
RIG_SERVER_URL: input.serverUrl,
|
|
960
|
+
...input.authToken ? { RIG_AUTH_TOKEN: input.authToken } : {},
|
|
961
|
+
...input.serverProjectRoot ? { RIG_PROJECT_ROOT: input.serverProjectRoot } : {}
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
965
|
+
const server = await ensureServerForCli(context.projectRoot);
|
|
966
|
+
let sessionFileArg = [];
|
|
967
|
+
try {
|
|
968
|
+
const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}/session-file`);
|
|
969
|
+
if (payload?.ok && typeof payload.content === "string" && payload.content.trim()) {
|
|
970
|
+
const fileName = typeof payload.fileName === "string" && payload.fileName.trim() ? payload.fileName.replace(/[^A-Za-z0-9._-]/g, "_") : `rig-run-${runId}.jsonl`;
|
|
971
|
+
const localSessionPath = join2(tempSessionDir, fileName);
|
|
972
|
+
const content = payload.content.split(`
|
|
973
|
+
`).map((line, index) => {
|
|
974
|
+
if (index > 0 || !line.trim())
|
|
975
|
+
return line;
|
|
976
|
+
try {
|
|
977
|
+
const header = JSON.parse(line);
|
|
978
|
+
if (header.type === "session" && typeof header.cwd === "string") {
|
|
979
|
+
return JSON.stringify({ ...header, cwd: process.cwd() });
|
|
980
|
+
}
|
|
981
|
+
} catch {}
|
|
982
|
+
return line;
|
|
983
|
+
}).join(`
|
|
984
|
+
`);
|
|
985
|
+
writeFileSync2(localSessionPath, content);
|
|
986
|
+
sessionFileArg = ["--session", localSessionPath];
|
|
987
|
+
}
|
|
988
|
+
} catch {}
|
|
989
|
+
return { server, sessionFileArg };
|
|
990
|
+
}
|
|
991
|
+
async function attachRunBundledPiFrontend(context, input) {
|
|
992
|
+
const tempSessionDir = mkdtempSync(join2(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
993
|
+
const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
|
|
994
|
+
const restoreEnv = setTemporaryEnv(buildOperatorPiEnv({
|
|
995
|
+
runId: input.runId,
|
|
996
|
+
serverUrl: server.baseUrl,
|
|
997
|
+
authToken: server.authToken,
|
|
998
|
+
serverProjectRoot: server.serverProjectRoot,
|
|
999
|
+
sessionDir: tempSessionDir
|
|
1000
|
+
}));
|
|
1001
|
+
const piRigExtensionFactory = (pi) => {
|
|
1002
|
+
createPiRigExtension(pi);
|
|
1003
|
+
};
|
|
1004
|
+
let detached = false;
|
|
1005
|
+
try {
|
|
1006
|
+
await runPiMain([
|
|
1007
|
+
"--no-extensions",
|
|
1008
|
+
"--no-skills",
|
|
1009
|
+
"--no-prompt-templates",
|
|
1010
|
+
"--no-context-files",
|
|
1011
|
+
...sessionFileArg
|
|
1012
|
+
], {
|
|
1013
|
+
extensionFactories: [piRigExtensionFactory]
|
|
1014
|
+
});
|
|
1015
|
+
detached = true;
|
|
1016
|
+
} finally {
|
|
1017
|
+
restoreEnv();
|
|
1018
|
+
rmSync(tempSessionDir, { recursive: true, force: true });
|
|
1019
|
+
}
|
|
1020
|
+
let run = { runId: input.runId, status: "unknown" };
|
|
1021
|
+
try {
|
|
1022
|
+
run = await getRunDetailsViaServer(context, input.runId);
|
|
1023
|
+
} catch {}
|
|
1024
|
+
return {
|
|
1025
|
+
run,
|
|
1026
|
+
logs: [],
|
|
1027
|
+
timeline: [],
|
|
1028
|
+
timelineCursor: null,
|
|
1029
|
+
steered: input.steered === true,
|
|
1030
|
+
detached,
|
|
1031
|
+
rendered: "stock Pi operator console with the pi-rig extension"
|
|
1032
|
+
};
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1029
1035
|
// packages/cli/src/commands/_operator-view.ts
|
|
1030
1036
|
var TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
|
|
1031
1037
|
function runStatusFromPayload(payload) {
|
|
@@ -511,6 +511,18 @@ async function withSpinner(label, work, options = {}) {
|
|
|
511
511
|
import { intro, log as log2, note as note2, outro } from "@clack/prompts";
|
|
512
512
|
import pc3 from "picocolors";
|
|
513
513
|
var TOP_LEVEL_SECTIONS = [
|
|
514
|
+
{
|
|
515
|
+
title: "Pi console",
|
|
516
|
+
subtitle: "the operator surface \u2014 every attach opens the run's FULL Pi session",
|
|
517
|
+
commands: [
|
|
518
|
+
{ command: "rig run attach <run-id>", description: "Open the run's Pi console: complete transcript (live AND finished runs), worker turns streaming in live." },
|
|
519
|
+
{ command: "type a message", description: "Inside the console, plain text steers the worker mid-turn \u2014 it lands in the agent's context, not a local model." },
|
|
520
|
+
{ command: "!<command>", description: "Inside the console, runs shell in the WORKER's workspace; output streams back into the transcript." },
|
|
521
|
+
{ command: "/<command>", description: "The palette includes the WORKER session's slash commands ([worker]-tagged) next to /rig." },
|
|
522
|
+
{ command: "/rig abort | /rig stop", description: "Abort the worker's current turn, or stop the whole run, from inside the console." },
|
|
523
|
+
{ command: "rig run steer <id> --message <text>", description: "Steer without attaching \u2014 queue a message; the worker picks it up within seconds." }
|
|
524
|
+
]
|
|
525
|
+
},
|
|
514
526
|
{
|
|
515
527
|
title: "Start here",
|
|
516
528
|
subtitle: "one-time setup, pick a server",
|
|
@@ -525,9 +537,9 @@ var TOP_LEVEL_SECTIONS = [
|
|
|
525
537
|
subtitle: "find a task, put an agent on it, answer what it asks",
|
|
526
538
|
commands: [
|
|
527
539
|
{ command: "rig task list", description: "What's on the board (from the selected source/server)." },
|
|
528
|
-
{ command: "rig task run --next", description: "Dispatch an agent; interactive mode
|
|
540
|
+
{ command: "rig task run --next", description: "Dispatch an agent on the next ready task; interactive mode drops you into its Pi console." },
|
|
529
541
|
{ command: "rig run status", description: "Active and recent runs at a glance." },
|
|
530
|
-
{ command: "rig run attach <id> --follow", description: "
|
|
542
|
+
{ command: "rig run attach <id> --follow", description: "Same as plain attach \u2014 the Pi console is always the interactive surface." },
|
|
531
543
|
{ command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." }
|
|
532
544
|
]
|
|
533
545
|
},
|
|
@@ -606,29 +618,35 @@ var PRIMARY_GROUPS = [
|
|
|
606
618
|
},
|
|
607
619
|
{
|
|
608
620
|
name: "run",
|
|
609
|
-
summary: "Observe, attach to, and control Rig runs.",
|
|
610
|
-
usage: ["rig run <list|status|show|attach|stop> [options]"],
|
|
621
|
+
summary: "Observe, attach to, and control Rig runs. `attach` opens the Pi console \u2014 the full worker session, live.",
|
|
622
|
+
usage: ["rig run <list|status|show|attach|steer|stop|resume|restart> [options]"],
|
|
611
623
|
commands: [
|
|
612
624
|
{ command: "list", description: "List recent runs from the selected server or local state.", primary: true },
|
|
613
625
|
{ command: "status", description: "Render active and recent run groups.", primary: true },
|
|
614
626
|
{ command: "show <id>|--run <id> [--raw]", description: "Show a human run summary; --raw prints the full payload.", primary: true },
|
|
615
|
-
{ command: "attach <run-id>|--run <id>
|
|
627
|
+
{ command: "attach <run-id>|--run <id>", description: "Open the run's Pi console \u2014 see 'Inside the console' below. Works on live AND finished runs.", primary: true },
|
|
628
|
+
{ command: "steer <run-id> --message <text>", description: "Queue a steering message into a live worker without attaching \u2014 delivered into the agent's context within seconds.", primary: true },
|
|
616
629
|
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
617
|
-
{ command: "
|
|
618
|
-
{ command: "
|
|
630
|
+
{ command: "resume [<run-id>]", description: "Resume an interrupted run on the selected server (defaults to the most recent resumable)." },
|
|
631
|
+
{ command: "restart [<run-id>]", description: "Re-dispatch a run from a clean runtime, reopening its Pi session where possible." },
|
|
632
|
+
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events (scripts; humans should attach)." },
|
|
619
633
|
{ command: "replay <run-id>|--run <id> [--with-session]", description: "Print the run's consolidated run.jsonl as a merged timeline; --with-session interleaves the Pi session log." },
|
|
620
|
-
{ command: "resume", description: "Resume the most recent interrupted local run." },
|
|
621
|
-
{ command: "restart", description: "Restart the most recent local run from a clean runtime." },
|
|
622
634
|
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
623
635
|
],
|
|
624
636
|
examples: [
|
|
637
|
+
"rig run attach <run-id> # full session console \u2014 live mirror, steering, worker shell",
|
|
638
|
+
"rig run steer <run-id> --message 'focus on the failing test first'",
|
|
625
639
|
"rig run list",
|
|
626
|
-
"rig run status",
|
|
627
640
|
"rig run show <run-id>",
|
|
628
|
-
"rig run attach <run-id> --follow",
|
|
629
641
|
"rig run stop <run-id>"
|
|
630
642
|
],
|
|
631
|
-
next: [
|
|
643
|
+
next: [
|
|
644
|
+
"Inside the console: the run's COMPLETE transcript loads on open (finished runs too), and new worker turns stream in live.",
|
|
645
|
+
"Inside the console: plain text = steering into the worker's context \xB7 !<cmd> = shell in the WORKER workspace \xB7 /<cmd> includes the worker session's commands \xB7 /rig abort stops the current turn.",
|
|
646
|
+
"The console is read-write but remote-only: nothing runs on your machine; the worker keeps running when you exit.",
|
|
647
|
+
"Use `rig task run --next` to create a new run; interactive mode drops you straight into its console.",
|
|
648
|
+
"Use `--json` when scripts need the full structured record."
|
|
649
|
+
]
|
|
632
650
|
},
|
|
633
651
|
{
|
|
634
652
|
name: "inbox",
|
|
@@ -845,7 +863,7 @@ function renderGroup(group) {
|
|
|
845
863
|
function renderTopLevelHelp() {
|
|
846
864
|
return [
|
|
847
865
|
`${heading("rig")} ${pc3.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
848
|
-
pc3.dim("
|
|
866
|
+
pc3.dim("The loop: pick a task, dispatch an agent, open its Pi console (`rig run attach <id>`) to watch and steer it live, clear inbox gates, merge."),
|
|
849
867
|
"",
|
|
850
868
|
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
851
869
|
`${pc3.bold(pc3.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc3.dim(section.subtitle)}`,
|
|
@@ -897,7 +915,7 @@ function printTopLevelHelp(state = {}) {
|
|
|
897
915
|
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
898
916
|
].join(`
|
|
899
917
|
`), "Global options");
|
|
900
|
-
outro("init \u2192 task run \u2192 watch \u2192 inbox \u2192 merged.");
|
|
918
|
+
outro("init \u2192 task run \u2192 attach (Pi console: watch + steer live) \u2192 inbox \u2192 merged.");
|
|
901
919
|
}
|
|
902
920
|
function printGroupHelpDocument(groupName) {
|
|
903
921
|
const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
|
|
@@ -1201,14 +1201,13 @@ function buildOperatorPiEnv(input) {
|
|
|
1201
1201
|
...input.serverProjectRoot ? { RIG_PROJECT_ROOT: input.serverProjectRoot } : {}
|
|
1202
1202
|
};
|
|
1203
1203
|
}
|
|
1204
|
-
async function
|
|
1205
|
-
const tempSessionDir = mkdtempSync(join(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
1204
|
+
async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
1206
1205
|
const server = await ensureServerForCli(context.projectRoot);
|
|
1207
1206
|
let sessionFileArg = [];
|
|
1208
1207
|
try {
|
|
1209
|
-
const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(
|
|
1208
|
+
const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}/session-file`);
|
|
1210
1209
|
if (payload?.ok && typeof payload.content === "string" && payload.content.trim()) {
|
|
1211
|
-
const fileName = typeof payload.fileName === "string" && payload.fileName.trim() ? payload.fileName.replace(/[^A-Za-z0-9._-]/g, "_") : `rig-run-${
|
|
1210
|
+
const fileName = typeof payload.fileName === "string" && payload.fileName.trim() ? payload.fileName.replace(/[^A-Za-z0-9._-]/g, "_") : `rig-run-${runId}.jsonl`;
|
|
1212
1211
|
const localSessionPath = join(tempSessionDir, fileName);
|
|
1213
1212
|
const content = payload.content.split(`
|
|
1214
1213
|
`).map((line, index) => {
|
|
@@ -1227,6 +1226,11 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
1227
1226
|
sessionFileArg = ["--session", localSessionPath];
|
|
1228
1227
|
}
|
|
1229
1228
|
} catch {}
|
|
1229
|
+
return { server, sessionFileArg };
|
|
1230
|
+
}
|
|
1231
|
+
async function attachRunBundledPiFrontend(context, input) {
|
|
1232
|
+
const tempSessionDir = mkdtempSync(join(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
1233
|
+
const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
|
|
1230
1234
|
const restoreEnv = setTemporaryEnv(buildOperatorPiEnv({
|
|
1231
1235
|
runId: input.runId,
|
|
1232
1236
|
serverUrl: server.baseUrl,
|
|
@@ -1571,6 +1575,18 @@ async function printPendingInboxFooter(context) {
|
|
|
1571
1575
|
import { intro, log as log2, note as note2, outro } from "@clack/prompts";
|
|
1572
1576
|
import pc3 from "picocolors";
|
|
1573
1577
|
var TOP_LEVEL_SECTIONS = [
|
|
1578
|
+
{
|
|
1579
|
+
title: "Pi console",
|
|
1580
|
+
subtitle: "the operator surface \u2014 every attach opens the run's FULL Pi session",
|
|
1581
|
+
commands: [
|
|
1582
|
+
{ command: "rig run attach <run-id>", description: "Open the run's Pi console: complete transcript (live AND finished runs), worker turns streaming in live." },
|
|
1583
|
+
{ command: "type a message", description: "Inside the console, plain text steers the worker mid-turn \u2014 it lands in the agent's context, not a local model." },
|
|
1584
|
+
{ command: "!<command>", description: "Inside the console, runs shell in the WORKER's workspace; output streams back into the transcript." },
|
|
1585
|
+
{ command: "/<command>", description: "The palette includes the WORKER session's slash commands ([worker]-tagged) next to /rig." },
|
|
1586
|
+
{ command: "/rig abort | /rig stop", description: "Abort the worker's current turn, or stop the whole run, from inside the console." },
|
|
1587
|
+
{ command: "rig run steer <id> --message <text>", description: "Steer without attaching \u2014 queue a message; the worker picks it up within seconds." }
|
|
1588
|
+
]
|
|
1589
|
+
},
|
|
1574
1590
|
{
|
|
1575
1591
|
title: "Start here",
|
|
1576
1592
|
subtitle: "one-time setup, pick a server",
|
|
@@ -1585,9 +1601,9 @@ var TOP_LEVEL_SECTIONS = [
|
|
|
1585
1601
|
subtitle: "find a task, put an agent on it, answer what it asks",
|
|
1586
1602
|
commands: [
|
|
1587
1603
|
{ command: "rig task list", description: "What's on the board (from the selected source/server)." },
|
|
1588
|
-
{ command: "rig task run --next", description: "Dispatch an agent; interactive mode
|
|
1604
|
+
{ command: "rig task run --next", description: "Dispatch an agent on the next ready task; interactive mode drops you into its Pi console." },
|
|
1589
1605
|
{ command: "rig run status", description: "Active and recent runs at a glance." },
|
|
1590
|
-
{ command: "rig run attach <id> --follow", description: "
|
|
1606
|
+
{ command: "rig run attach <id> --follow", description: "Same as plain attach \u2014 the Pi console is always the interactive surface." },
|
|
1591
1607
|
{ command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." }
|
|
1592
1608
|
]
|
|
1593
1609
|
},
|
|
@@ -1666,29 +1682,35 @@ var PRIMARY_GROUPS = [
|
|
|
1666
1682
|
},
|
|
1667
1683
|
{
|
|
1668
1684
|
name: "run",
|
|
1669
|
-
summary: "Observe, attach to, and control Rig runs.",
|
|
1670
|
-
usage: ["rig run <list|status|show|attach|stop> [options]"],
|
|
1685
|
+
summary: "Observe, attach to, and control Rig runs. `attach` opens the Pi console \u2014 the full worker session, live.",
|
|
1686
|
+
usage: ["rig run <list|status|show|attach|steer|stop|resume|restart> [options]"],
|
|
1671
1687
|
commands: [
|
|
1672
1688
|
{ command: "list", description: "List recent runs from the selected server or local state.", primary: true },
|
|
1673
1689
|
{ command: "status", description: "Render active and recent run groups.", primary: true },
|
|
1674
1690
|
{ command: "show <id>|--run <id> [--raw]", description: "Show a human run summary; --raw prints the full payload.", primary: true },
|
|
1675
|
-
{ command: "attach <run-id>|--run <id>
|
|
1691
|
+
{ command: "attach <run-id>|--run <id>", description: "Open the run's Pi console \u2014 see 'Inside the console' below. Works on live AND finished runs.", primary: true },
|
|
1692
|
+
{ command: "steer <run-id> --message <text>", description: "Queue a steering message into a live worker without attaching \u2014 delivered into the agent's context within seconds.", primary: true },
|
|
1676
1693
|
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
1677
|
-
{ command: "
|
|
1678
|
-
{ command: "
|
|
1694
|
+
{ command: "resume [<run-id>]", description: "Resume an interrupted run on the selected server (defaults to the most recent resumable)." },
|
|
1695
|
+
{ command: "restart [<run-id>]", description: "Re-dispatch a run from a clean runtime, reopening its Pi session where possible." },
|
|
1696
|
+
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events (scripts; humans should attach)." },
|
|
1679
1697
|
{ command: "replay <run-id>|--run <id> [--with-session]", description: "Print the run's consolidated run.jsonl as a merged timeline; --with-session interleaves the Pi session log." },
|
|
1680
|
-
{ command: "resume", description: "Resume the most recent interrupted local run." },
|
|
1681
|
-
{ command: "restart", description: "Restart the most recent local run from a clean runtime." },
|
|
1682
1698
|
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
1683
1699
|
],
|
|
1684
1700
|
examples: [
|
|
1701
|
+
"rig run attach <run-id> # full session console \u2014 live mirror, steering, worker shell",
|
|
1702
|
+
"rig run steer <run-id> --message 'focus on the failing test first'",
|
|
1685
1703
|
"rig run list",
|
|
1686
|
-
"rig run status",
|
|
1687
1704
|
"rig run show <run-id>",
|
|
1688
|
-
"rig run attach <run-id> --follow",
|
|
1689
1705
|
"rig run stop <run-id>"
|
|
1690
1706
|
],
|
|
1691
|
-
next: [
|
|
1707
|
+
next: [
|
|
1708
|
+
"Inside the console: the run's COMPLETE transcript loads on open (finished runs too), and new worker turns stream in live.",
|
|
1709
|
+
"Inside the console: plain text = steering into the worker's context \xB7 !<cmd> = shell in the WORKER workspace \xB7 /<cmd> includes the worker session's commands \xB7 /rig abort stops the current turn.",
|
|
1710
|
+
"The console is read-write but remote-only: nothing runs on your machine; the worker keeps running when you exit.",
|
|
1711
|
+
"Use `rig task run --next` to create a new run; interactive mode drops you straight into its console.",
|
|
1712
|
+
"Use `--json` when scripts need the full structured record."
|
|
1713
|
+
]
|
|
1692
1714
|
},
|
|
1693
1715
|
{
|
|
1694
1716
|
name: "inbox",
|
|
@@ -1905,7 +1927,7 @@ function renderGroup(group) {
|
|
|
1905
1927
|
function renderTopLevelHelp() {
|
|
1906
1928
|
return [
|
|
1907
1929
|
`${heading("rig")} ${pc3.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
1908
|
-
pc3.dim("
|
|
1930
|
+
pc3.dim("The loop: pick a task, dispatch an agent, open its Pi console (`rig run attach <id>`) to watch and steer it live, clear inbox gates, merge."),
|
|
1909
1931
|
"",
|
|
1910
1932
|
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
1911
1933
|
`${pc3.bold(pc3.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc3.dim(section.subtitle)}`,
|
|
@@ -1957,7 +1979,7 @@ function printTopLevelHelp(state = {}) {
|
|
|
1957
1979
|
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
1958
1980
|
].join(`
|
|
1959
1981
|
`), "Global options");
|
|
1960
|
-
outro("init \u2192 task run \u2192 watch \u2192 inbox \u2192 merged.");
|
|
1982
|
+
outro("init \u2192 task run \u2192 attach (Pi console: watch + steer live) \u2192 inbox \u2192 merged.");
|
|
1961
1983
|
}
|
|
1962
1984
|
function printGroupHelpDocument(groupName) {
|
|
1963
1985
|
const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
|
package/dist/src/commands.js
CHANGED
|
@@ -7698,14 +7698,13 @@ function buildOperatorPiEnv(input) {
|
|
|
7698
7698
|
...input.serverProjectRoot ? { RIG_PROJECT_ROOT: input.serverProjectRoot } : {}
|
|
7699
7699
|
};
|
|
7700
7700
|
}
|
|
7701
|
-
async function
|
|
7702
|
-
const tempSessionDir = mkdtempSync(join3(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
7701
|
+
async function prepareOperatorConsole(context, runId, tempSessionDir) {
|
|
7703
7702
|
const server = await ensureServerForCli(context.projectRoot);
|
|
7704
7703
|
let sessionFileArg = [];
|
|
7705
7704
|
try {
|
|
7706
|
-
const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(
|
|
7705
|
+
const payload = await requestServerJson(context, `/api/runs/${encodeURIComponent(runId)}/session-file`);
|
|
7707
7706
|
if (payload?.ok && typeof payload.content === "string" && payload.content.trim()) {
|
|
7708
|
-
const fileName = typeof payload.fileName === "string" && payload.fileName.trim() ? payload.fileName.replace(/[^A-Za-z0-9._-]/g, "_") : `rig-run-${
|
|
7707
|
+
const fileName = typeof payload.fileName === "string" && payload.fileName.trim() ? payload.fileName.replace(/[^A-Za-z0-9._-]/g, "_") : `rig-run-${runId}.jsonl`;
|
|
7709
7708
|
const localSessionPath = join3(tempSessionDir, fileName);
|
|
7710
7709
|
const content = payload.content.split(`
|
|
7711
7710
|
`).map((line, index) => {
|
|
@@ -7724,6 +7723,11 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
7724
7723
|
sessionFileArg = ["--session", localSessionPath];
|
|
7725
7724
|
}
|
|
7726
7725
|
} catch {}
|
|
7726
|
+
return { server, sessionFileArg };
|
|
7727
|
+
}
|
|
7728
|
+
async function attachRunBundledPiFrontend(context, input) {
|
|
7729
|
+
const tempSessionDir = mkdtempSync(join3(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
7730
|
+
const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
|
|
7727
7731
|
const restoreEnv = setTemporaryEnv(buildOperatorPiEnv({
|
|
7728
7732
|
runId: input.runId,
|
|
7729
7733
|
serverUrl: server.baseUrl,
|
|
@@ -8554,6 +8558,18 @@ import { computeRigStats } from "@rig/runtime/control-plane/native/run-stats";
|
|
|
8554
8558
|
import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@clack/prompts";
|
|
8555
8559
|
import pc5 from "picocolors";
|
|
8556
8560
|
var TOP_LEVEL_SECTIONS = [
|
|
8561
|
+
{
|
|
8562
|
+
title: "Pi console",
|
|
8563
|
+
subtitle: "the operator surface \u2014 every attach opens the run's FULL Pi session",
|
|
8564
|
+
commands: [
|
|
8565
|
+
{ command: "rig run attach <run-id>", description: "Open the run's Pi console: complete transcript (live AND finished runs), worker turns streaming in live." },
|
|
8566
|
+
{ command: "type a message", description: "Inside the console, plain text steers the worker mid-turn \u2014 it lands in the agent's context, not a local model." },
|
|
8567
|
+
{ command: "!<command>", description: "Inside the console, runs shell in the WORKER's workspace; output streams back into the transcript." },
|
|
8568
|
+
{ command: "/<command>", description: "The palette includes the WORKER session's slash commands ([worker]-tagged) next to /rig." },
|
|
8569
|
+
{ command: "/rig abort | /rig stop", description: "Abort the worker's current turn, or stop the whole run, from inside the console." },
|
|
8570
|
+
{ command: "rig run steer <id> --message <text>", description: "Steer without attaching \u2014 queue a message; the worker picks it up within seconds." }
|
|
8571
|
+
]
|
|
8572
|
+
},
|
|
8557
8573
|
{
|
|
8558
8574
|
title: "Start here",
|
|
8559
8575
|
subtitle: "one-time setup, pick a server",
|
|
@@ -8568,9 +8584,9 @@ var TOP_LEVEL_SECTIONS = [
|
|
|
8568
8584
|
subtitle: "find a task, put an agent on it, answer what it asks",
|
|
8569
8585
|
commands: [
|
|
8570
8586
|
{ command: "rig task list", description: "What's on the board (from the selected source/server)." },
|
|
8571
|
-
{ command: "rig task run --next", description: "Dispatch an agent; interactive mode
|
|
8587
|
+
{ command: "rig task run --next", description: "Dispatch an agent on the next ready task; interactive mode drops you into its Pi console." },
|
|
8572
8588
|
{ command: "rig run status", description: "Active and recent runs at a glance." },
|
|
8573
|
-
{ command: "rig run attach <id> --follow", description: "
|
|
8589
|
+
{ command: "rig run attach <id> --follow", description: "Same as plain attach \u2014 the Pi console is always the interactive surface." },
|
|
8574
8590
|
{ command: "rig inbox approvals", description: "Approvals workers are waiting on (then `rig inbox approve \u2026`)." }
|
|
8575
8591
|
]
|
|
8576
8592
|
},
|
|
@@ -8649,29 +8665,35 @@ var PRIMARY_GROUPS = [
|
|
|
8649
8665
|
},
|
|
8650
8666
|
{
|
|
8651
8667
|
name: "run",
|
|
8652
|
-
summary: "Observe, attach to, and control Rig runs.",
|
|
8653
|
-
usage: ["rig run <list|status|show|attach|stop> [options]"],
|
|
8668
|
+
summary: "Observe, attach to, and control Rig runs. `attach` opens the Pi console \u2014 the full worker session, live.",
|
|
8669
|
+
usage: ["rig run <list|status|show|attach|steer|stop|resume|restart> [options]"],
|
|
8654
8670
|
commands: [
|
|
8655
8671
|
{ command: "list", description: "List recent runs from the selected server or local state.", primary: true },
|
|
8656
8672
|
{ command: "status", description: "Render active and recent run groups.", primary: true },
|
|
8657
8673
|
{ command: "show <id>|--run <id> [--raw]", description: "Show a human run summary; --raw prints the full payload.", primary: true },
|
|
8658
|
-
{ command: "attach <run-id>|--run <id>
|
|
8674
|
+
{ command: "attach <run-id>|--run <id>", description: "Open the run's Pi console \u2014 see 'Inside the console' below. Works on live AND finished runs.", primary: true },
|
|
8675
|
+
{ command: "steer <run-id> --message <text>", description: "Queue a steering message into a live worker without attaching \u2014 delivered into the agent's context within seconds.", primary: true },
|
|
8659
8676
|
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
8660
|
-
{ command: "
|
|
8661
|
-
{ command: "
|
|
8677
|
+
{ command: "resume [<run-id>]", description: "Resume an interrupted run on the selected server (defaults to the most recent resumable)." },
|
|
8678
|
+
{ command: "restart [<run-id>]", description: "Re-dispatch a run from a clean runtime, reopening its Pi session where possible." },
|
|
8679
|
+
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events (scripts; humans should attach)." },
|
|
8662
8680
|
{ command: "replay <run-id>|--run <id> [--with-session]", description: "Print the run's consolidated run.jsonl as a merged timeline; --with-session interleaves the Pi session log." },
|
|
8663
|
-
{ command: "resume", description: "Resume the most recent interrupted local run." },
|
|
8664
|
-
{ command: "restart", description: "Restart the most recent local run from a clean runtime." },
|
|
8665
8681
|
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
8666
8682
|
],
|
|
8667
8683
|
examples: [
|
|
8684
|
+
"rig run attach <run-id> # full session console \u2014 live mirror, steering, worker shell",
|
|
8685
|
+
"rig run steer <run-id> --message 'focus on the failing test first'",
|
|
8668
8686
|
"rig run list",
|
|
8669
|
-
"rig run status",
|
|
8670
8687
|
"rig run show <run-id>",
|
|
8671
|
-
"rig run attach <run-id> --follow",
|
|
8672
8688
|
"rig run stop <run-id>"
|
|
8673
8689
|
],
|
|
8674
|
-
next: [
|
|
8690
|
+
next: [
|
|
8691
|
+
"Inside the console: the run's COMPLETE transcript loads on open (finished runs too), and new worker turns stream in live.",
|
|
8692
|
+
"Inside the console: plain text = steering into the worker's context \xB7 !<cmd> = shell in the WORKER workspace \xB7 /<cmd> includes the worker session's commands \xB7 /rig abort stops the current turn.",
|
|
8693
|
+
"The console is read-write but remote-only: nothing runs on your machine; the worker keeps running when you exit.",
|
|
8694
|
+
"Use `rig task run --next` to create a new run; interactive mode drops you straight into its console.",
|
|
8695
|
+
"Use `--json` when scripts need the full structured record."
|
|
8696
|
+
]
|
|
8675
8697
|
},
|
|
8676
8698
|
{
|
|
8677
8699
|
name: "inbox",
|
|
@@ -8894,7 +8916,7 @@ function renderGroup(group) {
|
|
|
8894
8916
|
function renderTopLevelHelp() {
|
|
8895
8917
|
return [
|
|
8896
8918
|
`${heading("rig")} ${pc5.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
8897
|
-
pc5.dim("
|
|
8919
|
+
pc5.dim("The loop: pick a task, dispatch an agent, open its Pi console (`rig run attach <id>`) to watch and steer it live, clear inbox gates, merge."),
|
|
8898
8920
|
"",
|
|
8899
8921
|
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
8900
8922
|
`${pc5.bold(pc5.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc5.dim(section.subtitle)}`,
|
|
@@ -8978,7 +9000,7 @@ function printTopLevelHelp(state = {}) {
|
|
|
8978
9000
|
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
8979
9001
|
].join(`
|
|
8980
9002
|
`), "Global options");
|
|
8981
|
-
outro3("init \u2192 task run \u2192 watch \u2192 inbox \u2192 merged.");
|
|
9003
|
+
outro3("init \u2192 task run \u2192 attach (Pi console: watch + steer live) \u2192 inbox \u2192 merged.");
|
|
8982
9004
|
}
|
|
8983
9005
|
function printAdvancedHelp() {
|
|
8984
9006
|
if (!shouldUseClackOutput2()) {
|