@h-rig/cli 0.0.6-alpha.87 → 0.0.6-alpha.88
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 +210 -562
- 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/family.js +31 -4
- package/dist/src/app-opentui/adapters/pi-attach.d.ts +7 -0
- package/dist/src/app-opentui/adapters/pi-attach.js +527 -473
- package/dist/src/app-opentui/adapters/tasks.js +82 -468
- package/dist/src/app-opentui/bootstrap.js +210 -562
- package/dist/src/app-opentui/index.js +68 -441
- package/dist/src/app-opentui/keymap.js +2 -387
- package/dist/src/app-opentui/pi-host-child.js +31 -4
- 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 +42 -427
- package/dist/src/app-opentui/react/ChromeHost.js +28 -411
- package/dist/src/app-opentui/react/launch.js +106 -466
- package/dist/src/app-opentui/registry.js +96 -482
- 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 +68 -441
- package/dist/src/commands/_operator-view.js +31 -4
- package/dist/src/commands/_pi-frontend.d.ts +25 -0
- package/dist/src/commands/_pi-frontend.js +32 -4
- package/dist/src/commands/run.js +31 -4
- package/dist/src/commands/task.js +31 -4
- package/dist/src/commands.js +31 -4
- package/dist/src/index.js +31 -4
- package/package.json +8 -8
|
@@ -1125,395 +1125,10 @@ function intentFromTypeBar(value) {
|
|
|
1125
1125
|
}
|
|
1126
1126
|
|
|
1127
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
1128
|
function getActivePiHost() {
|
|
1257
|
-
return
|
|
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
|
-
}
|
|
1129
|
+
return null;
|
|
1516
1130
|
}
|
|
1131
|
+
function stopActivePiHost(_reason) {}
|
|
1517
1132
|
|
|
1518
1133
|
// packages/cli/src/app-opentui/keymap.ts
|
|
1519
1134
|
var autocompleteState;
|
|
@@ -776,6 +776,29 @@ function installRigPiTheme() {
|
|
|
776
776
|
}
|
|
777
777
|
} catch {}
|
|
778
778
|
}
|
|
779
|
+
async function runWithProcessExitGuard(body) {
|
|
780
|
+
const realExit = process.exit;
|
|
781
|
+
let exitCode = 0;
|
|
782
|
+
let signalQuit = () => {};
|
|
783
|
+
const quit = new Promise((resolve3) => {
|
|
784
|
+
signalQuit = resolve3;
|
|
785
|
+
});
|
|
786
|
+
const guardedExit = (code) => {
|
|
787
|
+
exitCode = typeof code === "number" ? code : 0;
|
|
788
|
+
signalQuit();
|
|
789
|
+
return;
|
|
790
|
+
};
|
|
791
|
+
process.exit = guardedExit;
|
|
792
|
+
try {
|
|
793
|
+
await Promise.race([Promise.resolve().then(body), quit]);
|
|
794
|
+
} finally {
|
|
795
|
+
process.exit = realExit;
|
|
796
|
+
}
|
|
797
|
+
return exitCode;
|
|
798
|
+
}
|
|
799
|
+
function runPiMainReturningOnQuit(args, options) {
|
|
800
|
+
return runWithProcessExitGuard(() => runPiMain(args, options));
|
|
801
|
+
}
|
|
779
802
|
async function attachRunBundledPiFrontend(context, input) {
|
|
780
803
|
const tempSessionDir = mkdtempSync(join(tmpdir(), "rig-pi-frontend-sessions-"));
|
|
781
804
|
const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
|
|
@@ -791,16 +814,20 @@ async function attachRunBundledPiFrontend(context, input) {
|
|
|
791
814
|
};
|
|
792
815
|
let detached = false;
|
|
793
816
|
try {
|
|
794
|
-
|
|
817
|
+
const piArgs = [
|
|
795
818
|
"--offline",
|
|
796
819
|
"--no-extensions",
|
|
797
820
|
"--no-skills",
|
|
798
821
|
"--no-prompt-templates",
|
|
799
822
|
"--no-context-files",
|
|
800
823
|
...sessionFileArg
|
|
801
|
-
]
|
|
802
|
-
|
|
803
|
-
|
|
824
|
+
];
|
|
825
|
+
const piOptions = { extensionFactories: [piRigExtensionFactory] };
|
|
826
|
+
if (input.returnOnQuit) {
|
|
827
|
+
await runPiMainReturningOnQuit(piArgs, piOptions);
|
|
828
|
+
} else {
|
|
829
|
+
await runPiMain(piArgs, piOptions);
|
|
830
|
+
}
|
|
804
831
|
detached = true;
|
|
805
832
|
} finally {
|
|
806
833
|
restoreEnv();
|
|
@@ -1,78 +1,28 @@
|
|
|
1
|
-
import { StyledText } from "@opentui/core";
|
|
2
1
|
export type PiPtyHostStatus = "starting" | "running" | "exited" | "failed";
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* The worker/remote Pi daemon still owns tools, skills, cwd, model, session and
|
|
7
|
-
* context. This local host only mirrors a PTY/xterm viewport into selectable
|
|
8
|
-
* OpenTUI text. Keep this snapshot path explicit until Rig grows a dedicated
|
|
9
|
-
* PTY/xterm viewport renderable or deliberately suspends OpenTUI for direct Pi
|
|
10
|
-
* terminal ownership.
|
|
11
|
-
*/
|
|
2
|
+
/** Vestigial presentation snapshot. No longer produced (attach ejects to native
|
|
3
|
+
* Pi); retained as a type so the handoff scene's now-dead terminal branch still
|
|
4
|
+
* compiles. */
|
|
12
5
|
export type PiPtyHostSnapshot = {
|
|
13
6
|
readonly runId: string;
|
|
14
7
|
readonly status: PiPtyHostStatus;
|
|
15
8
|
readonly cols: number;
|
|
16
9
|
readonly rows: number;
|
|
17
10
|
readonly lines: readonly string[];
|
|
18
|
-
readonly styledLines?: readonly StyledText[];
|
|
11
|
+
readonly styledLines?: readonly import("@opentui/core").StyledText[];
|
|
19
12
|
readonly message?: string;
|
|
20
13
|
readonly resizeError?: string;
|
|
21
14
|
readonly exitCode?: number;
|
|
22
15
|
readonly signal?: string | null;
|
|
23
16
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
readonly
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
readonly env?: NodeJS.ProcessEnv;
|
|
31
|
-
readonly onSnapshot?: (snapshot: PiPtyHostSnapshot) => void;
|
|
32
|
-
readonly onExit?: (snapshot: PiPtyHostSnapshot) => void;
|
|
33
|
-
readonly onError?: (error: unknown, snapshot: PiPtyHostSnapshot) => void;
|
|
17
|
+
/** Minimal handle the shell's embedded-terminal code paths type against. Nothing
|
|
18
|
+
* constructs one anymore. */
|
|
19
|
+
export type PiPtyHost = {
|
|
20
|
+
readonly disposed: boolean;
|
|
21
|
+
write(data: string | Uint8Array | BufferSource): void;
|
|
22
|
+
resize(cols: number, rows: number): void;
|
|
34
23
|
};
|
|
24
|
+
/** There is no in-shell Pi host since attach ejects to native Pi — always null. */
|
|
35
25
|
export declare function getActivePiHost(): PiPtyHost | null;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
export declare
|
|
39
|
-
private readonly runId;
|
|
40
|
-
private readonly projectRoot;
|
|
41
|
-
private readonly onSnapshot?;
|
|
42
|
-
private readonly onExit?;
|
|
43
|
-
private readonly onError?;
|
|
44
|
-
private readonly terminal;
|
|
45
|
-
private readonly disposables;
|
|
46
|
-
private readonly decoder;
|
|
47
|
-
private proc;
|
|
48
|
-
private pty;
|
|
49
|
-
private status;
|
|
50
|
-
private cols;
|
|
51
|
-
private rows;
|
|
52
|
-
private message;
|
|
53
|
-
private lastResizeError;
|
|
54
|
-
private exitCode;
|
|
55
|
-
private signal;
|
|
56
|
-
private notifyTimer;
|
|
57
|
-
/** Last streamed buffer content, so the onWriteParsed handler only emits a
|
|
58
|
-
* snapshot when the rendered content actually changed. */
|
|
59
|
-
private lastStreamKey;
|
|
60
|
-
private _disposed;
|
|
61
|
-
constructor(options: PiPtyHostOptions);
|
|
62
|
-
get disposed(): boolean;
|
|
63
|
-
get snapshot(): PiPtyHostSnapshot;
|
|
64
|
-
start(): Promise<void>;
|
|
65
|
-
write(data: PiPtyInput): void;
|
|
66
|
-
resize(cols: number, rows: number): void;
|
|
67
|
-
detach(): PiPtyHostSnapshot;
|
|
68
|
-
dispose(reason?: string, options?: {
|
|
69
|
-
readonly kill?: boolean;
|
|
70
|
-
readonly notify?: boolean;
|
|
71
|
-
}): void;
|
|
72
|
-
private handlePtyData;
|
|
73
|
-
private emitSnapshotSoon;
|
|
74
|
-
private createSnapshot;
|
|
75
|
-
private registerTerminalResponders;
|
|
76
|
-
private respondToRawTerminalQueries;
|
|
77
|
-
}
|
|
78
|
-
export {};
|
|
26
|
+
/** No-op: nothing to stop, since attach ejects to native Pi and never spawns an
|
|
27
|
+
* in-shell host. Kept so existing detach/cleanup call sites compile unchanged. */
|
|
28
|
+
export declare function stopActivePiHost(_reason?: string): void;
|