@h-rig/cli 0.0.6-alpha.86 → 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.
Files changed (80) hide show
  1. package/dist/bin/rig.js +287 -578
  2. package/dist/src/app-opentui/adapters/common.d.ts +3 -0
  3. package/dist/src/app-opentui/adapters/common.js +4 -0
  4. package/dist/src/app-opentui/adapters/family.js +31 -4
  5. package/dist/src/app-opentui/adapters/pi-attach.d.ts +7 -0
  6. package/dist/src/app-opentui/adapters/pi-attach.js +527 -473
  7. package/dist/src/app-opentui/adapters/tasks.js +82 -468
  8. package/dist/src/app-opentui/bootstrap.js +287 -578
  9. package/dist/src/app-opentui/command-palette.js +1 -0
  10. package/dist/src/app-opentui/drone.js +1 -0
  11. package/dist/src/app-opentui/index.js +127 -446
  12. package/dist/src/app-opentui/keymap.js +2 -387
  13. package/dist/src/app-opentui/list-search.d.ts +5 -1
  14. package/dist/src/app-opentui/list-search.js +2 -2
  15. package/dist/src/app-opentui/pi-host-child.js +31 -4
  16. package/dist/src/app-opentui/pi-pty-host.d.ts +14 -64
  17. package/dist/src/app-opentui/pi-pty-host.js +3 -397
  18. package/dist/src/app-opentui/react/App.js +107 -433
  19. package/dist/src/app-opentui/react/Backdrop.js +1 -0
  20. package/dist/src/app-opentui/react/ChromeHost.js +34 -410
  21. package/dist/src/app-opentui/react/SceneFrameView.js +55 -5
  22. package/dist/src/app-opentui/react/launch.js +171 -472
  23. package/dist/src/app-opentui/react/syntax.js +1 -0
  24. package/dist/src/app-opentui/registry.js +99 -487
  25. package/dist/src/app-opentui/render/graphics.js +1 -0
  26. package/dist/src/app-opentui/render/hover.d.ts +11 -0
  27. package/dist/src/app-opentui/render/hover.js +34 -0
  28. package/dist/src/app-opentui/render/native-host.js +1 -0
  29. package/dist/src/app-opentui/render/panels.js +50 -3
  30. package/dist/src/app-opentui/render/preloader.js +1 -0
  31. package/dist/src/app-opentui/render/scene.js +1 -0
  32. package/dist/src/app-opentui/render/terminal-handoff.d.ts +16 -0
  33. package/dist/src/app-opentui/render/terminal-handoff.js +14 -0
  34. package/dist/src/app-opentui/render/text.d.ts +13 -0
  35. package/dist/src/app-opentui/render/text.js +54 -5
  36. package/dist/src/app-opentui/render/type-bar.js +1 -0
  37. package/dist/src/app-opentui/runtime.js +127 -446
  38. package/dist/src/app-opentui/scenes/command.js +1 -0
  39. package/dist/src/app-opentui/scenes/doctor.js +1 -0
  40. package/dist/src/app-opentui/scenes/error.js +1 -0
  41. package/dist/src/app-opentui/scenes/family-domains/agent.js +1 -0
  42. package/dist/src/app-opentui/scenes/family-domains/browser.js +1 -0
  43. package/dist/src/app-opentui/scenes/family-domains/dist.js +1 -0
  44. package/dist/src/app-opentui/scenes/family-domains/git.js +1 -0
  45. package/dist/src/app-opentui/scenes/family-domains/github.js +1 -0
  46. package/dist/src/app-opentui/scenes/family-domains/harness.js +1 -0
  47. package/dist/src/app-opentui/scenes/family-domains/index.js +1 -0
  48. package/dist/src/app-opentui/scenes/family-domains/kit.js +1 -0
  49. package/dist/src/app-opentui/scenes/family-domains/profile.js +1 -0
  50. package/dist/src/app-opentui/scenes/family-domains/queue.js +1 -0
  51. package/dist/src/app-opentui/scenes/family-domains/remote.js +1 -0
  52. package/dist/src/app-opentui/scenes/family-domains/review.js +1 -0
  53. package/dist/src/app-opentui/scenes/family-domains/setup.js +1 -0
  54. package/dist/src/app-opentui/scenes/family-domains/stats.js +1 -0
  55. package/dist/src/app-opentui/scenes/family.js +1 -0
  56. package/dist/src/app-opentui/scenes/fleet.js +3 -5
  57. package/dist/src/app-opentui/scenes/handoff.js +1 -0
  58. package/dist/src/app-opentui/scenes/help.js +1 -0
  59. package/dist/src/app-opentui/scenes/inbox.js +1 -0
  60. package/dist/src/app-opentui/scenes/init.js +1 -0
  61. package/dist/src/app-opentui/scenes/inspect.js +1 -0
  62. package/dist/src/app-opentui/scenes/main.js +1 -0
  63. package/dist/src/app-opentui/scenes/pi.js +1 -0
  64. package/dist/src/app-opentui/scenes/plugin.js +1 -0
  65. package/dist/src/app-opentui/scenes/repo.js +1 -0
  66. package/dist/src/app-opentui/scenes/run-detail.js +1 -0
  67. package/dist/src/app-opentui/scenes/server.js +1 -0
  68. package/dist/src/app-opentui/scenes/tasks.js +3 -5
  69. package/dist/src/app-opentui/scenes/workspace.js +1 -0
  70. package/dist/src/app-opentui/selectable.js +1 -0
  71. package/dist/src/app-opentui/theme.d.ts +1 -0
  72. package/dist/src/app-opentui/theme.js +1 -0
  73. package/dist/src/commands/_operator-view.js +31 -4
  74. package/dist/src/commands/_pi-frontend.d.ts +25 -0
  75. package/dist/src/commands/_pi-frontend.js +32 -4
  76. package/dist/src/commands/run.js +31 -4
  77. package/dist/src/commands/task.js +31 -4
  78. package/dist/src/commands.js +31 -4
  79. package/dist/src/index.js +31 -4
  80. package/package.json +8 -8
@@ -402,7 +402,7 @@ function truncateText(text, width) {
402
402
  // packages/cli/src/app-opentui/runtime.ts
403
403
  import { existsSync as existsSync3 } from "fs";
404
404
  import { resolve as resolve3 } from "path";
405
- import { BoxRenderable as BoxRenderable3, RGBA as RGBA8, StyledText as StyledText4, TextRenderable as TextRenderable4, createCliRenderer } from "@opentui/core";
405
+ import { BoxRenderable as BoxRenderable3, RGBA as RGBA7, StyledText as StyledText3, TextRenderable as TextRenderable4, createCliRenderer } from "@opentui/core";
406
406
 
407
407
  // packages/cli/src/app-opentui/focus-manager.ts
408
408
  class AppFocusManager {
@@ -1245,395 +1245,10 @@ function cycleCompletion(value, state, candidates = commandCandidates()) {
1245
1245
  }
1246
1246
 
1247
1247
  // packages/cli/src/app-opentui/pi-pty-host.ts
1248
- import { fileURLToPath as fileURLToPath2 } from "url";
1249
- import { basename as basename2 } from "path";
1250
- import { RGBA, StyledText, TextAttributes } from "@opentui/core";
1251
- import { Terminal as XtermTerminal2 } from "@xterm/headless";
1252
- var MIN_COLS2 = 40;
1253
- var MIN_ROWS2 = 12;
1254
- var MAX_ROWS2 = 300;
1255
- var MAX_SNAPSHOT_LINES2 = 360;
1256
- var STYLED_SNAPSHOT_MARGIN = 6;
1257
- var SNAPSHOT_DELAY_MS2 = 120;
1258
- var fallbackChildScriptPath = fileURLToPath2(new URL("./pi-host-child.ts", import.meta.url));
1259
- var activeHost2 = null;
1260
- function clampCols2(cols) {
1261
- return Math.max(MIN_COLS2, Math.trunc(cols || 100));
1262
- }
1263
- function clampRows2(rows) {
1264
- return Math.max(MIN_ROWS2, Math.min(MAX_ROWS2, Math.trunc(rows || 35)));
1265
- }
1266
- var XTERM_COLOR_MODE_INDEXED_16 = 16777216;
1267
- var XTERM_COLOR_MODE_INDEXED_256 = 33554432;
1268
- var XTERM_COLOR_MODE_RGB = 50331648;
1269
- function rgbaFromXtermColor(mode, value) {
1270
- if (mode === 1 || mode === 2 || mode === XTERM_COLOR_MODE_INDEXED_16 || mode === XTERM_COLOR_MODE_INDEXED_256) {
1271
- return RGBA.fromIndex(value);
1272
- }
1273
- if (mode === 3 || mode === XTERM_COLOR_MODE_RGB) {
1274
- return RGBA.fromInts(value >> 16 & 255, value >> 8 & 255, value & 255);
1275
- }
1276
- return;
1277
- }
1278
- function textAttributesFromCell(cell) {
1279
- let attributes = TextAttributes.NONE;
1280
- if (cell.isBold())
1281
- attributes |= TextAttributes.BOLD;
1282
- if (cell.isDim())
1283
- attributes |= TextAttributes.DIM;
1284
- if (cell.isItalic())
1285
- attributes |= TextAttributes.ITALIC;
1286
- if (cell.isUnderline())
1287
- attributes |= TextAttributes.UNDERLINE;
1288
- if (cell.isBlink())
1289
- attributes |= TextAttributes.BLINK;
1290
- if (cell.isInverse())
1291
- attributes |= TextAttributes.INVERSE;
1292
- if (cell.isInvisible())
1293
- attributes |= TextAttributes.HIDDEN;
1294
- if (cell.isStrikethrough())
1295
- attributes |= TextAttributes.STRIKETHROUGH;
1296
- return attributes;
1297
- }
1298
- function sameRgba(a, b) {
1299
- if (!a && !b)
1300
- return true;
1301
- return Boolean(a && b && a.equals(b));
1302
- }
1303
- function sameStyle(a, b) {
1304
- return sameRgba(a.fg, b.fg) && sameRgba(a.bg, b.bg) && (a.attributes ?? 0) === (b.attributes ?? 0);
1305
- }
1306
- function styleFromCell(cell) {
1307
- return {
1308
- fg: rgbaFromXtermColor(cell.getFgColorMode(), cell.getFgColor()),
1309
- bg: rgbaFromXtermColor(cell.getBgColorMode(), cell.getBgColor()),
1310
- attributes: textAttributesFromCell(cell)
1311
- };
1312
- }
1313
- function lineToStyledText(line, cols) {
1314
- if (!line)
1315
- return new StyledText([{ __isChunk: true, text: "" }]);
1316
- const chunks = [];
1317
- let run = "";
1318
- let runStyle = null;
1319
- const flush = () => {
1320
- if (!run)
1321
- return;
1322
- chunks.push({
1323
- __isChunk: true,
1324
- text: run,
1325
- ...runStyle?.fg ? { fg: runStyle.fg } : {},
1326
- ...runStyle?.bg ? { bg: runStyle.bg } : {},
1327
- ...(runStyle?.attributes ?? 0) !== 0 ? { attributes: runStyle.attributes } : {}
1328
- });
1329
- run = "";
1330
- };
1331
- for (let index = 0;index < cols; index += 1) {
1332
- const cell = line.getCell(index);
1333
- if (!cell) {
1334
- if (runStyle !== null)
1335
- flush();
1336
- runStyle = null;
1337
- run += " ";
1338
- continue;
1339
- }
1340
- if (cell.getWidth() === 0)
1341
- continue;
1342
- const style = styleFromCell(cell);
1343
- if (!runStyle || !sameStyle(runStyle, style)) {
1344
- flush();
1345
- runStyle = style;
1346
- }
1347
- run += cell.getChars() || " ";
1348
- }
1349
- flush();
1350
- return new StyledText(chunks.length > 0 ? chunks : [{ __isChunk: true, text: "" }]);
1351
- }
1352
- function childCommandPrefix2() {
1353
- const execName = basename2(process.execPath).toLowerCase();
1354
- const currentEntry = process.argv[1];
1355
- if (execName === "bun" || execName === "bun.exe") {
1356
- return currentEntry ? [process.execPath, currentEntry, "__opentui-pi-host"] : [process.execPath, fallbackChildScriptPath];
1357
- }
1358
- return [process.execPath, "__opentui-pi-host"];
1359
- }
1360
- function withEnv2(base) {
1361
- const env = {};
1362
- for (const [key, value] of Object.entries(base ?? process.env)) {
1363
- if (key === "RIG_PLAIN" || key === "RIG_CLI_PLAIN_HELP" || key === "NO_COLOR")
1364
- continue;
1365
- if (typeof value === "string")
1366
- env[key] = value;
1367
- }
1368
- return {
1369
- ...env,
1370
- TERM: "xterm-256color",
1371
- COLORTERM: "truecolor",
1372
- FORCE_COLOR: env.FORCE_COLOR ?? "1",
1373
- RIG_OPENTUI_PI_HOST: "1"
1374
- };
1375
- }
1376
1248
  function getActivePiHost() {
1377
- return activeHost2 && !activeHost2.disposed ? activeHost2 : null;
1378
- }
1379
- function stopActivePiHost(reason = "detach") {
1380
- activeHost2?.dispose(reason);
1381
- activeHost2 = null;
1382
- }
1383
-
1384
- class PiPtyHost {
1385
- runId;
1386
- projectRoot;
1387
- onSnapshot;
1388
- onExit;
1389
- onError;
1390
- terminal;
1391
- disposables = [];
1392
- decoder = new TextDecoder("utf-8");
1393
- proc = null;
1394
- pty = null;
1395
- status = "starting";
1396
- cols;
1397
- rows;
1398
- message = "starting bundled Pi";
1399
- lastResizeError = null;
1400
- exitCode;
1401
- signal;
1402
- notifyTimer = null;
1403
- lastStreamKey = "";
1404
- _disposed = false;
1405
- constructor(options) {
1406
- this.runId = options.runId;
1407
- this.projectRoot = options.projectRoot;
1408
- this.cols = clampCols2(options.cols);
1409
- this.rows = clampRows2(options.rows);
1410
- this.onSnapshot = options.onSnapshot;
1411
- this.onExit = options.onExit;
1412
- this.onError = options.onError;
1413
- this.terminal = new XtermTerminal2({
1414
- allowProposedApi: true,
1415
- cols: this.cols,
1416
- rows: this.rows,
1417
- scrollback: 1000
1418
- });
1419
- this.registerTerminalResponders();
1420
- this.disposables.push(this.terminal.onWriteParsed(() => {
1421
- if (this._disposed)
1422
- return;
1423
- const snapshot = this.createSnapshot();
1424
- const key = snapshot.lines.join(`
1425
- `);
1426
- if (key === this.lastStreamKey)
1427
- return;
1428
- this.lastStreamKey = key;
1429
- this.onSnapshot?.(snapshot);
1430
- }));
1431
- }
1432
- get disposed() {
1433
- return this._disposed;
1434
- }
1435
- get snapshot() {
1436
- return this.createSnapshot();
1437
- }
1438
- async start() {
1439
- if (this._disposed)
1440
- throw new Error("Pi PTY host is disposed.");
1441
- if (typeof Bun.Terminal !== "function") {
1442
- throw new Error("Bun native PTY is unavailable in this runtime. Pi host requires Bun.Terminal.");
1443
- }
1444
- const spawnOptions = {
1445
- cwd: this.projectRoot,
1446
- env: withEnv2(process.env),
1447
- terminal: {
1448
- cols: this.cols,
1449
- rows: this.rows,
1450
- name: "xterm-256color",
1451
- data: (_terminal, data) => this.handlePtyData(data)
1452
- }
1453
- };
1454
- const proc = Bun.spawn([
1455
- ...childCommandPrefix2(),
1456
- "--run-id",
1457
- this.runId,
1458
- "--project-root",
1459
- this.projectRoot
1460
- ], spawnOptions);
1461
- if (!proc.terminal)
1462
- throw new Error("Bun did not attach a terminal to the bundled Pi child process.");
1463
- this.proc = proc;
1464
- this.pty = proc.terminal;
1465
- this.status = "running";
1466
- this.message = "bundled Pi running inside this app";
1467
- this.emitSnapshotSoon(0);
1468
- proc.exited.then((exitCode) => {
1469
- if (this._disposed)
1470
- return;
1471
- this.status = exitCode === 0 ? "exited" : "failed";
1472
- this.exitCode = exitCode;
1473
- this.signal = null;
1474
- this.message = exitCode === 0 ? "bundled Pi exited" : `bundled Pi exited with code ${exitCode}`;
1475
- const snapshot = this.createSnapshot();
1476
- this.onSnapshot?.(snapshot);
1477
- this.onExit?.(snapshot);
1478
- if (activeHost2 === this)
1479
- activeHost2 = null;
1480
- this.dispose("exit", { kill: false, notify: false });
1481
- }).catch((error) => {
1482
- if (this._disposed)
1483
- return;
1484
- this.status = "failed";
1485
- this.message = error instanceof Error ? error.message : String(error);
1486
- const snapshot = this.createSnapshot();
1487
- this.onSnapshot?.(snapshot);
1488
- this.onError?.(error, snapshot);
1489
- if (activeHost2 === this)
1490
- activeHost2 = null;
1491
- this.dispose("error", { kill: false, notify: false });
1492
- });
1493
- }
1494
- write(data) {
1495
- if (this._disposed || !this.pty)
1496
- return;
1497
- try {
1498
- this.pty.write(data);
1499
- } catch (error) {
1500
- this.status = "failed";
1501
- this.message = error instanceof Error ? error.message : String(error);
1502
- const snapshot = this.createSnapshot();
1503
- this.onSnapshot?.(snapshot);
1504
- this.onError?.(error, snapshot);
1505
- }
1506
- }
1507
- resize(cols, rows) {
1508
- const nextCols = clampCols2(cols);
1509
- const nextRows = clampRows2(rows);
1510
- if (nextCols === this.cols && nextRows === this.rows)
1511
- return;
1512
- this.cols = nextCols;
1513
- this.rows = nextRows;
1514
- this.terminal.resize(nextCols, nextRows);
1515
- try {
1516
- this.pty?.resize(nextCols, nextRows);
1517
- this.lastResizeError = null;
1518
- } catch (error) {
1519
- this.lastResizeError = error instanceof Error ? error.message : String(error);
1520
- }
1521
- this.emitSnapshotSoon(0);
1522
- }
1523
- detach() {
1524
- this.dispose("detach");
1525
- return this.createSnapshot("detached from bundled Pi");
1526
- }
1527
- dispose(reason = "dispose", options = {}) {
1528
- if (this._disposed)
1529
- return;
1530
- this._disposed = true;
1531
- if (this.notifyTimer)
1532
- clearTimeout(this.notifyTimer);
1533
- this.notifyTimer = null;
1534
- for (const disposable of this.disposables.splice(0)) {
1535
- try {
1536
- disposable.dispose();
1537
- } catch {}
1538
- }
1539
- if (options.kill !== false) {
1540
- try {
1541
- this.proc?.kill("SIGTERM");
1542
- } catch {}
1543
- }
1544
- try {
1545
- this.pty?.close();
1546
- } catch {}
1547
- try {
1548
- this.terminal.dispose();
1549
- } catch {}
1550
- if (activeHost2 === this)
1551
- activeHost2 = null;
1552
- if (options.notify) {
1553
- this.message = reason;
1554
- this.onSnapshot?.(this.createSnapshot(reason));
1555
- }
1556
- }
1557
- handlePtyData(data) {
1558
- if (this._disposed)
1559
- return;
1560
- const text = this.decoder.decode(data, { stream: true });
1561
- this.respondToRawTerminalQueries(text);
1562
- this.terminal.write(data);
1563
- }
1564
- emitSnapshotSoon(delayMs = SNAPSHOT_DELAY_MS2) {
1565
- if (this._disposed || this.notifyTimer)
1566
- return;
1567
- this.notifyTimer = setTimeout(() => {
1568
- this.notifyTimer = null;
1569
- if (this._disposed)
1570
- return;
1571
- this.onSnapshot?.(this.createSnapshot());
1572
- }, delayMs);
1573
- }
1574
- createSnapshot(message = this.message) {
1575
- const buffer = this.terminal.buffer.active;
1576
- const end = buffer.length;
1577
- const start = Math.max(0, end - MAX_SNAPSHOT_LINES2);
1578
- const styledStart = Math.max(start, end - this.rows - STYLED_SNAPSHOT_MARGIN);
1579
- const lines = [];
1580
- const styledLines = [];
1581
- for (let row = start;row < end; row += 1) {
1582
- const line = buffer.getLine(row);
1583
- lines.push((line?.translateToString(false) ?? "").slice(0, this.cols));
1584
- if (row >= styledStart)
1585
- styledLines[lines.length - 1] = lineToStyledText(line, this.cols);
1586
- }
1587
- while (lines.length < this.rows) {
1588
- lines.push("");
1589
- styledLines[lines.length - 1] = new StyledText([{ __isChunk: true, text: "" }]);
1590
- }
1591
- const resolvedMessage = this.lastResizeError ? `resize degraded: ${this.lastResizeError}` : message;
1592
- return {
1593
- runId: this.runId,
1594
- status: this.status,
1595
- cols: this.cols,
1596
- rows: this.rows,
1597
- lines,
1598
- styledLines,
1599
- message: resolvedMessage,
1600
- ...this.lastResizeError ? { resizeError: this.lastResizeError } : {},
1601
- ...this.exitCode !== undefined ? { exitCode: this.exitCode } : {},
1602
- ...this.signal !== undefined ? { signal: this.signal } : {}
1603
- };
1604
- }
1605
- registerTerminalResponders() {
1606
- this.disposables.push(this.terminal.parser.registerCsiHandler({ final: "c" }, (params) => {
1607
- if (params.length === 0 || params[0] === 0)
1608
- this.write("\x1B[?62;22c");
1609
- return false;
1610
- }));
1611
- this.disposables.push(this.terminal.parser.registerCsiHandler({ prefix: ">", final: "c" }, (params) => {
1612
- if (params.length === 0 || params[0] === 0)
1613
- this.write("\x1B[>0;0;0c");
1614
- return false;
1615
- }));
1616
- this.disposables.push(this.terminal.parser.registerCsiHandler({ final: "n" }, (params) => {
1617
- if (params[0] === 5) {
1618
- this.write("\x1B[0n");
1619
- } else if (params[0] === 6) {
1620
- const row = this.terminal.buffer.active.cursorY + 1;
1621
- const col = this.terminal.buffer.active.cursorX + 1;
1622
- this.write(`\x1B[${row};${col}R`);
1623
- }
1624
- return false;
1625
- }));
1626
- }
1627
- respondToRawTerminalQueries(text) {
1628
- if (!text)
1629
- return;
1630
- const decrqm = /\x1b\[\?(\d+)\$p/g;
1631
- let match;
1632
- while ((match = decrqm.exec(text)) !== null) {
1633
- this.write(`\x1B[?${match[1]};2$y`);
1634
- }
1635
- }
1249
+ return null;
1636
1250
  }
1251
+ function stopActivePiHost(_reason) {}
1637
1252
 
1638
1253
  // packages/cli/src/app-opentui/keymap.ts
1639
1254
  var autocompleteState;
@@ -2235,13 +1850,14 @@ import {
2235
1850
  dim as otuiDim,
2236
1851
  fg as otuiFg,
2237
1852
  t,
2238
- TextAttributes as TextAttributes2
1853
+ TextAttributes
2239
1854
  } from "@opentui/core";
2240
1855
  var RIG_UI = {
2241
1856
  bg: "#070809",
2242
1857
  bg2: "#0b0c0e",
2243
1858
  panel: "#101115",
2244
1859
  panel2: "#14161b",
1860
+ hover: "#181b24",
2245
1861
  glass: "#1e2230",
2246
1862
  border: "#2a2e3a",
2247
1863
  ink: "#f4f5f8",
@@ -2297,7 +1913,7 @@ function statusColor(status) {
2297
1913
  }
2298
1914
 
2299
1915
  // packages/cli/src/app-opentui/drone.ts
2300
- import { RGBA as RGBA2, StyledText as StyledText2, TextAttributes as TextAttributes3 } from "@opentui/core";
1916
+ import { RGBA, StyledText, TextAttributes as TextAttributes2 } from "@opentui/core";
2301
1917
  var MINI_DRONE = [
2302
1918
  "(!!!) (!!!)",
2303
1919
  " \\%==%/ ",
@@ -2313,13 +1929,13 @@ var LEAD_MARK = [
2313
1929
  var BLADE_FRAMES = ["---", "\\\\\\", "|||", "///"];
2314
1930
  var EYE_FRAMES = ["o", "@", "\u2022", "."];
2315
1931
  var COLOR = {
2316
- body: RGBA2.fromHex(RIG_UI.lime),
2317
- mini: RGBA2.fromHex(RIG_UI.limeDim),
2318
- rotor: RGBA2.fromHex(RIG_UI.cyan),
2319
- path: RGBA2.fromHex(RIG_UI.cyan),
2320
- eye: RGBA2.fromHex(RIG_UI.ink),
2321
- dim: RGBA2.fromHex(RIG_UI.ink4),
2322
- ink: RGBA2.fromHex(RIG_UI.ink2)
1932
+ body: RGBA.fromHex(RIG_UI.lime),
1933
+ mini: RGBA.fromHex(RIG_UI.limeDim),
1934
+ rotor: RGBA.fromHex(RIG_UI.cyan),
1935
+ path: RGBA.fromHex(RIG_UI.cyan),
1936
+ eye: RGBA.fromHex(RIG_UI.ink),
1937
+ dim: RGBA.fromHex(RIG_UI.ink4),
1938
+ ink: RGBA.fromHex(RIG_UI.ink2)
2323
1939
  };
2324
1940
  function bladeForTick(tick, phase = 0) {
2325
1941
  return BLADE_FRAMES[(Math.floor(tick / 3) + phase) % BLADE_FRAMES.length];
@@ -2329,12 +1945,12 @@ function eyeForTick(tick, phase = 0) {
2329
1945
  return pulse > 0.55 ? EYE_FRAMES[1] : pulse > 0.1 ? EYE_FRAMES[0] : pulse > -0.45 ? EYE_FRAMES[2] : EYE_FRAMES[3];
2330
1946
  }
2331
1947
  function chunk(text, fg, bold = false, dim = false) {
2332
- let attributes = TextAttributes3.NONE;
1948
+ let attributes = TextAttributes2.NONE;
2333
1949
  if (bold)
2334
- attributes |= TextAttributes3.BOLD;
1950
+ attributes |= TextAttributes2.BOLD;
2335
1951
  if (dim)
2336
- attributes |= TextAttributes3.DIM;
2337
- return { __isChunk: true, text, fg, ...attributes !== TextAttributes3.NONE ? { attributes } : {} };
1952
+ attributes |= TextAttributes2.DIM;
1953
+ return { __isChunk: true, text, fg, ...attributes !== TextAttributes2.NONE ? { attributes } : {} };
2338
1954
  }
2339
1955
  function styledLine(text, colorFor) {
2340
1956
  const chunks = [];
@@ -2355,7 +1971,7 @@ function styledLine(text, colorFor) {
2355
1971
  run += char;
2356
1972
  }
2357
1973
  flush();
2358
- return new StyledText2(chunks.length > 0 ? chunks : [chunk("", COLOR.ink)]);
1974
+ return new StyledText(chunks.length > 0 ? chunks : [chunk("", COLOR.ink)]);
2359
1975
  }
2360
1976
  function droneColor(char) {
2361
1977
  if (char === "?" || char === "o" || char === "@" || char === "\u2022")
@@ -2665,7 +2281,7 @@ function reduceAppEvent(state, event) {
2665
2281
  }
2666
2282
 
2667
2283
  // packages/cli/src/app-opentui/render/graphics.ts
2668
- import { FrameBufferRenderable, RGBA as RGBA3 } from "@opentui/core";
2284
+ import { FrameBufferRenderable, RGBA as RGBA2 } from "@opentui/core";
2669
2285
 
2670
2286
  // packages/cli/src/app-opentui/render/ascii-fleet.ts
2671
2287
  var LEAD_DRONE = [
@@ -2809,13 +2425,13 @@ var GLOW_FALLOFF_EXP_ASCII = 2.2;
2809
2425
  // packages/cli/src/app-opentui/render/graphics.ts
2810
2426
  var BRAILLE_SAMPLES_X = 2;
2811
2427
  var BRAILLE_SAMPLES_Y = 4;
2812
- var TRANSPARENT = RGBA3.fromValues(0, 0, 0, 0);
2813
- var BACKDROP = RGBA3.fromHex(RIG_UI.bg);
2814
- var PANEL_BG = RGBA3.fromInts(16, 17, 21, 184);
2815
- var PANEL_HEADER_BG = RGBA3.fromInts(16, 17, 21, 188);
2816
- var PANEL_LINE = RGBA3.fromInts(255, 255, 255, 20);
2817
- var PANEL_LINE_DIM = RGBA3.fromInts(255, 255, 255, 8);
2818
- var PANEL_TEXT_DIM = RGBA3.fromInts(108, 110, 121, 255);
2428
+ var TRANSPARENT = RGBA2.fromValues(0, 0, 0, 0);
2429
+ var BACKDROP = RGBA2.fromHex(RIG_UI.bg);
2430
+ var PANEL_BG = RGBA2.fromInts(16, 17, 21, 184);
2431
+ var PANEL_HEADER_BG = RGBA2.fromInts(16, 17, 21, 188);
2432
+ var PANEL_LINE = RGBA2.fromInts(255, 255, 255, 20);
2433
+ var PANEL_LINE_DIM = RGBA2.fromInts(255, 255, 255, 8);
2434
+ var PANEL_TEXT_DIM = RGBA2.fromInts(108, 110, 121, 255);
2819
2435
  var AC_RGB = [204, 255, 77];
2820
2436
  var C2_RGB = [86, 216, 255];
2821
2437
  var MG_RGB = [255, 121, 176];
@@ -2920,7 +2536,7 @@ function paletteColor(ac, c2, mg, ink) {
2920
2536
  const b = (AC_RGB[2] * ac + C2_RGB[2] * c2 + MG_RGB[2] * mg + INK_RGB[2] * ink) / total;
2921
2537
  const intensity = Math.min(1, total / 4);
2922
2538
  const lift = 0.34 + intensity * 0.66;
2923
- return RGBA3.fromInts(Math.round(r * lift), Math.round(g * lift), Math.round(b * lift), 255);
2539
+ return RGBA2.fromInts(Math.round(r * lift), Math.round(g * lift), Math.round(b * lift), 255);
2924
2540
  }
2925
2541
  function clearCanvas(canvas) {
2926
2542
  canvas.ac.fill(0);
@@ -3275,8 +2891,8 @@ function staticFleetTick(scene) {
3275
2891
  }
3276
2892
  function withAlpha(hex, alpha) {
3277
2893
  const a = Math.max(0, Math.min(255, Math.round(alpha * 255)));
3278
- const [r, g, b] = RGBA3.fromHex(hex).toInts();
3279
- return RGBA3.fromInts(r, g, b, a);
2894
+ const [r, g, b] = RGBA2.fromHex(hex).toInts();
2895
+ return RGBA2.fromInts(r, g, b, a);
3280
2896
  }
3281
2897
  function asciiFleetColor(char, row, alpha) {
3282
2898
  if (char === "@" || char === "$" || char === "o")
@@ -3284,7 +2900,7 @@ function asciiFleetColor(char, row, alpha) {
3284
2900
  if (char === "%" || char === "!" || char === "/" || char === "\\" || char === "|")
3285
2901
  return withAlpha(RIG_UI.cyan, alpha);
3286
2902
  if (char === "." || char === "'" || char === "_" || row < 3 || row > FLEET_GRID_HEIGHT - 4) {
3287
- return RGBA3.fromInts(108, 110, 121, Math.min(170, Math.max(0, Math.min(255, Math.round(alpha * 255)))));
2903
+ return RGBA2.fromInts(108, 110, 121, Math.min(170, Math.max(0, Math.min(255, Math.round(alpha * 255)))));
3288
2904
  }
3289
2905
  return withAlpha(RIG_UI.limeDim, alpha);
3290
2906
  }
@@ -3397,16 +3013,67 @@ function sparklineString(values, width) {
3397
3013
  }
3398
3014
 
3399
3015
  // packages/cli/src/app-opentui/render/text.ts
3400
- import { RGBA as RGBA4, TextAttributes as TextAttributes4, TextRenderable } from "@opentui/core";
3401
- var TRANSPARENT2 = RGBA4.fromInts(0, 0, 0, 0);
3016
+ import { RGBA as RGBA3, TextAttributes as TextAttributes3, TextRenderable } from "@opentui/core";
3017
+
3018
+ // packages/cli/src/app-opentui/render/hover.ts
3019
+ var hoveredId;
3020
+ var listeners = new Set;
3021
+ function isHovered(id) {
3022
+ return id !== undefined && id === hoveredId;
3023
+ }
3024
+ function setHoveredSelectableId(id) {
3025
+ if (hoveredId === id)
3026
+ return;
3027
+ hoveredId = id;
3028
+ for (const listener of listeners)
3029
+ listener();
3030
+ }
3031
+ function clearHoveredSelectableId(id) {
3032
+ if (id !== undefined && hoveredId === id)
3033
+ setHoveredSelectableId(undefined);
3034
+ }
3035
+ function subscribeHover(listener) {
3036
+ listeners.add(listener);
3037
+ return () => {
3038
+ listeners.delete(listener);
3039
+ };
3040
+ }
3041
+
3042
+ // packages/cli/src/app-opentui/render/text.ts
3043
+ var TRANSPARENT2 = RGBA3.fromInts(0, 0, 0, 0);
3044
+ var HOVER_BG = RGBA3.fromHex(RIG_UI.hover);
3045
+ function lineIsClickable(line2) {
3046
+ return line2?.selectable !== undefined || line2?.selectableIndex !== undefined;
3047
+ }
3048
+ function lineSelectableId(line2) {
3049
+ return line2?.selectable?.id ?? line2?.selectableId;
3050
+ }
3051
+ function lineBackground(line2) {
3052
+ if (line2?.bg)
3053
+ return RGBA3.fromHex(line2.bg);
3054
+ const id = lineSelectableId(line2);
3055
+ if (id !== undefined && isHovered(id))
3056
+ return HOVER_BG;
3057
+ return TRANSPARENT2;
3058
+ }
3402
3059
  function selectableMouseHandler(currentLineRef, onLineMouseDown) {
3403
3060
  return (event) => {
3404
3061
  const currentLine = currentLineRef();
3405
- if (currentLine?.selectableIndex === undefined)
3062
+ if (!lineIsClickable(currentLine))
3406
3063
  return;
3407
3064
  onLineMouseDown?.(currentLine, event);
3408
3065
  };
3409
3066
  }
3067
+ function hoverHandlers(currentLineRef) {
3068
+ return {
3069
+ onMouseOver: () => {
3070
+ const id = lineSelectableId(currentLineRef());
3071
+ if (id !== undefined)
3072
+ setHoveredSelectableId(id);
3073
+ },
3074
+ onMouseOut: () => clearHoveredSelectableId(lineSelectableId(currentLineRef()))
3075
+ };
3076
+ }
3410
3077
  function createTextLine(renderer, id, top, onLineMouseDown) {
3411
3078
  let currentLine;
3412
3079
  const renderable = new TextRenderable(renderer, {
@@ -3418,7 +3085,8 @@ function createTextLine(renderer, id, top, onLineMouseDown) {
3418
3085
  width: 1,
3419
3086
  fg: RIG_UI.ink2,
3420
3087
  selectable: true,
3421
- onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
3088
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown),
3089
+ ...hoverHandlers(() => currentLine)
3422
3090
  });
3423
3091
  renderable.setRigSceneLine = (line2) => {
3424
3092
  currentLine = line2;
@@ -3435,7 +3103,8 @@ function createFlowTextLine(renderer, id, onLineMouseDown) {
3435
3103
  flexShrink: 0,
3436
3104
  fg: RIG_UI.ink2,
3437
3105
  selectable: true,
3438
- onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
3106
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown),
3107
+ ...hoverHandlers(() => currentLine)
3439
3108
  });
3440
3109
  renderable.setRigSceneLine = (line2) => {
3441
3110
  currentLine = line2;
@@ -3449,8 +3118,8 @@ function applyTextLine(renderable, line2, top, left, width) {
3449
3118
  renderable.width = width;
3450
3119
  renderable.content = line2?.styledText ?? line2?.text ?? "";
3451
3120
  renderable.fg = line2?.fg ?? RIG_UI.ink2;
3452
- renderable.bg = line2?.bg ?? TRANSPARENT2;
3453
- renderable.attributes = line2?.bold ? TextAttributes4.BOLD : line2?.dim ? TextAttributes4.DIM : 0;
3121
+ renderable.bg = lineBackground(line2);
3122
+ renderable.attributes = line2?.bold ? TextAttributes3.BOLD : line2?.dim ? TextAttributes3.DIM : 0;
3454
3123
  }
3455
3124
  function applyFlowTextLine(renderable, line2, width) {
3456
3125
  renderable.setRigSceneLine?.(line2);
@@ -3459,8 +3128,8 @@ function applyFlowTextLine(renderable, line2, width) {
3459
3128
  renderable.width = Math.max(1, width);
3460
3129
  renderable.content = line2?.styledText ?? line2?.text ?? "";
3461
3130
  renderable.fg = line2?.fg ?? RIG_UI.ink2;
3462
- renderable.bg = line2?.bg ?? TRANSPARENT2;
3463
- renderable.attributes = line2?.bold ? TextAttributes4.BOLD : line2?.dim ? TextAttributes4.DIM : 0;
3131
+ renderable.bg = lineBackground(line2);
3132
+ renderable.attributes = line2?.bold ? TextAttributes3.BOLD : line2?.dim ? TextAttributes3.DIM : 0;
3464
3133
  }
3465
3134
  function clearTextLines(renderables, from = 0) {
3466
3135
  for (let index = from;index < renderables.length; index += 1) {
@@ -3474,9 +3143,20 @@ function clearTextLines(renderables, from = 0) {
3474
3143
  }
3475
3144
  }
3476
3145
 
3146
+ // packages/cli/src/app-opentui/render/terminal-handoff.ts
3147
+ function resumeRendererClean(renderer) {
3148
+ try {
3149
+ renderer.pendingSuspendedTerminalSetup = true;
3150
+ } catch {}
3151
+ renderer.resume();
3152
+ try {
3153
+ renderer.requestRender?.();
3154
+ } catch {}
3155
+ }
3156
+
3477
3157
  // packages/cli/src/app-opentui/render/panels.ts
3478
- import { RGBA as RGBA5, ScrollBoxRenderable } from "@opentui/core";
3479
- var TRANSPARENT3 = RGBA5.fromInts(0, 0, 0, 0);
3158
+ import { RGBA as RGBA4, ScrollBoxRenderable } from "@opentui/core";
3159
+ var TRANSPARENT3 = RGBA4.fromInts(0, 0, 0, 0);
3480
3160
  var MAX_PANEL_LINES = 420;
3481
3161
  var PANEL_OPAQUE_ALPHA = 255;
3482
3162
  var PANEL_BORDER = hexToRgba(RIG_UI.border, 255);
@@ -3485,8 +3165,8 @@ function hexToRgba(hex, alpha) {
3485
3165
  const full = clean.length === 3 ? clean.split("").map((part) => `${part}${part}`).join("") : clean;
3486
3166
  const value = Number.parseInt(full, 16);
3487
3167
  if (!Number.isFinite(value))
3488
- return RGBA5.fromInts(14, 15, 17, alpha);
3489
- return RGBA5.fromInts(value >> 16 & 255, value >> 8 & 255, value & 255, alpha);
3168
+ return RGBA4.fromInts(14, 15, 17, alpha);
3169
+ return RGBA4.fromInts(value >> 16 & 255, value >> 8 & 255, value & 255, alpha);
3490
3170
  }
3491
3171
  function panelBackground(panel) {
3492
3172
  return hexToRgba(panel.backgroundColor ?? RIG_UI.panel, PANEL_OPAQUE_ALPHA);
@@ -3601,9 +3281,9 @@ function applyScrollPanels(panels, layout, scenePanels) {
3601
3281
  }
3602
3282
 
3603
3283
  // packages/cli/src/app-opentui/render/type-bar.ts
3604
- import { BoxRenderable, InputRenderable, InputRenderableEvents, RGBA as RGBA6, StyledText as StyledText3, TextRenderable as TextRenderable2 } from "@opentui/core";
3605
- var TYPEBAR_BG = RGBA6.fromInts(20, 25, 14, 224);
3606
- var TYPEBAR_BORDER = RGBA6.fromInts(204, 255, 77, 92);
3284
+ import { BoxRenderable, InputRenderable, InputRenderableEvents, RGBA as RGBA5, StyledText as StyledText2, TextRenderable as TextRenderable2 } from "@opentui/core";
3285
+ var TYPEBAR_BG = RGBA5.fromInts(20, 25, 14, 224);
3286
+ var TYPEBAR_BORDER = RGBA5.fromInts(204, 255, 77, 92);
3607
3287
  function createTypeBar(renderer) {
3608
3288
  const background = new BoxRenderable(renderer, {
3609
3289
  id: "typebar-card",
@@ -3751,7 +3431,7 @@ function formatFooter(footer, width) {
3751
3431
  chunks.push(cell.style(text));
3752
3432
  used += visibleWidth(text);
3753
3433
  });
3754
- return new StyledText3(chunks);
3434
+ return new StyledText2(chunks);
3755
3435
  }
3756
3436
 
3757
3437
  // packages/cli/src/app-opentui/render/native-host.ts
@@ -3759,7 +3439,7 @@ import {
3759
3439
  BoxRenderable as BoxRenderable2,
3760
3440
  CodeRenderable,
3761
3441
  DiffRenderable,
3762
- RGBA as RGBA7,
3442
+ RGBA as RGBA6,
3763
3443
  ScrollBoxRenderable as ScrollBoxRenderable2,
3764
3444
  SyntaxStyle,
3765
3445
  TextRenderable as TextRenderable3,
@@ -3770,19 +3450,19 @@ function rigSyntaxStyle() {
3770
3450
  if (syntaxStyle)
3771
3451
  return syntaxStyle;
3772
3452
  syntaxStyle = SyntaxStyle.fromStyles({
3773
- keyword: { fg: RGBA7.fromHex(RIG_UI.magenta), bold: true },
3774
- string: { fg: RGBA7.fromHex(RIG_UI.lime) },
3775
- number: { fg: RGBA7.fromHex(RIG_UI.cyan) },
3776
- comment: { fg: RGBA7.fromHex(RIG_UI.ink4), italic: true },
3777
- function: { fg: RGBA7.fromHex(RIG_UI.cyan) },
3778
- type: { fg: RGBA7.fromHex(RIG_UI.limeDim) },
3779
- constant: { fg: RGBA7.fromHex(RIG_UI.yellow) },
3780
- default: { fg: RGBA7.fromHex(RIG_UI.ink2) }
3453
+ keyword: { fg: RGBA6.fromHex(RIG_UI.magenta), bold: true },
3454
+ string: { fg: RGBA6.fromHex(RIG_UI.lime) },
3455
+ number: { fg: RGBA6.fromHex(RIG_UI.cyan) },
3456
+ comment: { fg: RGBA6.fromHex(RIG_UI.ink4), italic: true },
3457
+ function: { fg: RGBA6.fromHex(RIG_UI.cyan) },
3458
+ type: { fg: RGBA6.fromHex(RIG_UI.limeDim) },
3459
+ constant: { fg: RGBA6.fromHex(RIG_UI.yellow) },
3460
+ default: { fg: RGBA6.fromHex(RIG_UI.ink2) }
3781
3461
  });
3782
3462
  return syntaxStyle;
3783
3463
  }
3784
3464
  function tableContent(rows) {
3785
- return rows.map((row, rowIndex) => row.map((cell) => [{ __isChunk: true, text: cell, fg: RGBA7.fromHex(rowIndex === 0 ? RIG_UI.ink3 : RIG_UI.ink2) }]));
3465
+ return rows.map((row, rowIndex) => row.map((cell) => [{ __isChunk: true, text: cell, fg: RGBA6.fromHex(rowIndex === 0 ? RIG_UI.ink3 : RIG_UI.ink2) }]));
3786
3466
  }
3787
3467
  function createNativeHost(renderer) {
3788
3468
  try {
@@ -4272,7 +3952,7 @@ function renderMainScene(state, layout) {
4272
3952
  var MAX_SCENE_LINES = 200;
4273
3953
  var MAX_SCENE_PANELS = 5;
4274
3954
  var ANIMATION_SLOWDOWN = 1;
4275
- var PRELOADER_BACKDROP = RGBA8.fromHex(RIG_UI.bg);
3955
+ var PRELOADER_BACKDROP = RGBA7.fromHex(RIG_UI.bg);
4276
3956
  function inboxPendingCount(state) {
4277
3957
  const inbox = state.data.inbox;
4278
3958
  if (!inbox || typeof inbox !== "object" || Array.isArray(inbox))
@@ -4477,7 +4157,7 @@ function buildNavStrip(state) {
4477
4157
  chunks.push(otuiBold(styles.yellow(String(badgeCount))));
4478
4158
  }
4479
4159
  });
4480
- return new StyledText4(chunks);
4160
+ return new StyledText3(chunks);
4481
4161
  }
4482
4162
  function requestRender(renderer) {
4483
4163
  renderer.requestRender?.();
@@ -4675,7 +4355,8 @@ async function launchRigOpenTuiApp(options) {
4675
4355
  },
4676
4356
  suspend: () => renderer?.suspend(),
4677
4357
  resume: () => {
4678
- renderer?.resume();
4358
+ if (renderer)
4359
+ resumeRendererClean(renderer);
4679
4360
  renderApp();
4680
4361
  },
4681
4362
  destroy: () => renderer?.destroy()
@@ -4782,8 +4463,7 @@ async function launchRigOpenTuiApp(options) {
4782
4463
  } else if (!selectById(store, id, renderedSelectableItems)) {
4783
4464
  return;
4784
4465
  }
4785
- if (line2.activateOnClick)
4786
- runAppAction("Activate selection", () => activateSelection(runtime, renderedSelectableItems));
4466
+ runAppAction("Activate selection", () => activateSelection(runtime, renderedSelectableItems));
4787
4467
  };
4788
4468
  for (let index = 0;index < MAX_SCENE_PANELS; index += 1) {
4789
4469
  const panel = createScrollPanelLayer(renderer, `rig-scroll-panel-${index}`, onLineClick);
@@ -4850,6 +4530,7 @@ async function launchRigOpenTuiApp(options) {
4850
4530
  };
4851
4531
  renderer.keyInput.on("keypress", onKeyPress);
4852
4532
  resources.add(() => renderer?.keyInput.off("keypress", onKeyPress));
4533
+ resources.add(subscribeHover(() => scheduleAppRender(0)));
4853
4534
  const onPaste = (event) => {
4854
4535
  const state = store.getState();
4855
4536
  if (state.scene === "handoff") {