@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
@@ -39,6 +39,7 @@ var RIG_UI = {
39
39
  bg2: "#0b0c0e",
40
40
  panel: "#101115",
41
41
  panel2: "#14161b",
42
+ hover: "#181b24",
42
43
  glass: "#1e2230",
43
44
  border: "#2a2e3a",
44
45
  ink: "#f4f5f8",
@@ -43,6 +43,7 @@ var RIG_UI = {
43
43
  bg2: "#0b0c0e",
44
44
  panel: "#101115",
45
45
  panel2: "#14161b",
46
+ hover: "#181b24",
46
47
  glass: "#1e2230",
47
48
  border: "#2a2e3a",
48
49
  ink: "#f4f5f8",
@@ -224,7 +225,7 @@ function formatFooter(footer, width) {
224
225
  }
225
226
 
226
227
  // packages/cli/src/app-opentui/runtime.ts
227
- import { BoxRenderable as BoxRenderable3, RGBA as RGBA8, StyledText as StyledText4, TextRenderable as TextRenderable4, createCliRenderer } from "@opentui/core";
228
+ import { BoxRenderable as BoxRenderable3, RGBA as RGBA7, StyledText as StyledText3, TextRenderable as TextRenderable4, createCliRenderer } from "@opentui/core";
228
229
 
229
230
  // packages/cli/src/app-opentui/command-pty-host.ts
230
231
  import { basename } from "path";
@@ -876,389 +877,6 @@ var HOLLOW_FAMILIES = new Set([
876
877
  "test"
877
878
  ]);
878
879
 
879
- // packages/cli/src/app-opentui/pi-pty-host.ts
880
- import { fileURLToPath as fileURLToPath2 } from "url";
881
- import { basename as basename2 } from "path";
882
- import { RGBA as RGBA2, StyledText as StyledText2, TextAttributes as TextAttributes2 } from "@opentui/core";
883
- import { Terminal as XtermTerminal2 } from "@xterm/headless";
884
- var MIN_COLS2 = 40;
885
- var MIN_ROWS2 = 12;
886
- var MAX_ROWS2 = 300;
887
- var MAX_SNAPSHOT_LINES2 = 360;
888
- var STYLED_SNAPSHOT_MARGIN = 6;
889
- var SNAPSHOT_DELAY_MS2 = 120;
890
- var fallbackChildScriptPath = fileURLToPath2(new URL("./pi-host-child.ts", import.meta.url));
891
- var activeHost2 = null;
892
- function clampCols2(cols) {
893
- return Math.max(MIN_COLS2, Math.trunc(cols || 100));
894
- }
895
- function clampRows2(rows) {
896
- return Math.max(MIN_ROWS2, Math.min(MAX_ROWS2, Math.trunc(rows || 35)));
897
- }
898
- var XTERM_COLOR_MODE_INDEXED_16 = 16777216;
899
- var XTERM_COLOR_MODE_INDEXED_256 = 33554432;
900
- var XTERM_COLOR_MODE_RGB = 50331648;
901
- function rgbaFromXtermColor(mode, value) {
902
- if (mode === 1 || mode === 2 || mode === XTERM_COLOR_MODE_INDEXED_16 || mode === XTERM_COLOR_MODE_INDEXED_256) {
903
- return RGBA2.fromIndex(value);
904
- }
905
- if (mode === 3 || mode === XTERM_COLOR_MODE_RGB) {
906
- return RGBA2.fromInts(value >> 16 & 255, value >> 8 & 255, value & 255);
907
- }
908
- return;
909
- }
910
- function textAttributesFromCell(cell) {
911
- let attributes = TextAttributes2.NONE;
912
- if (cell.isBold())
913
- attributes |= TextAttributes2.BOLD;
914
- if (cell.isDim())
915
- attributes |= TextAttributes2.DIM;
916
- if (cell.isItalic())
917
- attributes |= TextAttributes2.ITALIC;
918
- if (cell.isUnderline())
919
- attributes |= TextAttributes2.UNDERLINE;
920
- if (cell.isBlink())
921
- attributes |= TextAttributes2.BLINK;
922
- if (cell.isInverse())
923
- attributes |= TextAttributes2.INVERSE;
924
- if (cell.isInvisible())
925
- attributes |= TextAttributes2.HIDDEN;
926
- if (cell.isStrikethrough())
927
- attributes |= TextAttributes2.STRIKETHROUGH;
928
- return attributes;
929
- }
930
- function sameRgba(a, b) {
931
- if (!a && !b)
932
- return true;
933
- return Boolean(a && b && a.equals(b));
934
- }
935
- function sameStyle(a, b) {
936
- return sameRgba(a.fg, b.fg) && sameRgba(a.bg, b.bg) && (a.attributes ?? 0) === (b.attributes ?? 0);
937
- }
938
- function styleFromCell(cell) {
939
- return {
940
- fg: rgbaFromXtermColor(cell.getFgColorMode(), cell.getFgColor()),
941
- bg: rgbaFromXtermColor(cell.getBgColorMode(), cell.getBgColor()),
942
- attributes: textAttributesFromCell(cell)
943
- };
944
- }
945
- function lineToStyledText(line, cols) {
946
- if (!line)
947
- return new StyledText2([{ __isChunk: true, text: "" }]);
948
- const chunks = [];
949
- let run = "";
950
- let runStyle = null;
951
- const flush = () => {
952
- if (!run)
953
- return;
954
- chunks.push({
955
- __isChunk: true,
956
- text: run,
957
- ...runStyle?.fg ? { fg: runStyle.fg } : {},
958
- ...runStyle?.bg ? { bg: runStyle.bg } : {},
959
- ...(runStyle?.attributes ?? 0) !== 0 ? { attributes: runStyle.attributes } : {}
960
- });
961
- run = "";
962
- };
963
- for (let index = 0;index < cols; index += 1) {
964
- const cell = line.getCell(index);
965
- if (!cell) {
966
- if (runStyle !== null)
967
- flush();
968
- runStyle = null;
969
- run += " ";
970
- continue;
971
- }
972
- if (cell.getWidth() === 0)
973
- continue;
974
- const style = styleFromCell(cell);
975
- if (!runStyle || !sameStyle(runStyle, style)) {
976
- flush();
977
- runStyle = style;
978
- }
979
- run += cell.getChars() || " ";
980
- }
981
- flush();
982
- return new StyledText2(chunks.length > 0 ? chunks : [{ __isChunk: true, text: "" }]);
983
- }
984
- function childCommandPrefix2() {
985
- const execName = basename2(process.execPath).toLowerCase();
986
- const currentEntry = process.argv[1];
987
- if (execName === "bun" || execName === "bun.exe") {
988
- return currentEntry ? [process.execPath, currentEntry, "__opentui-pi-host"] : [process.execPath, fallbackChildScriptPath];
989
- }
990
- return [process.execPath, "__opentui-pi-host"];
991
- }
992
- function withEnv2(base) {
993
- const env = {};
994
- for (const [key, value] of Object.entries(base ?? process.env)) {
995
- if (key === "RIG_PLAIN" || key === "RIG_CLI_PLAIN_HELP" || key === "NO_COLOR")
996
- continue;
997
- if (typeof value === "string")
998
- env[key] = value;
999
- }
1000
- return {
1001
- ...env,
1002
- TERM: "xterm-256color",
1003
- COLORTERM: "truecolor",
1004
- FORCE_COLOR: env.FORCE_COLOR ?? "1",
1005
- RIG_OPENTUI_PI_HOST: "1"
1006
- };
1007
- }
1008
- class PiPtyHost {
1009
- runId;
1010
- projectRoot;
1011
- onSnapshot;
1012
- onExit;
1013
- onError;
1014
- terminal;
1015
- disposables = [];
1016
- decoder = new TextDecoder("utf-8");
1017
- proc = null;
1018
- pty = null;
1019
- status = "starting";
1020
- cols;
1021
- rows;
1022
- message = "starting bundled Pi";
1023
- lastResizeError = null;
1024
- exitCode;
1025
- signal;
1026
- notifyTimer = null;
1027
- lastStreamKey = "";
1028
- _disposed = false;
1029
- constructor(options) {
1030
- this.runId = options.runId;
1031
- this.projectRoot = options.projectRoot;
1032
- this.cols = clampCols2(options.cols);
1033
- this.rows = clampRows2(options.rows);
1034
- this.onSnapshot = options.onSnapshot;
1035
- this.onExit = options.onExit;
1036
- this.onError = options.onError;
1037
- this.terminal = new XtermTerminal2({
1038
- allowProposedApi: true,
1039
- cols: this.cols,
1040
- rows: this.rows,
1041
- scrollback: 1000
1042
- });
1043
- this.registerTerminalResponders();
1044
- this.disposables.push(this.terminal.onWriteParsed(() => {
1045
- if (this._disposed)
1046
- return;
1047
- const snapshot = this.createSnapshot();
1048
- const key = snapshot.lines.join(`
1049
- `);
1050
- if (key === this.lastStreamKey)
1051
- return;
1052
- this.lastStreamKey = key;
1053
- this.onSnapshot?.(snapshot);
1054
- }));
1055
- }
1056
- get disposed() {
1057
- return this._disposed;
1058
- }
1059
- get snapshot() {
1060
- return this.createSnapshot();
1061
- }
1062
- async start() {
1063
- if (this._disposed)
1064
- throw new Error("Pi PTY host is disposed.");
1065
- if (typeof Bun.Terminal !== "function") {
1066
- throw new Error("Bun native PTY is unavailable in this runtime. Pi host requires Bun.Terminal.");
1067
- }
1068
- const spawnOptions = {
1069
- cwd: this.projectRoot,
1070
- env: withEnv2(process.env),
1071
- terminal: {
1072
- cols: this.cols,
1073
- rows: this.rows,
1074
- name: "xterm-256color",
1075
- data: (_terminal, data) => this.handlePtyData(data)
1076
- }
1077
- };
1078
- const proc = Bun.spawn([
1079
- ...childCommandPrefix2(),
1080
- "--run-id",
1081
- this.runId,
1082
- "--project-root",
1083
- this.projectRoot
1084
- ], spawnOptions);
1085
- if (!proc.terminal)
1086
- throw new Error("Bun did not attach a terminal to the bundled Pi child process.");
1087
- this.proc = proc;
1088
- this.pty = proc.terminal;
1089
- this.status = "running";
1090
- this.message = "bundled Pi running inside this app";
1091
- this.emitSnapshotSoon(0);
1092
- proc.exited.then((exitCode) => {
1093
- if (this._disposed)
1094
- return;
1095
- this.status = exitCode === 0 ? "exited" : "failed";
1096
- this.exitCode = exitCode;
1097
- this.signal = null;
1098
- this.message = exitCode === 0 ? "bundled Pi exited" : `bundled Pi exited with code ${exitCode}`;
1099
- const snapshot = this.createSnapshot();
1100
- this.onSnapshot?.(snapshot);
1101
- this.onExit?.(snapshot);
1102
- if (activeHost2 === this)
1103
- activeHost2 = null;
1104
- this.dispose("exit", { kill: false, notify: false });
1105
- }).catch((error) => {
1106
- if (this._disposed)
1107
- return;
1108
- this.status = "failed";
1109
- this.message = error instanceof Error ? error.message : String(error);
1110
- const snapshot = this.createSnapshot();
1111
- this.onSnapshot?.(snapshot);
1112
- this.onError?.(error, snapshot);
1113
- if (activeHost2 === this)
1114
- activeHost2 = null;
1115
- this.dispose("error", { kill: false, notify: false });
1116
- });
1117
- }
1118
- write(data) {
1119
- if (this._disposed || !this.pty)
1120
- return;
1121
- try {
1122
- this.pty.write(data);
1123
- } catch (error) {
1124
- this.status = "failed";
1125
- this.message = error instanceof Error ? error.message : String(error);
1126
- const snapshot = this.createSnapshot();
1127
- this.onSnapshot?.(snapshot);
1128
- this.onError?.(error, snapshot);
1129
- }
1130
- }
1131
- resize(cols, rows) {
1132
- const nextCols = clampCols2(cols);
1133
- const nextRows = clampRows2(rows);
1134
- if (nextCols === this.cols && nextRows === this.rows)
1135
- return;
1136
- this.cols = nextCols;
1137
- this.rows = nextRows;
1138
- this.terminal.resize(nextCols, nextRows);
1139
- try {
1140
- this.pty?.resize(nextCols, nextRows);
1141
- this.lastResizeError = null;
1142
- } catch (error) {
1143
- this.lastResizeError = error instanceof Error ? error.message : String(error);
1144
- }
1145
- this.emitSnapshotSoon(0);
1146
- }
1147
- detach() {
1148
- this.dispose("detach");
1149
- return this.createSnapshot("detached from bundled Pi");
1150
- }
1151
- dispose(reason = "dispose", options = {}) {
1152
- if (this._disposed)
1153
- return;
1154
- this._disposed = true;
1155
- if (this.notifyTimer)
1156
- clearTimeout(this.notifyTimer);
1157
- this.notifyTimer = null;
1158
- for (const disposable of this.disposables.splice(0)) {
1159
- try {
1160
- disposable.dispose();
1161
- } catch {}
1162
- }
1163
- if (options.kill !== false) {
1164
- try {
1165
- this.proc?.kill("SIGTERM");
1166
- } catch {}
1167
- }
1168
- try {
1169
- this.pty?.close();
1170
- } catch {}
1171
- try {
1172
- this.terminal.dispose();
1173
- } catch {}
1174
- if (activeHost2 === this)
1175
- activeHost2 = null;
1176
- if (options.notify) {
1177
- this.message = reason;
1178
- this.onSnapshot?.(this.createSnapshot(reason));
1179
- }
1180
- }
1181
- handlePtyData(data) {
1182
- if (this._disposed)
1183
- return;
1184
- const text = this.decoder.decode(data, { stream: true });
1185
- this.respondToRawTerminalQueries(text);
1186
- this.terminal.write(data);
1187
- }
1188
- emitSnapshotSoon(delayMs = SNAPSHOT_DELAY_MS2) {
1189
- if (this._disposed || this.notifyTimer)
1190
- return;
1191
- this.notifyTimer = setTimeout(() => {
1192
- this.notifyTimer = null;
1193
- if (this._disposed)
1194
- return;
1195
- this.onSnapshot?.(this.createSnapshot());
1196
- }, delayMs);
1197
- }
1198
- createSnapshot(message = this.message) {
1199
- const buffer = this.terminal.buffer.active;
1200
- const end = buffer.length;
1201
- const start = Math.max(0, end - MAX_SNAPSHOT_LINES2);
1202
- const styledStart = Math.max(start, end - this.rows - STYLED_SNAPSHOT_MARGIN);
1203
- const lines = [];
1204
- const styledLines = [];
1205
- for (let row = start;row < end; row += 1) {
1206
- const line = buffer.getLine(row);
1207
- lines.push((line?.translateToString(false) ?? "").slice(0, this.cols));
1208
- if (row >= styledStart)
1209
- styledLines[lines.length - 1] = lineToStyledText(line, this.cols);
1210
- }
1211
- while (lines.length < this.rows) {
1212
- lines.push("");
1213
- styledLines[lines.length - 1] = new StyledText2([{ __isChunk: true, text: "" }]);
1214
- }
1215
- const resolvedMessage = this.lastResizeError ? `resize degraded: ${this.lastResizeError}` : message;
1216
- return {
1217
- runId: this.runId,
1218
- status: this.status,
1219
- cols: this.cols,
1220
- rows: this.rows,
1221
- lines,
1222
- styledLines,
1223
- message: resolvedMessage,
1224
- ...this.lastResizeError ? { resizeError: this.lastResizeError } : {},
1225
- ...this.exitCode !== undefined ? { exitCode: this.exitCode } : {},
1226
- ...this.signal !== undefined ? { signal: this.signal } : {}
1227
- };
1228
- }
1229
- registerTerminalResponders() {
1230
- this.disposables.push(this.terminal.parser.registerCsiHandler({ final: "c" }, (params) => {
1231
- if (params.length === 0 || params[0] === 0)
1232
- this.write("\x1B[?62;22c");
1233
- return false;
1234
- }));
1235
- this.disposables.push(this.terminal.parser.registerCsiHandler({ prefix: ">", final: "c" }, (params) => {
1236
- if (params.length === 0 || params[0] === 0)
1237
- this.write("\x1B[>0;0;0c");
1238
- return false;
1239
- }));
1240
- this.disposables.push(this.terminal.parser.registerCsiHandler({ final: "n" }, (params) => {
1241
- if (params[0] === 5) {
1242
- this.write("\x1B[0n");
1243
- } else if (params[0] === 6) {
1244
- const row = this.terminal.buffer.active.cursorY + 1;
1245
- const col = this.terminal.buffer.active.cursorX + 1;
1246
- this.write(`\x1B[${row};${col}R`);
1247
- }
1248
- return false;
1249
- }));
1250
- }
1251
- respondToRawTerminalQueries(text) {
1252
- if (!text)
1253
- return;
1254
- const decrqm = /\x1b\[\?(\d+)\$p/g;
1255
- let match;
1256
- while ((match = decrqm.exec(text)) !== null) {
1257
- this.write(`\x1B[?${match[1]};2$y`);
1258
- }
1259
- }
1260
- }
1261
-
1262
880
  // packages/cli/src/commands/_server-events.ts
1263
881
  import { WsTransport } from "@rig/client";
1264
882
  import { RIG_WS_CHANNELS } from "@rig/contracts";
@@ -1286,19 +904,19 @@ var RESUMABLE_RUN_STATUSES = new Set([
1286
904
  ]);
1287
905
 
1288
906
  // packages/cli/src/app-opentui/drone.ts
1289
- import { RGBA as RGBA3, StyledText as StyledText3, TextAttributes as TextAttributes3 } from "@opentui/core";
907
+ import { RGBA as RGBA2, StyledText as StyledText2, TextAttributes as TextAttributes2 } from "@opentui/core";
1290
908
  var COLOR = {
1291
- body: RGBA3.fromHex(RIG_UI.lime),
1292
- mini: RGBA3.fromHex(RIG_UI.limeDim),
1293
- rotor: RGBA3.fromHex(RIG_UI.cyan),
1294
- path: RGBA3.fromHex(RIG_UI.cyan),
1295
- eye: RGBA3.fromHex(RIG_UI.ink),
1296
- dim: RGBA3.fromHex(RIG_UI.ink4),
1297
- ink: RGBA3.fromHex(RIG_UI.ink2)
909
+ body: RGBA2.fromHex(RIG_UI.lime),
910
+ mini: RGBA2.fromHex(RIG_UI.limeDim),
911
+ rotor: RGBA2.fromHex(RIG_UI.cyan),
912
+ path: RGBA2.fromHex(RIG_UI.cyan),
913
+ eye: RGBA2.fromHex(RIG_UI.ink),
914
+ dim: RGBA2.fromHex(RIG_UI.ink4),
915
+ ink: RGBA2.fromHex(RIG_UI.ink2)
1298
916
  };
1299
917
 
1300
918
  // packages/cli/src/app-opentui/render/graphics.ts
1301
- import { FrameBufferRenderable, RGBA as RGBA4 } from "@opentui/core";
919
+ import { FrameBufferRenderable, RGBA as RGBA3 } from "@opentui/core";
1302
920
 
1303
921
  // packages/cli/src/app-opentui/render/constants.ts
1304
922
  var LCG_MULTIPLIER = 1664525;
@@ -1335,13 +953,13 @@ var GLOW_FALLOFF_EXP_ASCII = 2.2;
1335
953
  // packages/cli/src/app-opentui/render/graphics.ts
1336
954
  var BRAILLE_SAMPLES_X = 2;
1337
955
  var BRAILLE_SAMPLES_Y = 4;
1338
- var TRANSPARENT = RGBA4.fromValues(0, 0, 0, 0);
1339
- var BACKDROP = RGBA4.fromHex(RIG_UI.bg);
1340
- var PANEL_BG = RGBA4.fromInts(16, 17, 21, 184);
1341
- var PANEL_HEADER_BG = RGBA4.fromInts(16, 17, 21, 188);
1342
- var PANEL_LINE = RGBA4.fromInts(255, 255, 255, 20);
1343
- var PANEL_LINE_DIM = RGBA4.fromInts(255, 255, 255, 8);
1344
- var PANEL_TEXT_DIM = RGBA4.fromInts(108, 110, 121, 255);
956
+ var TRANSPARENT = RGBA3.fromValues(0, 0, 0, 0);
957
+ var BACKDROP = RGBA3.fromHex(RIG_UI.bg);
958
+ var PANEL_BG = RGBA3.fromInts(16, 17, 21, 184);
959
+ var PANEL_HEADER_BG = RGBA3.fromInts(16, 17, 21, 188);
960
+ var PANEL_LINE = RGBA3.fromInts(255, 255, 255, 20);
961
+ var PANEL_LINE_DIM = RGBA3.fromInts(255, 255, 255, 8);
962
+ var PANEL_TEXT_DIM = RGBA3.fromInts(108, 110, 121, 255);
1345
963
  var AC_RGB = [204, 255, 77];
1346
964
  var C2_RGB = [86, 216, 255];
1347
965
  var MG_RGB = [255, 121, 176];
@@ -1446,7 +1064,7 @@ function paletteColor(ac, c2, mg, ink) {
1446
1064
  const b = (AC_RGB[2] * ac + C2_RGB[2] * c2 + MG_RGB[2] * mg + INK_RGB[2] * ink) / total;
1447
1065
  const intensity = Math.min(1, total / 4);
1448
1066
  const lift = 0.34 + intensity * 0.66;
1449
- return RGBA4.fromInts(Math.round(r * lift), Math.round(g * lift), Math.round(b * lift), 255);
1067
+ return RGBA3.fromInts(Math.round(r * lift), Math.round(g * lift), Math.round(b * lift), 255);
1450
1068
  }
1451
1069
  function clearCanvas(canvas) {
1452
1070
  canvas.ac.fill(0);
@@ -1746,20 +1364,26 @@ var ACTIVE_STATUSES = new Set([
1746
1364
  ]);
1747
1365
 
1748
1366
  // packages/cli/src/app-opentui/render/text.ts
1749
- import { RGBA as RGBA5, TextAttributes as TextAttributes4, TextRenderable as TextRenderable2 } from "@opentui/core";
1750
- var TRANSPARENT2 = RGBA5.fromInts(0, 0, 0, 0);
1367
+ import { RGBA as RGBA4, TextAttributes as TextAttributes3, TextRenderable as TextRenderable2 } from "@opentui/core";
1368
+
1369
+ // packages/cli/src/app-opentui/render/hover.ts
1370
+ var listeners = new Set;
1371
+
1372
+ // packages/cli/src/app-opentui/render/text.ts
1373
+ var TRANSPARENT2 = RGBA4.fromInts(0, 0, 0, 0);
1374
+ var HOVER_BG = RGBA4.fromHex(RIG_UI.hover);
1751
1375
 
1752
1376
  // packages/cli/src/app-opentui/render/panels.ts
1753
- import { RGBA as RGBA6, ScrollBoxRenderable } from "@opentui/core";
1754
- var TRANSPARENT3 = RGBA6.fromInts(0, 0, 0, 0);
1377
+ import { RGBA as RGBA5, ScrollBoxRenderable } from "@opentui/core";
1378
+ var TRANSPARENT3 = RGBA5.fromInts(0, 0, 0, 0);
1755
1379
  var PANEL_BORDER = hexToRgba(RIG_UI.border, 255);
1756
1380
  function hexToRgba(hex, alpha) {
1757
1381
  const clean = hex.replace(/^#/, "");
1758
1382
  const full = clean.length === 3 ? clean.split("").map((part) => `${part}${part}`).join("") : clean;
1759
1383
  const value = Number.parseInt(full, 16);
1760
1384
  if (!Number.isFinite(value))
1761
- return RGBA6.fromInts(14, 15, 17, alpha);
1762
- return RGBA6.fromInts(value >> 16 & 255, value >> 8 & 255, value & 255, alpha);
1385
+ return RGBA5.fromInts(14, 15, 17, alpha);
1386
+ return RGBA5.fromInts(value >> 16 & 255, value >> 8 & 255, value & 255, alpha);
1763
1387
  }
1764
1388
 
1765
1389
  // packages/cli/src/app-opentui/render/native-host.ts
@@ -1767,7 +1391,7 @@ import {
1767
1391
  BoxRenderable as BoxRenderable2,
1768
1392
  CodeRenderable,
1769
1393
  DiffRenderable,
1770
- RGBA as RGBA7,
1394
+ RGBA as RGBA6,
1771
1395
  ScrollBoxRenderable as ScrollBoxRenderable2,
1772
1396
  SyntaxStyle,
1773
1397
  TextRenderable as TextRenderable3,
@@ -1775,7 +1399,7 @@ import {
1775
1399
  } from "@opentui/core";
1776
1400
 
1777
1401
  // packages/cli/src/app-opentui/runtime.ts
1778
- var PRELOADER_BACKDROP = RGBA8.fromHex(RIG_UI.bg);
1402
+ var PRELOADER_BACKDROP = RGBA7.fromHex(RIG_UI.bg);
1779
1403
  function inboxPendingCount(state) {
1780
1404
  const inbox = state.data.inbox;
1781
1405
  if (!inbox || typeof inbox !== "object" || Array.isArray(inbox))
@@ -1834,7 +1458,7 @@ function buildNavStrip(state) {
1834
1458
  chunks.push(otuiBold(styles.yellow(String(badgeCount))));
1835
1459
  }
1836
1460
  });
1837
- return new StyledText4(chunks);
1461
+ return new StyledText3(chunks);
1838
1462
  }
1839
1463
  var DESTRUCTIVE_ACTION_KINDS = new Set(["run-stop", "inbox-reject"]);
1840
1464
 
@@ -17,6 +17,7 @@ var RIG_UI = {
17
17
  bg2: "#0b0c0e",
18
18
  panel: "#101115",
19
19
  panel2: "#14161b",
20
+ hover: "#181b24",
20
21
  glass: "#1e2230",
21
22
  border: "#2a2e3a",
22
23
  ink: "#f4f5f8",
@@ -95,15 +96,60 @@ function fitSceneLines(lines, layout) {
95
96
 
96
97
  // packages/cli/src/app-opentui/render/text.ts
97
98
  import { RGBA as RGBA2, TextAttributes as TextAttributes3, TextRenderable } from "@opentui/core";
99
+
100
+ // packages/cli/src/app-opentui/render/hover.ts
101
+ var hoveredId;
102
+ var listeners = new Set;
103
+ function isHovered(id) {
104
+ return id !== undefined && id === hoveredId;
105
+ }
106
+ function setHoveredSelectableId(id) {
107
+ if (hoveredId === id)
108
+ return;
109
+ hoveredId = id;
110
+ for (const listener of listeners)
111
+ listener();
112
+ }
113
+ function clearHoveredSelectableId(id) {
114
+ if (id !== undefined && hoveredId === id)
115
+ setHoveredSelectableId(undefined);
116
+ }
117
+
118
+ // packages/cli/src/app-opentui/render/text.ts
98
119
  var TRANSPARENT = RGBA2.fromInts(0, 0, 0, 0);
120
+ var HOVER_BG = RGBA2.fromHex(RIG_UI.hover);
121
+ function lineIsClickable(line) {
122
+ return line?.selectable !== undefined || line?.selectableIndex !== undefined;
123
+ }
124
+ function lineSelectableId(line) {
125
+ return line?.selectable?.id ?? line?.selectableId;
126
+ }
127
+ function lineBackground(line) {
128
+ if (line?.bg)
129
+ return RGBA2.fromHex(line.bg);
130
+ const id = lineSelectableId(line);
131
+ if (id !== undefined && isHovered(id))
132
+ return HOVER_BG;
133
+ return TRANSPARENT;
134
+ }
99
135
  function selectableMouseHandler(currentLineRef, onLineMouseDown) {
100
136
  return (event) => {
101
137
  const currentLine = currentLineRef();
102
- if (currentLine?.selectableIndex === undefined)
138
+ if (!lineIsClickable(currentLine))
103
139
  return;
104
140
  onLineMouseDown?.(currentLine, event);
105
141
  };
106
142
  }
143
+ function hoverHandlers(currentLineRef) {
144
+ return {
145
+ onMouseOver: () => {
146
+ const id = lineSelectableId(currentLineRef());
147
+ if (id !== undefined)
148
+ setHoveredSelectableId(id);
149
+ },
150
+ onMouseOut: () => clearHoveredSelectableId(lineSelectableId(currentLineRef()))
151
+ };
152
+ }
107
153
  function createFlowTextLine(renderer, id, onLineMouseDown) {
108
154
  let currentLine;
109
155
  const renderable = new TextRenderable(renderer, {
@@ -114,7 +160,8 @@ function createFlowTextLine(renderer, id, onLineMouseDown) {
114
160
  flexShrink: 0,
115
161
  fg: RIG_UI.ink2,
116
162
  selectable: true,
117
- onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
163
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown),
164
+ ...hoverHandlers(() => currentLine)
118
165
  });
119
166
  renderable.setRigSceneLine = (line) => {
120
167
  currentLine = line;
@@ -128,7 +175,7 @@ function applyFlowTextLine(renderable, line, width) {
128
175
  renderable.width = Math.max(1, width);
129
176
  renderable.content = line?.styledText ?? line?.text ?? "";
130
177
  renderable.fg = line?.fg ?? RIG_UI.ink2;
131
- renderable.bg = line?.bg ?? TRANSPARENT;
178
+ renderable.bg = lineBackground(line);
132
179
  renderable.attributes = line?.bold ? TextAttributes3.BOLD : line?.dim ? TextAttributes3.DIM : 0;
133
180
  }
134
181
 
@@ -435,13 +482,16 @@ function lineContent(line) {
435
482
  }
436
483
  function LineView(props) {
437
484
  const { line, onLineClick } = props;
485
+ const id = lineSelectableId(line);
438
486
  return /* @__PURE__ */ jsxDEV("text", {
439
487
  style: { position: "absolute", left: props.left, top: props.top, width: props.width, zIndex: 5 },
440
488
  fg: line.fg ?? RIG_UI.ink2,
441
- bg: line.bg ?? TRANSPARENT,
489
+ bg: lineBackground(line),
442
490
  attributes: lineAttributes(line),
443
491
  content: lineContent(line),
444
- onMouseDown: onLineClick ? () => onLineClick(line) : undefined
492
+ onMouseDown: onLineClick ? () => onLineClick(line) : undefined,
493
+ onMouseOver: id !== undefined ? () => setHoveredSelectableId(id) : undefined,
494
+ onMouseOut: id !== undefined ? () => clearHoveredSelectableId(id) : undefined
445
495
  }, undefined, false, undefined, this);
446
496
  }
447
497
  function PanelHost(props) {