@h-rig/cli 0.0.6-alpha.87 → 0.0.6-alpha.89
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 +1380 -865
- package/dist/src/app/board.js +462 -48
- package/dist/src/app-opentui/adapters/common.d.ts +3 -0
- package/dist/src/app-opentui/adapters/common.js +4 -0
- package/dist/src/app-opentui/adapters/doctor.js +458 -46
- package/dist/src/app-opentui/adapters/family.js +701 -151
- package/dist/src/app-opentui/adapters/fleet.js +477 -46
- package/dist/src/app-opentui/adapters/inbox.js +477 -46
- package/dist/src/app-opentui/adapters/init.js +497 -74
- package/dist/src/app-opentui/adapters/inspect.js +477 -46
- package/dist/src/app-opentui/adapters/pi-attach.d.ts +7 -0
- package/dist/src/app-opentui/adapters/pi-attach.js +1004 -519
- package/dist/src/app-opentui/adapters/run-detail.js +477 -46
- package/dist/src/app-opentui/adapters/server.d.ts +26 -0
- package/dist/src/app-opentui/adapters/server.js +676 -59
- package/dist/src/app-opentui/adapters/tasks.js +621 -549
- package/dist/src/app-opentui/autocomplete.js +4 -2
- package/dist/src/app-opentui/bootstrap.js +1376 -861
- package/dist/src/app-opentui/command-palette.js +37 -10
- package/dist/src/app-opentui/index.js +632 -528
- package/dist/src/app-opentui/intent.js +33 -8
- package/dist/src/app-opentui/keymap.js +43 -414
- package/dist/src/app-opentui/pi-host-child.js +496 -57
- package/dist/src/app-opentui/pi-pty-host.d.ts +14 -64
- package/dist/src/app-opentui/pi-pty-host.js +3 -397
- package/dist/src/app-opentui/react/App.js +144 -469
- package/dist/src/app-opentui/react/ChromeHost.js +44 -415
- package/dist/src/app-opentui/react/launch.js +659 -552
- package/dist/src/app-opentui/react/nav.js +1 -1
- package/dist/src/app-opentui/registry.js +1181 -742
- package/dist/src/app-opentui/remote-link.d.ts +10 -0
- package/dist/src/app-opentui/remote-link.js +47 -0
- package/dist/src/app-opentui/render/terminal-handoff.d.ts +16 -0
- package/dist/src/app-opentui/render/terminal-handoff.js +14 -0
- package/dist/src/app-opentui/runtime.js +632 -528
- package/dist/src/app-opentui/scenes/doctor.js +1 -1
- package/dist/src/app-opentui/scenes/error.js +50 -4
- package/dist/src/app-opentui/scenes/family.js +60 -6
- package/dist/src/app-opentui/scenes/fleet.js +65 -13
- package/dist/src/app-opentui/scenes/help.js +4 -2
- package/dist/src/app-opentui/scenes/init.js +12 -12
- package/dist/src/app-opentui/scenes/main.js +7 -7
- package/dist/src/app-opentui/scenes/server.js +83 -11
- package/dist/src/app-opentui/scenes/tasks.js +79 -16
- package/dist/src/app-opentui/state.js +25 -5
- package/dist/src/app-opentui/surface-catalog.js +4 -2
- package/dist/src/app-opentui/types.d.ts +1 -1
- package/dist/src/commands/_cli-format.d.ts +10 -1
- package/dist/src/commands/_cli-format.js +5 -2
- package/dist/src/commands/_connection-state.d.ts +11 -1
- package/dist/src/commands/_connection-state.js +50 -5
- package/dist/src/commands/_doctor-checks.js +458 -46
- package/dist/src/commands/_help-catalog.js +4 -2
- package/dist/src/commands/_json-output.js +4 -0
- package/dist/src/commands/_operator-view.js +496 -57
- package/dist/src/commands/_pi-frontend.d.ts +25 -0
- package/dist/src/commands/_pi-frontend.js +497 -57
- package/dist/src/commands/_preflight.js +509 -72
- package/dist/src/commands/_server-client.d.ts +33 -0
- package/dist/src/commands/_server-client.js +477 -46
- package/dist/src/commands/_server-events.js +446 -41
- package/dist/src/commands/_snapshot-upload.js +460 -48
- package/dist/src/commands/connect.js +620 -15
- package/dist/src/commands/doctor.js +458 -46
- package/dist/src/commands/github.js +462 -50
- package/dist/src/commands/inbox.js +458 -46
- package/dist/src/commands/init.js +497 -74
- package/dist/src/commands/inspect.js +458 -46
- package/dist/src/commands/run.js +496 -57
- package/dist/src/commands/server.js +647 -163
- package/dist/src/commands/setup.js +463 -51
- package/dist/src/commands/stats.js +462 -48
- package/dist/src/commands/task-run-driver.js +464 -52
- package/dist/src/commands/task.js +551 -85
- package/dist/src/commands.js +701 -151
- package/dist/src/index.js +705 -151
- package/dist/src/launcher.js +4 -0
- package/package.json +8 -8
|
@@ -187,16 +187,31 @@ function taskViewIntent(argv, command = "", rest = [], raw) {
|
|
|
187
187
|
const { payload, label } = taskViewPayload(command, rest);
|
|
188
188
|
return intent("tasks", argv, "refresh", payload, label, raw);
|
|
189
189
|
}
|
|
190
|
-
function routeServer(argv, command, raw, checkingLabel) {
|
|
191
|
-
if (!command || command === "status") {
|
|
190
|
+
function routeServer(argv, command, rest, raw, checkingLabel) {
|
|
191
|
+
if (!command || command === "status" || command === "list") {
|
|
192
192
|
return intent("server", argv, "refresh", undefined, command ? checkingLabel : "Loading server", raw);
|
|
193
193
|
}
|
|
194
|
+
if (command === "use") {
|
|
195
|
+
const alias = firstNonOption(rest);
|
|
196
|
+
if (alias === "local")
|
|
197
|
+
return intent("server", argv, "server-use-local", undefined, "Use local server", raw);
|
|
198
|
+
if (alias)
|
|
199
|
+
return intent("server", argv, "server-use-remote", { alias }, `Use ${alias}`, raw);
|
|
200
|
+
return intent("server", argv, "refresh", undefined, "Select a remote alias in Server", raw);
|
|
201
|
+
}
|
|
202
|
+
if (command === "add")
|
|
203
|
+
return intent("server", argv, "server-add-remote", { argv: [...argv] }, "Add remote server", raw);
|
|
204
|
+
if (command === "repair-link")
|
|
205
|
+
return intent("server", argv, "remote-link-repair", undefined, "Repair remote link", raw);
|
|
194
206
|
return commandRunIntent(argv, raw);
|
|
195
207
|
}
|
|
196
208
|
function routeGithub(argv, command, rest, raw) {
|
|
197
209
|
if (command === "auth" && (rest[0]?.toLowerCase() ?? "status") === "status" && rest.length <= 1) {
|
|
198
210
|
return intent("server", argv, "refresh", undefined, "Checking GitHub auth", raw);
|
|
199
211
|
}
|
|
212
|
+
if (command === "auth" && rest[0]?.toLowerCase() === "import-gh" && rest.length <= 1) {
|
|
213
|
+
return intent("server", argv, "github-auth-import", undefined, "Import GitHub auth", raw);
|
|
214
|
+
}
|
|
200
215
|
return commandRunIntent(argv, raw);
|
|
201
216
|
}
|
|
202
217
|
function routeDoctor(argv, command, raw) {
|
|
@@ -245,11 +260,16 @@ function intentFromArgv(argv) {
|
|
|
245
260
|
return commandRunIntent(argv);
|
|
246
261
|
}
|
|
247
262
|
if (normalizedGroup === "server")
|
|
248
|
-
return routeServer(argv, normalizedCommand, undefined, "Checking server");
|
|
263
|
+
return routeServer(argv, normalizedCommand, rest, undefined, "Checking server");
|
|
249
264
|
if (normalizedGroup === "github")
|
|
250
265
|
return routeGithub(argv, normalizedCommand, rest);
|
|
251
|
-
if (normalizedGroup === "init")
|
|
252
|
-
|
|
266
|
+
if (normalizedGroup === "init") {
|
|
267
|
+
if (!normalizedCommand)
|
|
268
|
+
return intent("init", argv, "refresh", undefined, "Open init");
|
|
269
|
+
if (rest.includes("--yes") || normalizedCommand === "--yes")
|
|
270
|
+
return intent("init", argv, "init-start", undefined, "Run init");
|
|
271
|
+
return intent("init", argv, "refresh", undefined, "Open init");
|
|
272
|
+
}
|
|
253
273
|
if (normalizedGroup === "doctor")
|
|
254
274
|
return routeDoctor(argv, normalizedCommand);
|
|
255
275
|
if (normalizedGroup === "inbox")
|
|
@@ -312,12 +332,17 @@ function intentFromTypeBar(value) {
|
|
|
312
332
|
return commandRunIntent(parts, value);
|
|
313
333
|
return intent("tasks", parts, "refresh", undefined, "Select a task, then press Enter; or use run next", value);
|
|
314
334
|
}
|
|
315
|
-
if (first === "init")
|
|
316
|
-
|
|
335
|
+
if (first === "init") {
|
|
336
|
+
if (!second)
|
|
337
|
+
return intent("init", parts, "refresh", undefined, "Open init", value);
|
|
338
|
+
if (parts.includes("--yes"))
|
|
339
|
+
return intent("init", parts, "init-start", undefined, "Run init", value);
|
|
340
|
+
return intent("init", parts, "refresh", undefined, "Open init", value);
|
|
341
|
+
}
|
|
317
342
|
if (first === "doctor")
|
|
318
343
|
return routeDoctor(parts, second, value);
|
|
319
344
|
if (first === "server")
|
|
320
|
-
return routeServer(parts, second, value, "Loading server");
|
|
345
|
+
return routeServer(parts, second, rest, value, "Loading server");
|
|
321
346
|
if (first === "github")
|
|
322
347
|
return routeGithub(parts, second, rest, value);
|
|
323
348
|
if (first === "inbox")
|
|
@@ -67,12 +67,13 @@ var PRIMARY_GROUPS = [
|
|
|
67
67
|
{
|
|
68
68
|
name: "server",
|
|
69
69
|
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
70
|
-
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
70
|
+
usage: ["rig server <status|list|add|use|repair-link|start> [options]"],
|
|
71
71
|
commands: [
|
|
72
|
-
{ command: "status", description: "Show the selected server for this repo.", primary: true },
|
|
72
|
+
{ command: "status", description: "Show the selected server and remote project-root link for this repo.", primary: true },
|
|
73
73
|
{ command: "use local", description: "Switch this repo to the local Rig server.", primary: true },
|
|
74
74
|
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
75
75
|
{ command: "use <alias>", description: "Select a saved remote server alias.", primary: true },
|
|
76
|
+
{ command: "repair-link [--prepare|--backfill-only] [--repo owner/repo]", description: "Backfill or prepare the selected remote's server-host checkout link.", primary: true },
|
|
76
77
|
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
77
78
|
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process." }
|
|
78
79
|
],
|
|
@@ -80,6 +81,7 @@ var PRIMARY_GROUPS = [
|
|
|
80
81
|
"rig server status",
|
|
81
82
|
"rig server add prod https://where.rig-does.work",
|
|
82
83
|
"rig server use prod",
|
|
84
|
+
"rig server repair-link --repo owner/repo",
|
|
83
85
|
"rig server use local",
|
|
84
86
|
"rig server start --port 3773"
|
|
85
87
|
],
|
|
@@ -976,16 +978,31 @@ function taskViewIntent(argv, command = "", rest = [], raw) {
|
|
|
976
978
|
const { payload, label } = taskViewPayload(command, rest);
|
|
977
979
|
return intent("tasks", argv, "refresh", payload, label, raw);
|
|
978
980
|
}
|
|
979
|
-
function routeServer(argv, command, raw, checkingLabel) {
|
|
980
|
-
if (!command || command === "status") {
|
|
981
|
+
function routeServer(argv, command, rest, raw, checkingLabel) {
|
|
982
|
+
if (!command || command === "status" || command === "list") {
|
|
981
983
|
return intent("server", argv, "refresh", undefined, command ? checkingLabel : "Loading server", raw);
|
|
982
984
|
}
|
|
985
|
+
if (command === "use") {
|
|
986
|
+
const alias = firstNonOption(rest);
|
|
987
|
+
if (alias === "local")
|
|
988
|
+
return intent("server", argv, "server-use-local", undefined, "Use local server", raw);
|
|
989
|
+
if (alias)
|
|
990
|
+
return intent("server", argv, "server-use-remote", { alias }, `Use ${alias}`, raw);
|
|
991
|
+
return intent("server", argv, "refresh", undefined, "Select a remote alias in Server", raw);
|
|
992
|
+
}
|
|
993
|
+
if (command === "add")
|
|
994
|
+
return intent("server", argv, "server-add-remote", { argv: [...argv] }, "Add remote server", raw);
|
|
995
|
+
if (command === "repair-link")
|
|
996
|
+
return intent("server", argv, "remote-link-repair", undefined, "Repair remote link", raw);
|
|
983
997
|
return commandRunIntent(argv, raw);
|
|
984
998
|
}
|
|
985
999
|
function routeGithub(argv, command, rest, raw) {
|
|
986
1000
|
if (command === "auth" && (rest[0]?.toLowerCase() ?? "status") === "status" && rest.length <= 1) {
|
|
987
1001
|
return intent("server", argv, "refresh", undefined, "Checking GitHub auth", raw);
|
|
988
1002
|
}
|
|
1003
|
+
if (command === "auth" && rest[0]?.toLowerCase() === "import-gh" && rest.length <= 1) {
|
|
1004
|
+
return intent("server", argv, "github-auth-import", undefined, "Import GitHub auth", raw);
|
|
1005
|
+
}
|
|
989
1006
|
return commandRunIntent(argv, raw);
|
|
990
1007
|
}
|
|
991
1008
|
function routeDoctor(argv, command, raw) {
|
|
@@ -1034,11 +1051,16 @@ function intentFromArgv(argv) {
|
|
|
1034
1051
|
return commandRunIntent(argv);
|
|
1035
1052
|
}
|
|
1036
1053
|
if (normalizedGroup === "server")
|
|
1037
|
-
return routeServer(argv, normalizedCommand, undefined, "Checking server");
|
|
1054
|
+
return routeServer(argv, normalizedCommand, rest, undefined, "Checking server");
|
|
1038
1055
|
if (normalizedGroup === "github")
|
|
1039
1056
|
return routeGithub(argv, normalizedCommand, rest);
|
|
1040
|
-
if (normalizedGroup === "init")
|
|
1041
|
-
|
|
1057
|
+
if (normalizedGroup === "init") {
|
|
1058
|
+
if (!normalizedCommand)
|
|
1059
|
+
return intent("init", argv, "refresh", undefined, "Open init");
|
|
1060
|
+
if (rest.includes("--yes") || normalizedCommand === "--yes")
|
|
1061
|
+
return intent("init", argv, "init-start", undefined, "Run init");
|
|
1062
|
+
return intent("init", argv, "refresh", undefined, "Open init");
|
|
1063
|
+
}
|
|
1042
1064
|
if (normalizedGroup === "doctor")
|
|
1043
1065
|
return routeDoctor(argv, normalizedCommand);
|
|
1044
1066
|
if (normalizedGroup === "inbox")
|
|
@@ -1101,12 +1123,17 @@ function intentFromTypeBar(value) {
|
|
|
1101
1123
|
return commandRunIntent(parts, value);
|
|
1102
1124
|
return intent("tasks", parts, "refresh", undefined, "Select a task, then press Enter; or use run next", value);
|
|
1103
1125
|
}
|
|
1104
|
-
if (first === "init")
|
|
1105
|
-
|
|
1126
|
+
if (first === "init") {
|
|
1127
|
+
if (!second)
|
|
1128
|
+
return intent("init", parts, "refresh", undefined, "Open init", value);
|
|
1129
|
+
if (parts.includes("--yes"))
|
|
1130
|
+
return intent("init", parts, "init-start", undefined, "Run init", value);
|
|
1131
|
+
return intent("init", parts, "refresh", undefined, "Open init", value);
|
|
1132
|
+
}
|
|
1106
1133
|
if (first === "doctor")
|
|
1107
1134
|
return routeDoctor(parts, second, value);
|
|
1108
1135
|
if (first === "server")
|
|
1109
|
-
return routeServer(parts, second, value, "Loading server");
|
|
1136
|
+
return routeServer(parts, second, rest, value, "Loading server");
|
|
1110
1137
|
if (first === "github")
|
|
1111
1138
|
return routeGithub(parts, second, rest, value);
|
|
1112
1139
|
if (first === "inbox")
|
|
@@ -1124,397 +1151,6 @@ function intentFromTypeBar(value) {
|
|
|
1124
1151
|
return intentFromArgv(parts);
|
|
1125
1152
|
}
|
|
1126
1153
|
|
|
1127
|
-
// packages/cli/src/app-opentui/pi-pty-host.ts
|
|
1128
|
-
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1129
|
-
import { basename as basename2 } from "path";
|
|
1130
|
-
import { RGBA, StyledText, TextAttributes } from "@opentui/core";
|
|
1131
|
-
import { Terminal as XtermTerminal2 } from "@xterm/headless";
|
|
1132
|
-
var MIN_COLS2 = 40;
|
|
1133
|
-
var MIN_ROWS2 = 12;
|
|
1134
|
-
var MAX_ROWS2 = 300;
|
|
1135
|
-
var MAX_SNAPSHOT_LINES2 = 360;
|
|
1136
|
-
var STYLED_SNAPSHOT_MARGIN = 6;
|
|
1137
|
-
var SNAPSHOT_DELAY_MS2 = 120;
|
|
1138
|
-
var fallbackChildScriptPath = fileURLToPath2(new URL("./pi-host-child.ts", import.meta.url));
|
|
1139
|
-
var activeHost2 = null;
|
|
1140
|
-
function clampCols2(cols) {
|
|
1141
|
-
return Math.max(MIN_COLS2, Math.trunc(cols || 100));
|
|
1142
|
-
}
|
|
1143
|
-
function clampRows2(rows) {
|
|
1144
|
-
return Math.max(MIN_ROWS2, Math.min(MAX_ROWS2, Math.trunc(rows || 35)));
|
|
1145
|
-
}
|
|
1146
|
-
var XTERM_COLOR_MODE_INDEXED_16 = 16777216;
|
|
1147
|
-
var XTERM_COLOR_MODE_INDEXED_256 = 33554432;
|
|
1148
|
-
var XTERM_COLOR_MODE_RGB = 50331648;
|
|
1149
|
-
function rgbaFromXtermColor(mode, value) {
|
|
1150
|
-
if (mode === 1 || mode === 2 || mode === XTERM_COLOR_MODE_INDEXED_16 || mode === XTERM_COLOR_MODE_INDEXED_256) {
|
|
1151
|
-
return RGBA.fromIndex(value);
|
|
1152
|
-
}
|
|
1153
|
-
if (mode === 3 || mode === XTERM_COLOR_MODE_RGB) {
|
|
1154
|
-
return RGBA.fromInts(value >> 16 & 255, value >> 8 & 255, value & 255);
|
|
1155
|
-
}
|
|
1156
|
-
return;
|
|
1157
|
-
}
|
|
1158
|
-
function textAttributesFromCell(cell) {
|
|
1159
|
-
let attributes = TextAttributes.NONE;
|
|
1160
|
-
if (cell.isBold())
|
|
1161
|
-
attributes |= TextAttributes.BOLD;
|
|
1162
|
-
if (cell.isDim())
|
|
1163
|
-
attributes |= TextAttributes.DIM;
|
|
1164
|
-
if (cell.isItalic())
|
|
1165
|
-
attributes |= TextAttributes.ITALIC;
|
|
1166
|
-
if (cell.isUnderline())
|
|
1167
|
-
attributes |= TextAttributes.UNDERLINE;
|
|
1168
|
-
if (cell.isBlink())
|
|
1169
|
-
attributes |= TextAttributes.BLINK;
|
|
1170
|
-
if (cell.isInverse())
|
|
1171
|
-
attributes |= TextAttributes.INVERSE;
|
|
1172
|
-
if (cell.isInvisible())
|
|
1173
|
-
attributes |= TextAttributes.HIDDEN;
|
|
1174
|
-
if (cell.isStrikethrough())
|
|
1175
|
-
attributes |= TextAttributes.STRIKETHROUGH;
|
|
1176
|
-
return attributes;
|
|
1177
|
-
}
|
|
1178
|
-
function sameRgba(a, b) {
|
|
1179
|
-
if (!a && !b)
|
|
1180
|
-
return true;
|
|
1181
|
-
return Boolean(a && b && a.equals(b));
|
|
1182
|
-
}
|
|
1183
|
-
function sameStyle(a, b) {
|
|
1184
|
-
return sameRgba(a.fg, b.fg) && sameRgba(a.bg, b.bg) && (a.attributes ?? 0) === (b.attributes ?? 0);
|
|
1185
|
-
}
|
|
1186
|
-
function styleFromCell(cell) {
|
|
1187
|
-
return {
|
|
1188
|
-
fg: rgbaFromXtermColor(cell.getFgColorMode(), cell.getFgColor()),
|
|
1189
|
-
bg: rgbaFromXtermColor(cell.getBgColorMode(), cell.getBgColor()),
|
|
1190
|
-
attributes: textAttributesFromCell(cell)
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
function lineToStyledText(line, cols) {
|
|
1194
|
-
if (!line)
|
|
1195
|
-
return new StyledText([{ __isChunk: true, text: "" }]);
|
|
1196
|
-
const chunks = [];
|
|
1197
|
-
let run = "";
|
|
1198
|
-
let runStyle = null;
|
|
1199
|
-
const flush = () => {
|
|
1200
|
-
if (!run)
|
|
1201
|
-
return;
|
|
1202
|
-
chunks.push({
|
|
1203
|
-
__isChunk: true,
|
|
1204
|
-
text: run,
|
|
1205
|
-
...runStyle?.fg ? { fg: runStyle.fg } : {},
|
|
1206
|
-
...runStyle?.bg ? { bg: runStyle.bg } : {},
|
|
1207
|
-
...(runStyle?.attributes ?? 0) !== 0 ? { attributes: runStyle.attributes } : {}
|
|
1208
|
-
});
|
|
1209
|
-
run = "";
|
|
1210
|
-
};
|
|
1211
|
-
for (let index = 0;index < cols; index += 1) {
|
|
1212
|
-
const cell = line.getCell(index);
|
|
1213
|
-
if (!cell) {
|
|
1214
|
-
if (runStyle !== null)
|
|
1215
|
-
flush();
|
|
1216
|
-
runStyle = null;
|
|
1217
|
-
run += " ";
|
|
1218
|
-
continue;
|
|
1219
|
-
}
|
|
1220
|
-
if (cell.getWidth() === 0)
|
|
1221
|
-
continue;
|
|
1222
|
-
const style = styleFromCell(cell);
|
|
1223
|
-
if (!runStyle || !sameStyle(runStyle, style)) {
|
|
1224
|
-
flush();
|
|
1225
|
-
runStyle = style;
|
|
1226
|
-
}
|
|
1227
|
-
run += cell.getChars() || " ";
|
|
1228
|
-
}
|
|
1229
|
-
flush();
|
|
1230
|
-
return new StyledText(chunks.length > 0 ? chunks : [{ __isChunk: true, text: "" }]);
|
|
1231
|
-
}
|
|
1232
|
-
function childCommandPrefix2() {
|
|
1233
|
-
const execName = basename2(process.execPath).toLowerCase();
|
|
1234
|
-
const currentEntry = process.argv[1];
|
|
1235
|
-
if (execName === "bun" || execName === "bun.exe") {
|
|
1236
|
-
return currentEntry ? [process.execPath, currentEntry, "__opentui-pi-host"] : [process.execPath, fallbackChildScriptPath];
|
|
1237
|
-
}
|
|
1238
|
-
return [process.execPath, "__opentui-pi-host"];
|
|
1239
|
-
}
|
|
1240
|
-
function withEnv2(base) {
|
|
1241
|
-
const env = {};
|
|
1242
|
-
for (const [key, value] of Object.entries(base ?? process.env)) {
|
|
1243
|
-
if (key === "RIG_PLAIN" || key === "RIG_CLI_PLAIN_HELP" || key === "NO_COLOR")
|
|
1244
|
-
continue;
|
|
1245
|
-
if (typeof value === "string")
|
|
1246
|
-
env[key] = value;
|
|
1247
|
-
}
|
|
1248
|
-
return {
|
|
1249
|
-
...env,
|
|
1250
|
-
TERM: "xterm-256color",
|
|
1251
|
-
COLORTERM: "truecolor",
|
|
1252
|
-
FORCE_COLOR: env.FORCE_COLOR ?? "1",
|
|
1253
|
-
RIG_OPENTUI_PI_HOST: "1"
|
|
1254
|
-
};
|
|
1255
|
-
}
|
|
1256
|
-
function getActivePiHost() {
|
|
1257
|
-
return activeHost2 && !activeHost2.disposed ? activeHost2 : null;
|
|
1258
|
-
}
|
|
1259
|
-
function stopActivePiHost(reason = "detach") {
|
|
1260
|
-
activeHost2?.dispose(reason);
|
|
1261
|
-
activeHost2 = null;
|
|
1262
|
-
}
|
|
1263
|
-
|
|
1264
|
-
class PiPtyHost {
|
|
1265
|
-
runId;
|
|
1266
|
-
projectRoot;
|
|
1267
|
-
onSnapshot;
|
|
1268
|
-
onExit;
|
|
1269
|
-
onError;
|
|
1270
|
-
terminal;
|
|
1271
|
-
disposables = [];
|
|
1272
|
-
decoder = new TextDecoder("utf-8");
|
|
1273
|
-
proc = null;
|
|
1274
|
-
pty = null;
|
|
1275
|
-
status = "starting";
|
|
1276
|
-
cols;
|
|
1277
|
-
rows;
|
|
1278
|
-
message = "starting bundled Pi";
|
|
1279
|
-
lastResizeError = null;
|
|
1280
|
-
exitCode;
|
|
1281
|
-
signal;
|
|
1282
|
-
notifyTimer = null;
|
|
1283
|
-
lastStreamKey = "";
|
|
1284
|
-
_disposed = false;
|
|
1285
|
-
constructor(options) {
|
|
1286
|
-
this.runId = options.runId;
|
|
1287
|
-
this.projectRoot = options.projectRoot;
|
|
1288
|
-
this.cols = clampCols2(options.cols);
|
|
1289
|
-
this.rows = clampRows2(options.rows);
|
|
1290
|
-
this.onSnapshot = options.onSnapshot;
|
|
1291
|
-
this.onExit = options.onExit;
|
|
1292
|
-
this.onError = options.onError;
|
|
1293
|
-
this.terminal = new XtermTerminal2({
|
|
1294
|
-
allowProposedApi: true,
|
|
1295
|
-
cols: this.cols,
|
|
1296
|
-
rows: this.rows,
|
|
1297
|
-
scrollback: 1000
|
|
1298
|
-
});
|
|
1299
|
-
this.registerTerminalResponders();
|
|
1300
|
-
this.disposables.push(this.terminal.onWriteParsed(() => {
|
|
1301
|
-
if (this._disposed)
|
|
1302
|
-
return;
|
|
1303
|
-
const snapshot = this.createSnapshot();
|
|
1304
|
-
const key = snapshot.lines.join(`
|
|
1305
|
-
`);
|
|
1306
|
-
if (key === this.lastStreamKey)
|
|
1307
|
-
return;
|
|
1308
|
-
this.lastStreamKey = key;
|
|
1309
|
-
this.onSnapshot?.(snapshot);
|
|
1310
|
-
}));
|
|
1311
|
-
}
|
|
1312
|
-
get disposed() {
|
|
1313
|
-
return this._disposed;
|
|
1314
|
-
}
|
|
1315
|
-
get snapshot() {
|
|
1316
|
-
return this.createSnapshot();
|
|
1317
|
-
}
|
|
1318
|
-
async start() {
|
|
1319
|
-
if (this._disposed)
|
|
1320
|
-
throw new Error("Pi PTY host is disposed.");
|
|
1321
|
-
if (typeof Bun.Terminal !== "function") {
|
|
1322
|
-
throw new Error("Bun native PTY is unavailable in this runtime. Pi host requires Bun.Terminal.");
|
|
1323
|
-
}
|
|
1324
|
-
const spawnOptions = {
|
|
1325
|
-
cwd: this.projectRoot,
|
|
1326
|
-
env: withEnv2(process.env),
|
|
1327
|
-
terminal: {
|
|
1328
|
-
cols: this.cols,
|
|
1329
|
-
rows: this.rows,
|
|
1330
|
-
name: "xterm-256color",
|
|
1331
|
-
data: (_terminal, data) => this.handlePtyData(data)
|
|
1332
|
-
}
|
|
1333
|
-
};
|
|
1334
|
-
const proc = Bun.spawn([
|
|
1335
|
-
...childCommandPrefix2(),
|
|
1336
|
-
"--run-id",
|
|
1337
|
-
this.runId,
|
|
1338
|
-
"--project-root",
|
|
1339
|
-
this.projectRoot
|
|
1340
|
-
], spawnOptions);
|
|
1341
|
-
if (!proc.terminal)
|
|
1342
|
-
throw new Error("Bun did not attach a terminal to the bundled Pi child process.");
|
|
1343
|
-
this.proc = proc;
|
|
1344
|
-
this.pty = proc.terminal;
|
|
1345
|
-
this.status = "running";
|
|
1346
|
-
this.message = "bundled Pi running inside this app";
|
|
1347
|
-
this.emitSnapshotSoon(0);
|
|
1348
|
-
proc.exited.then((exitCode) => {
|
|
1349
|
-
if (this._disposed)
|
|
1350
|
-
return;
|
|
1351
|
-
this.status = exitCode === 0 ? "exited" : "failed";
|
|
1352
|
-
this.exitCode = exitCode;
|
|
1353
|
-
this.signal = null;
|
|
1354
|
-
this.message = exitCode === 0 ? "bundled Pi exited" : `bundled Pi exited with code ${exitCode}`;
|
|
1355
|
-
const snapshot = this.createSnapshot();
|
|
1356
|
-
this.onSnapshot?.(snapshot);
|
|
1357
|
-
this.onExit?.(snapshot);
|
|
1358
|
-
if (activeHost2 === this)
|
|
1359
|
-
activeHost2 = null;
|
|
1360
|
-
this.dispose("exit", { kill: false, notify: false });
|
|
1361
|
-
}).catch((error) => {
|
|
1362
|
-
if (this._disposed)
|
|
1363
|
-
return;
|
|
1364
|
-
this.status = "failed";
|
|
1365
|
-
this.message = error instanceof Error ? error.message : String(error);
|
|
1366
|
-
const snapshot = this.createSnapshot();
|
|
1367
|
-
this.onSnapshot?.(snapshot);
|
|
1368
|
-
this.onError?.(error, snapshot);
|
|
1369
|
-
if (activeHost2 === this)
|
|
1370
|
-
activeHost2 = null;
|
|
1371
|
-
this.dispose("error", { kill: false, notify: false });
|
|
1372
|
-
});
|
|
1373
|
-
}
|
|
1374
|
-
write(data) {
|
|
1375
|
-
if (this._disposed || !this.pty)
|
|
1376
|
-
return;
|
|
1377
|
-
try {
|
|
1378
|
-
this.pty.write(data);
|
|
1379
|
-
} catch (error) {
|
|
1380
|
-
this.status = "failed";
|
|
1381
|
-
this.message = error instanceof Error ? error.message : String(error);
|
|
1382
|
-
const snapshot = this.createSnapshot();
|
|
1383
|
-
this.onSnapshot?.(snapshot);
|
|
1384
|
-
this.onError?.(error, snapshot);
|
|
1385
|
-
}
|
|
1386
|
-
}
|
|
1387
|
-
resize(cols, rows) {
|
|
1388
|
-
const nextCols = clampCols2(cols);
|
|
1389
|
-
const nextRows = clampRows2(rows);
|
|
1390
|
-
if (nextCols === this.cols && nextRows === this.rows)
|
|
1391
|
-
return;
|
|
1392
|
-
this.cols = nextCols;
|
|
1393
|
-
this.rows = nextRows;
|
|
1394
|
-
this.terminal.resize(nextCols, nextRows);
|
|
1395
|
-
try {
|
|
1396
|
-
this.pty?.resize(nextCols, nextRows);
|
|
1397
|
-
this.lastResizeError = null;
|
|
1398
|
-
} catch (error) {
|
|
1399
|
-
this.lastResizeError = error instanceof Error ? error.message : String(error);
|
|
1400
|
-
}
|
|
1401
|
-
this.emitSnapshotSoon(0);
|
|
1402
|
-
}
|
|
1403
|
-
detach() {
|
|
1404
|
-
this.dispose("detach");
|
|
1405
|
-
return this.createSnapshot("detached from bundled Pi");
|
|
1406
|
-
}
|
|
1407
|
-
dispose(reason = "dispose", options = {}) {
|
|
1408
|
-
if (this._disposed)
|
|
1409
|
-
return;
|
|
1410
|
-
this._disposed = true;
|
|
1411
|
-
if (this.notifyTimer)
|
|
1412
|
-
clearTimeout(this.notifyTimer);
|
|
1413
|
-
this.notifyTimer = null;
|
|
1414
|
-
for (const disposable of this.disposables.splice(0)) {
|
|
1415
|
-
try {
|
|
1416
|
-
disposable.dispose();
|
|
1417
|
-
} catch {}
|
|
1418
|
-
}
|
|
1419
|
-
if (options.kill !== false) {
|
|
1420
|
-
try {
|
|
1421
|
-
this.proc?.kill("SIGTERM");
|
|
1422
|
-
} catch {}
|
|
1423
|
-
}
|
|
1424
|
-
try {
|
|
1425
|
-
this.pty?.close();
|
|
1426
|
-
} catch {}
|
|
1427
|
-
try {
|
|
1428
|
-
this.terminal.dispose();
|
|
1429
|
-
} catch {}
|
|
1430
|
-
if (activeHost2 === this)
|
|
1431
|
-
activeHost2 = null;
|
|
1432
|
-
if (options.notify) {
|
|
1433
|
-
this.message = reason;
|
|
1434
|
-
this.onSnapshot?.(this.createSnapshot(reason));
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
handlePtyData(data) {
|
|
1438
|
-
if (this._disposed)
|
|
1439
|
-
return;
|
|
1440
|
-
const text = this.decoder.decode(data, { stream: true });
|
|
1441
|
-
this.respondToRawTerminalQueries(text);
|
|
1442
|
-
this.terminal.write(data);
|
|
1443
|
-
}
|
|
1444
|
-
emitSnapshotSoon(delayMs = SNAPSHOT_DELAY_MS2) {
|
|
1445
|
-
if (this._disposed || this.notifyTimer)
|
|
1446
|
-
return;
|
|
1447
|
-
this.notifyTimer = setTimeout(() => {
|
|
1448
|
-
this.notifyTimer = null;
|
|
1449
|
-
if (this._disposed)
|
|
1450
|
-
return;
|
|
1451
|
-
this.onSnapshot?.(this.createSnapshot());
|
|
1452
|
-
}, delayMs);
|
|
1453
|
-
}
|
|
1454
|
-
createSnapshot(message = this.message) {
|
|
1455
|
-
const buffer = this.terminal.buffer.active;
|
|
1456
|
-
const end = buffer.length;
|
|
1457
|
-
const start = Math.max(0, end - MAX_SNAPSHOT_LINES2);
|
|
1458
|
-
const styledStart = Math.max(start, end - this.rows - STYLED_SNAPSHOT_MARGIN);
|
|
1459
|
-
const lines = [];
|
|
1460
|
-
const styledLines = [];
|
|
1461
|
-
for (let row = start;row < end; row += 1) {
|
|
1462
|
-
const line = buffer.getLine(row);
|
|
1463
|
-
lines.push((line?.translateToString(false) ?? "").slice(0, this.cols));
|
|
1464
|
-
if (row >= styledStart)
|
|
1465
|
-
styledLines[lines.length - 1] = lineToStyledText(line, this.cols);
|
|
1466
|
-
}
|
|
1467
|
-
while (lines.length < this.rows) {
|
|
1468
|
-
lines.push("");
|
|
1469
|
-
styledLines[lines.length - 1] = new StyledText([{ __isChunk: true, text: "" }]);
|
|
1470
|
-
}
|
|
1471
|
-
const resolvedMessage = this.lastResizeError ? `resize degraded: ${this.lastResizeError}` : message;
|
|
1472
|
-
return {
|
|
1473
|
-
runId: this.runId,
|
|
1474
|
-
status: this.status,
|
|
1475
|
-
cols: this.cols,
|
|
1476
|
-
rows: this.rows,
|
|
1477
|
-
lines,
|
|
1478
|
-
styledLines,
|
|
1479
|
-
message: resolvedMessage,
|
|
1480
|
-
...this.lastResizeError ? { resizeError: this.lastResizeError } : {},
|
|
1481
|
-
...this.exitCode !== undefined ? { exitCode: this.exitCode } : {},
|
|
1482
|
-
...this.signal !== undefined ? { signal: this.signal } : {}
|
|
1483
|
-
};
|
|
1484
|
-
}
|
|
1485
|
-
registerTerminalResponders() {
|
|
1486
|
-
this.disposables.push(this.terminal.parser.registerCsiHandler({ final: "c" }, (params) => {
|
|
1487
|
-
if (params.length === 0 || params[0] === 0)
|
|
1488
|
-
this.write("\x1B[?62;22c");
|
|
1489
|
-
return false;
|
|
1490
|
-
}));
|
|
1491
|
-
this.disposables.push(this.terminal.parser.registerCsiHandler({ prefix: ">", final: "c" }, (params) => {
|
|
1492
|
-
if (params.length === 0 || params[0] === 0)
|
|
1493
|
-
this.write("\x1B[>0;0;0c");
|
|
1494
|
-
return false;
|
|
1495
|
-
}));
|
|
1496
|
-
this.disposables.push(this.terminal.parser.registerCsiHandler({ final: "n" }, (params) => {
|
|
1497
|
-
if (params[0] === 5) {
|
|
1498
|
-
this.write("\x1B[0n");
|
|
1499
|
-
} else if (params[0] === 6) {
|
|
1500
|
-
const row = this.terminal.buffer.active.cursorY + 1;
|
|
1501
|
-
const col = this.terminal.buffer.active.cursorX + 1;
|
|
1502
|
-
this.write(`\x1B[${row};${col}R`);
|
|
1503
|
-
}
|
|
1504
|
-
return false;
|
|
1505
|
-
}));
|
|
1506
|
-
}
|
|
1507
|
-
respondToRawTerminalQueries(text) {
|
|
1508
|
-
if (!text)
|
|
1509
|
-
return;
|
|
1510
|
-
const decrqm = /\x1b\[\?(\d+)\$p/g;
|
|
1511
|
-
let match;
|
|
1512
|
-
while ((match = decrqm.exec(text)) !== null) {
|
|
1513
|
-
this.write(`\x1B[?${match[1]};2$y`);
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
}
|
|
1517
|
-
|
|
1518
1154
|
// packages/cli/src/app-opentui/keymap.ts
|
|
1519
1155
|
var autocompleteState;
|
|
1520
1156
|
function clearTypeBar(context, message) {
|
|
@@ -1524,22 +1160,15 @@ function clearTypeBar(context, message) {
|
|
|
1524
1160
|
context.emitTypeBarPatch({ value: "", mode: "nav", prompt: undefined, message });
|
|
1525
1161
|
}
|
|
1526
1162
|
function handleEmbeddedTerminalKey(context, key) {
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
const
|
|
1530
|
-
const host = state.scene === "handoff" ? piHost : state.scene === "command" ? commandHost : null;
|
|
1163
|
+
if (context.getState().scene !== "command")
|
|
1164
|
+
return false;
|
|
1165
|
+
const host = getActiveCommandHost();
|
|
1531
1166
|
if (!host)
|
|
1532
1167
|
return false;
|
|
1533
1168
|
if (key.ctrl && key.name === "]") {
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
context.runAppAction("Opening runs", () => context.runtime.runIntent({ scene: "fleet", argv: ["runs"], action: { kind: "refresh", label: "Opening runs" } }));
|
|
1538
|
-
} else {
|
|
1539
|
-
stopActiveCommandHost("operator detach");
|
|
1540
|
-
clearTypeBar(context, "closed command");
|
|
1541
|
-
context.runAppAction("Project menu", () => context.runtime.runIntent({ scene: "main", argv: ["main"], action: { kind: "none", label: "Project menu" } }));
|
|
1542
|
-
}
|
|
1169
|
+
stopActiveCommandHost("operator detach");
|
|
1170
|
+
clearTypeBar(context, "closed command");
|
|
1171
|
+
context.runAppAction("Project menu", () => context.runtime.runIntent({ scene: "main", argv: ["main"], action: { kind: "none", label: "Project menu" } }));
|
|
1543
1172
|
return true;
|
|
1544
1173
|
}
|
|
1545
1174
|
const sequence = key.raw || key.sequence;
|