@h-rig/cli 0.0.6-alpha.82 → 0.0.6-alpha.84

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 (206) hide show
  1. package/dist/bin/build-rig-binaries.js +40 -8
  2. package/dist/bin/rig.js +23402 -14577
  3. package/dist/src/app/board.js +217 -41
  4. package/dist/src/app-opentui/adapters/command.d.ts +2 -0
  5. package/dist/src/app-opentui/adapters/command.js +329 -0
  6. package/dist/src/app-opentui/adapters/common.js +2 -2
  7. package/dist/src/app-opentui/adapters/doctor.d.ts +0 -2
  8. package/dist/src/app-opentui/adapters/doctor.js +64 -39
  9. package/dist/src/app-opentui/adapters/family.d.ts +62 -0
  10. package/dist/src/app-opentui/adapters/family.js +14305 -0
  11. package/dist/src/app-opentui/adapters/fleet.d.ts +0 -2
  12. package/dist/src/app-opentui/adapters/fleet.js +90 -60
  13. package/dist/src/app-opentui/adapters/inbox.d.ts +12 -2
  14. package/dist/src/app-opentui/adapters/inbox.js +137 -78
  15. package/dist/src/app-opentui/adapters/init.d.ts +0 -2
  16. package/dist/src/app-opentui/adapters/init.js +85 -47
  17. package/dist/src/app-opentui/adapters/inspect.d.ts +52 -0
  18. package/dist/src/app-opentui/adapters/inspect.js +1024 -0
  19. package/dist/src/app-opentui/adapters/pi-attach.d.ts +15 -6
  20. package/dist/src/app-opentui/adapters/pi-attach.js +442 -125
  21. package/dist/src/app-opentui/adapters/pi.d.ts +23 -0
  22. package/dist/src/app-opentui/adapters/pi.js +363 -0
  23. package/dist/src/app-opentui/adapters/plugin.d.ts +84 -0
  24. package/dist/src/app-opentui/adapters/plugin.js +544 -0
  25. package/dist/src/app-opentui/adapters/repo.d.ts +37 -0
  26. package/dist/src/app-opentui/adapters/repo.js +186 -0
  27. package/dist/src/app-opentui/adapters/run-detail.d.ts +9 -2
  28. package/dist/src/app-opentui/adapters/run-detail.js +180 -63
  29. package/dist/src/app-opentui/adapters/server.d.ts +10 -2
  30. package/dist/src/app-opentui/adapters/server.js +191 -45
  31. package/dist/src/app-opentui/adapters/tasks.d.ts +11 -2
  32. package/dist/src/app-opentui/adapters/tasks.js +1123 -143
  33. package/dist/src/app-opentui/adapters/workspace.d.ts +49 -0
  34. package/dist/src/app-opentui/adapters/workspace.js +333 -0
  35. package/dist/src/app-opentui/autocomplete.d.ts +20 -0
  36. package/dist/src/app-opentui/autocomplete.js +576 -0
  37. package/dist/src/app-opentui/bootstrap.d.ts +1 -6
  38. package/dist/src/app-opentui/bootstrap.js +25252 -16474
  39. package/dist/src/app-opentui/command-palette.d.ts +3 -0
  40. package/dist/src/app-opentui/command-palette.js +1010 -0
  41. package/dist/src/app-opentui/command-pty-host.d.ts +62 -0
  42. package/dist/src/app-opentui/command-pty-host.js +248 -0
  43. package/dist/src/app-opentui/drone.js +8 -6
  44. package/dist/src/app-opentui/events.js +1 -1
  45. package/dist/src/app-opentui/fleet-stats.d.ts +32 -0
  46. package/dist/src/app-opentui/fleet-stats.js +114 -0
  47. package/dist/src/app-opentui/focus-manager.d.ts +14 -0
  48. package/dist/src/app-opentui/focus-manager.js +24 -0
  49. package/dist/src/app-opentui/index.js +5431 -2797
  50. package/dist/src/app-opentui/intent.js +179 -50
  51. package/dist/src/app-opentui/keymap.d.ts +21 -0
  52. package/dist/src/app-opentui/keymap.js +1748 -0
  53. package/dist/src/app-opentui/launch-routing.d.ts +16 -0
  54. package/dist/src/app-opentui/launch-routing.js +55 -0
  55. package/dist/src/app-opentui/layout.d.ts +7 -0
  56. package/dist/src/app-opentui/layout.js +13 -6
  57. package/dist/src/app-opentui/list-search.d.ts +24 -0
  58. package/dist/src/app-opentui/list-search.js +88 -1
  59. package/dist/src/app-opentui/pi-host-child.js +99 -17
  60. package/dist/src/app-opentui/pi-pty-host.d.ts +14 -0
  61. package/dist/src/app-opentui/pi-pty-host.js +30 -14
  62. package/dist/src/app-opentui/react/App.d.ts +9 -0
  63. package/dist/src/app-opentui/react/App.js +5144 -0
  64. package/dist/src/app-opentui/react/Backdrop.d.ts +5 -0
  65. package/dist/src/app-opentui/react/Backdrop.js +1834 -0
  66. package/dist/src/app-opentui/react/ChromeHost.d.ts +5 -0
  67. package/dist/src/app-opentui/react/ChromeHost.js +2942 -0
  68. package/dist/src/app-opentui/react/SceneFrameView.d.ts +7 -0
  69. package/dist/src/app-opentui/react/SceneFrameView.js +529 -0
  70. package/dist/src/app-opentui/react/context.d.ts +17 -0
  71. package/dist/src/app-opentui/react/context.js +37 -0
  72. package/dist/src/app-opentui/react/launch.d.ts +2 -0
  73. package/dist/src/app-opentui/react/launch.js +5743 -0
  74. package/dist/src/app-opentui/react/nav.d.ts +18 -0
  75. package/dist/src/app-opentui/react/nav.js +54 -0
  76. package/dist/src/app-opentui/react/scroll.d.ts +12 -0
  77. package/dist/src/app-opentui/react/scroll.js +21 -0
  78. package/dist/src/app-opentui/react/syntax.d.ts +2 -0
  79. package/dist/src/app-opentui/react/syntax.js +64 -0
  80. package/dist/src/app-opentui/registry.js +20428 -4828
  81. package/dist/src/app-opentui/render/ascii-fleet.d.ts +15 -0
  82. package/dist/src/app-opentui/render/ascii-fleet.js +82 -0
  83. package/dist/src/app-opentui/render/constants.d.ts +31 -0
  84. package/dist/src/app-opentui/render/constants.js +66 -0
  85. package/dist/src/app-opentui/render/graphics.d.ts +2 -1
  86. package/dist/src/app-opentui/render/graphics.js +228 -46
  87. package/dist/src/app-opentui/render/image-visual-layer-worker.js +469 -930
  88. package/dist/src/app-opentui/render/image-visual-layer.d.ts +25 -10
  89. package/dist/src/app-opentui/render/image-visual-layer.js +448 -329
  90. package/dist/src/app-opentui/render/native-host.d.ts +37 -0
  91. package/dist/src/app-opentui/render/native-host.js +179 -0
  92. package/dist/src/app-opentui/render/panel-layout.d.ts +38 -0
  93. package/dist/src/app-opentui/render/panel-layout.js +48 -0
  94. package/dist/src/app-opentui/render/panels.d.ts +2 -0
  95. package/dist/src/app-opentui/render/panels.js +78 -38
  96. package/dist/src/app-opentui/render/preloader.d.ts +10 -0
  97. package/dist/src/app-opentui/render/preloader.js +165 -0
  98. package/dist/src/app-opentui/render/scene.d.ts +53 -1
  99. package/dist/src/app-opentui/render/scene.js +195 -6
  100. package/dist/src/app-opentui/render/text.d.ts +7 -1
  101. package/dist/src/app-opentui/render/text.js +15 -8
  102. package/dist/src/app-opentui/render/type-bar.d.ts +2 -1
  103. package/dist/src/app-opentui/render/type-bar.js +113 -39
  104. package/dist/src/app-opentui/runtime-resources.d.ts +16 -0
  105. package/dist/src/app-opentui/runtime-resources.js +62 -0
  106. package/dist/src/app-opentui/runtime.d.ts +44 -1
  107. package/dist/src/app-opentui/runtime.js +5415 -2738
  108. package/dist/src/app-opentui/scenes/command.d.ts +3 -0
  109. package/dist/src/app-opentui/scenes/command.js +117 -0
  110. package/dist/src/app-opentui/scenes/doctor.d.ts +2 -1
  111. package/dist/src/app-opentui/scenes/doctor.js +221 -17
  112. package/dist/src/app-opentui/scenes/error.js +60 -20
  113. package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +2 -0
  114. package/dist/src/app-opentui/scenes/family-domains/agent.js +348 -0
  115. package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +2 -0
  116. package/dist/src/app-opentui/scenes/family-domains/browser.js +195 -0
  117. package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +2 -0
  118. package/dist/src/app-opentui/scenes/family-domains/dist.js +243 -0
  119. package/dist/src/app-opentui/scenes/family-domains/git.d.ts +2 -0
  120. package/dist/src/app-opentui/scenes/family-domains/git.js +195 -0
  121. package/dist/src/app-opentui/scenes/family-domains/github.d.ts +2 -0
  122. package/dist/src/app-opentui/scenes/family-domains/github.js +274 -0
  123. package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +2 -0
  124. package/dist/src/app-opentui/scenes/family-domains/harness.js +152 -0
  125. package/dist/src/app-opentui/scenes/family-domains/index.d.ts +4 -0
  126. package/dist/src/app-opentui/scenes/family-domains/index.js +1679 -0
  127. package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +76 -0
  128. package/dist/src/app-opentui/scenes/family-domains/kit.js +305 -0
  129. package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +2 -0
  130. package/dist/src/app-opentui/scenes/family-domains/profile.js +212 -0
  131. package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +2 -0
  132. package/dist/src/app-opentui/scenes/family-domains/queue.js +146 -0
  133. package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +2 -0
  134. package/dist/src/app-opentui/scenes/family-domains/remote.js +518 -0
  135. package/dist/src/app-opentui/scenes/family-domains/review.d.ts +2 -0
  136. package/dist/src/app-opentui/scenes/family-domains/review.js +280 -0
  137. package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +2 -0
  138. package/dist/src/app-opentui/scenes/family-domains/setup.js +267 -0
  139. package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +2 -0
  140. package/dist/src/app-opentui/scenes/family-domains/stats.js +370 -0
  141. package/dist/src/app-opentui/scenes/family.d.ts +3 -0
  142. package/dist/src/app-opentui/scenes/family.js +2144 -0
  143. package/dist/src/app-opentui/scenes/fleet.js +552 -43
  144. package/dist/src/app-opentui/scenes/handoff.js +342 -35
  145. package/dist/src/app-opentui/scenes/help.js +640 -56
  146. package/dist/src/app-opentui/scenes/inbox.d.ts +2 -1
  147. package/dist/src/app-opentui/scenes/inbox.js +329 -21
  148. package/dist/src/app-opentui/scenes/init.d.ts +2 -1
  149. package/dist/src/app-opentui/scenes/init.js +120 -34
  150. package/dist/src/app-opentui/scenes/inspect.d.ts +3 -0
  151. package/dist/src/app-opentui/scenes/inspect.js +793 -0
  152. package/dist/src/app-opentui/scenes/main.d.ts +2 -1
  153. package/dist/src/app-opentui/scenes/main.js +264 -29
  154. package/dist/src/app-opentui/scenes/pi.d.ts +3 -0
  155. package/dist/src/app-opentui/scenes/pi.js +508 -0
  156. package/dist/src/app-opentui/scenes/plugin.d.ts +3 -0
  157. package/dist/src/app-opentui/scenes/plugin.js +486 -0
  158. package/dist/src/app-opentui/scenes/repo.d.ts +3 -0
  159. package/dist/src/app-opentui/scenes/repo.js +424 -0
  160. package/dist/src/app-opentui/scenes/run-detail.d.ts +2 -1
  161. package/dist/src/app-opentui/scenes/run-detail.js +362 -35
  162. package/dist/src/app-opentui/scenes/server.d.ts +2 -1
  163. package/dist/src/app-opentui/scenes/server.js +243 -26
  164. package/dist/src/app-opentui/scenes/tasks.js +518 -41
  165. package/dist/src/app-opentui/scenes/workspace.d.ts +3 -0
  166. package/dist/src/app-opentui/scenes/workspace.js +426 -0
  167. package/dist/src/app-opentui/selectable.d.ts +19 -0
  168. package/dist/src/app-opentui/selectable.js +79 -0
  169. package/dist/src/app-opentui/state.js +129 -36
  170. package/dist/src/app-opentui/surface-catalog.d.ts +20 -0
  171. package/dist/src/app-opentui/surface-catalog.js +540 -0
  172. package/dist/src/app-opentui/terminal-capabilities.d.ts +7 -0
  173. package/dist/src/app-opentui/terminal-capabilities.js +15 -0
  174. package/dist/src/app-opentui/theme.d.ts +28 -6
  175. package/dist/src/app-opentui/theme.js +61 -8
  176. package/dist/src/app-opentui/types.d.ts +130 -5
  177. package/dist/src/commands/_authority-runs.d.ts +1 -1
  178. package/dist/src/commands/_authority-runs.js +2 -12
  179. package/dist/src/commands/_doctor-checks.js +62 -13
  180. package/dist/src/commands/_help-catalog.js +95 -15
  181. package/dist/src/commands/_operator-view.js +97 -15
  182. package/dist/src/commands/_pi-frontend.d.ts +2 -0
  183. package/dist/src/commands/_pi-frontend.js +97 -13
  184. package/dist/src/commands/_preflight.js +64 -14
  185. package/dist/src/commands/_server-client.js +82 -18
  186. package/dist/src/commands/_server-events.d.ts +26 -0
  187. package/dist/src/commands/_server-events.js +310 -0
  188. package/dist/src/commands/_snapshot-upload.js +62 -13
  189. package/dist/src/commands/agent.js +2 -12
  190. package/dist/src/commands/connect.js +7 -1
  191. package/dist/src/commands/doctor.js +62 -13
  192. package/dist/src/commands/github.js +144 -23
  193. package/dist/src/commands/inbox.js +62 -13
  194. package/dist/src/commands/init.js +82 -18
  195. package/dist/src/commands/inspect.js +62 -13
  196. package/dist/src/commands/run.js +100 -15
  197. package/dist/src/commands/server.js +71 -26
  198. package/dist/src/commands/setup.js +62 -13
  199. package/dist/src/commands/stats.js +157 -28
  200. package/dist/src/commands/task-run-driver.js +64 -25
  201. package/dist/src/commands/task.js +196 -43
  202. package/dist/src/commands.js +419 -123
  203. package/dist/src/index.js +426 -130
  204. package/package.json +11 -10
  205. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.d.ts +0 -2
  206. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.js +0 -1484
@@ -0,0 +1,165 @@
1
+ // @bun
2
+ // packages/cli/src/app-opentui/theme.ts
3
+ import {
4
+ bold as otuiBold,
5
+ dim as otuiDim,
6
+ fg as otuiFg,
7
+ t,
8
+ TextAttributes
9
+ } from "@opentui/core";
10
+ var RIG_UI = {
11
+ bg: "#070809",
12
+ bg2: "#0b0c0e",
13
+ panel: "#101115",
14
+ panel2: "#14161b",
15
+ glass: "#1e2230",
16
+ border: "#2a2e3a",
17
+ ink: "#f4f5f8",
18
+ ink2: "#c7c9d3",
19
+ ink3: "#9aa0ae",
20
+ ink4: "#787b86",
21
+ lime: "#ccff4d",
22
+ limeDim: "#a9d63f",
23
+ cyan: "#56d8ff",
24
+ cyanDim: "#3f9fbd",
25
+ red: "#ff5d5d",
26
+ yellow: "#ffd24d",
27
+ magenta: "#ff79b0"
28
+ };
29
+ var styles = {
30
+ ink: otuiFg(RIG_UI.ink),
31
+ ink2: otuiFg(RIG_UI.ink2),
32
+ ink3: otuiFg(RIG_UI.ink3),
33
+ ink4: otuiFg(RIG_UI.ink4),
34
+ lime: otuiFg(RIG_UI.lime),
35
+ limeDim: otuiFg(RIG_UI.limeDim),
36
+ cyan: otuiFg(RIG_UI.cyan),
37
+ red: otuiFg(RIG_UI.red),
38
+ yellow: otuiFg(RIG_UI.yellow),
39
+ magenta: otuiFg(RIG_UI.magenta)
40
+ };
41
+
42
+ // packages/cli/src/app-opentui/render/ascii-fleet.ts
43
+ var LEAD_DRONE = [
44
+ " .-=-. .-=-. ",
45
+ " ( !!! ) ( !!! ) ",
46
+ " '-=-'._ _.'-=-' ",
47
+ " '._ _.' ",
48
+ " '=$$$$$$$=.' ",
49
+ " =$$$$$$$$$$$= ",
50
+ " $$$@@@@@@@@@@$$$ ",
51
+ " $$$@@ @@$$$ ",
52
+ " $$@ ? @$$$ ",
53
+ " $$$@ '-' @$$$ ",
54
+ " $$$@@ @@$$$ ",
55
+ " $$$@@@@@@@@@@$$$ ",
56
+ " =$$$$$$$$$$$= ",
57
+ " '=$$$$$$$=.' ",
58
+ " _.' '._ ",
59
+ " .-=-.' '.-=-. ",
60
+ " ( !!! ) ( !!! ) ",
61
+ " '-=-' '-=-' "
62
+ ];
63
+ var MINI_DRONE = [
64
+ "(!!!) (!!!)",
65
+ " \\%==%/ ",
66
+ " %%?%% ",
67
+ " /%==%\\ ",
68
+ "(!!!) (!!!)"
69
+ ];
70
+ var ROTORS = ["---", "\\\\\\", "|||", "///"];
71
+ var FLEET_GRID_WIDTH = 52;
72
+ var FLEET_GRID_HEIGHT = 27;
73
+ var FLEET = [
74
+ { art: MINI_DRONE, x: 0, y: 2, amp: 1, speed: 0.05, phase: 0, dx: 1, driftSpeed: 0.02 },
75
+ { art: MINI_DRONE, x: 39, y: 2, amp: 1, speed: 0.044, phase: 2.1, dx: 1, driftSpeed: 0.017 },
76
+ { art: MINI_DRONE, x: 1, y: 20, amp: 1, speed: 0.048, phase: 4.2, dx: 1, driftSpeed: 0.023 },
77
+ { art: MINI_DRONE, x: 38, y: 20, amp: 1, speed: 0.041, phase: 1.3, dx: 1, driftSpeed: 0.015 },
78
+ { art: LEAD_DRONE, x: 10, y: 5, amp: 2, speed: 0.04, phase: 0, dx: 0, driftSpeed: 0.011 }
79
+ ];
80
+ function fleetRows(tick, options = {}) {
81
+ const animate = options.animate ?? true;
82
+ const t2 = animate ? tick : 0;
83
+ const blade = ROTORS[Math.floor(t2 / 4) % ROTORS.length];
84
+ const pulse = Math.sin(t2 * 0.07);
85
+ const eye = pulse > 0.45 ? "@" : pulse > -0.1 ? "o" : ".";
86
+ const grid = Array.from({ length: FLEET_GRID_HEIGHT }, () => Array.from({ length: FLEET_GRID_WIDTH }, () => " "));
87
+ for (const drone of FLEET) {
88
+ const yOffset = drone.y + Math.round(drone.amp * Math.sin(t2 * drone.speed + drone.phase));
89
+ const xOffset = drone.x + Math.round(drone.dx * Math.sin(t2 * drone.driftSpeed + drone.phase));
90
+ for (let row = 0;row < drone.art.length; row += 1) {
91
+ const source = drone.art[row];
92
+ const targetY = yOffset + row;
93
+ if (targetY < 0 || targetY >= FLEET_GRID_HEIGHT)
94
+ continue;
95
+ for (let col = 0;col < source.length; col += 1) {
96
+ let char = source[col];
97
+ if (char === " ")
98
+ continue;
99
+ const targetX = xOffset + col;
100
+ if (targetX < 0 || targetX >= FLEET_GRID_WIDTH)
101
+ continue;
102
+ if (source.slice(col, col + 3) === "!!!") {
103
+ for (let rotorIndex = 0;rotorIndex < 3; rotorIndex += 1) {
104
+ if (targetX + rotorIndex < FLEET_GRID_WIDTH)
105
+ grid[targetY][targetX + rotorIndex] = blade[rotorIndex];
106
+ }
107
+ col += 2;
108
+ continue;
109
+ }
110
+ if (char === "?")
111
+ char = eye;
112
+ grid[targetY][targetX] = char;
113
+ }
114
+ }
115
+ }
116
+ return grid.map((row) => row.join("").replace(/\s+$/, ""));
117
+ }
118
+
119
+ // packages/cli/src/app-opentui/render/preloader.ts
120
+ var PRELOADER_MIN_DURATION_MS = 520;
121
+ var PRELOADER_MAX_DURATION_MS = 5000;
122
+ function maybeStartPreloaderTransition(transition, scene, now = Date.now()) {
123
+ if (transition.scene === scene)
124
+ return;
125
+ transition.scene = scene;
126
+ transition.startedAtMs = now;
127
+ transition.minUntilMs = now + PRELOADER_MIN_DURATION_MS;
128
+ }
129
+ function isPreloaderActive(transition, targetReady, now = Date.now()) {
130
+ if (now < transition.minUntilMs)
131
+ return true;
132
+ if (!targetReady && now - transition.startedAtMs < PRELOADER_MAX_DURATION_MS)
133
+ return true;
134
+ return false;
135
+ }
136
+ function preloaderLine(line, options = {}) {
137
+ return { text: line, bg: RIG_UI.bg, ...options };
138
+ }
139
+ function blockLine(text, leftPad, fg) {
140
+ return preloaderLine(`${" ".repeat(Math.max(0, leftPad))}${text.padEnd(FLEET_GRID_WIDTH)}`, { fg });
141
+ }
142
+ function renderAsciiPreloaderFrame(scene, layout, tick) {
143
+ const sprite = fleetRows(tick);
144
+ const leftPad = Math.max(0, Math.floor((layout.width - FLEET_GRID_WIDTH) / 2));
145
+ const blank = () => preloaderLine("");
146
+ const body = [
147
+ ...sprite.map((text, index) => blockLine(text, leftPad, index >= 7 && index <= 18 ? RIG_UI.lime : RIG_UI.limeDim))
148
+ ];
149
+ const topPadding = Math.max(0, Math.floor((layout.height - body.length) / 2));
150
+ const bottomPadding = Math.max(0, layout.height - body.length - topPadding);
151
+ return {
152
+ scene,
153
+ title: "Preloader",
154
+ lines: [...Array.from({ length: topPadding }, blank), ...body, ...Array.from({ length: bottomPadding }, blank)],
155
+ live: true,
156
+ fullScreen: true,
157
+ hideTypeBar: true,
158
+ footer: { message: "" }
159
+ };
160
+ }
161
+ export {
162
+ renderAsciiPreloaderFrame,
163
+ maybeStartPreloaderTransition,
164
+ isPreloaderActive
165
+ };
@@ -1,5 +1,5 @@
1
1
  import { type StageLayout } from "../layout";
2
- import type { AppSceneFrame, AppSceneLine } from "../types";
2
+ import type { AppSceneFrame, AppSceneLine, AppState } from "../types";
3
3
  export declare function line(text: string, options?: Omit<AppSceneLine, "text">): AppSceneLine;
4
4
  export declare function blank(): AppSceneLine;
5
5
  export declare function center(text: string, fg?: string, bold?: boolean): AppSceneLine;
@@ -11,6 +11,58 @@ export declare function deckRow(input: {
11
11
  readonly activateOnClick?: boolean;
12
12
  }): AppSceneLine;
13
13
  export declare function kv(label: string, value: string, fg?: string): AppSceneLine;
14
+ /**
15
+ * The canonical selectable row — the one selection-highlight mechanism for the
16
+ * whole shell (the dense tables already do this; this lifts the pattern out of
17
+ * each scene so they converge). A selected row gets the solid left rule
18
+ * (`SELECTION_MARKER`), lime+bold text, and `RIG_UI.glass` as the row `bg` so it
19
+ * paints a raised bar on the opaque panel ground (render/text.ts plumbs `bg` →
20
+ * RGBA). An idle row keeps a same-width blank marker so labels stay
21
+ * column-aligned whether or not a row is selected. `selectableIndex` makes the
22
+ * row clickable/navigable; pass the list index.
23
+ */
24
+ export declare function selectionLine(input: {
25
+ readonly text: string;
26
+ readonly active: boolean;
27
+ readonly index?: number;
28
+ readonly activateOnClick?: boolean;
29
+ }): AppSceneLine;
30
+ /**
31
+ * A dense-table header row: bold ink heading text on the `RIG_UI.glass` bar, the
32
+ * same raised-bar treatment a selected row gets, so a table's header and its
33
+ * selection share one visual language. Columns are joined with the shared
34
+ * `COLUMN_GUTTER`; pass already-padded column labels.
35
+ */
36
+ export declare function tableHeaderLine(columns: readonly string[]): AppSceneLine;
37
+ /**
38
+ * A `LABEL value` definition row padded to the shared `LABEL_WIDTH`, the
39
+ * canonical width for kv/deck rows across the shell (scenes had diverged on
40
+ * 10/22/26). The label is upper-cased chrome; the value carries the data tone.
41
+ */
42
+ export declare function labeledLine(label: string, value: string, fg?: string): AppSceneLine;
43
+ export declare function loadingLine(message?: string): AppSceneLine;
44
+ export declare function emptyLine(message?: string): AppSceneLine;
45
+ export declare function errorLine(message: string): AppSceneLine;
46
+ /**
47
+ * Per-scene preloader shown while a scene's primary data slice is still absent
48
+ * during a `loading` status (#22). Uses the Rig drone mascot — the animated
49
+ * signal-bus fleet sized for a panel body — with a captioned drone underneath,
50
+ * so a slow fetch reads as a live, branded "fetching" state rather than an empty
51
+ * panel. `tick` (from AppState.tick) drives the animation; pass it from the
52
+ * scene. `compact` swaps the full fleet for a single mini drone in tight panels.
53
+ */
54
+ export declare function loadingRows(label: string, tick?: number, compact?: boolean): AppSceneLine[];
55
+ /**
56
+ * Non-destructive failure banner for a degraded background refresh. Surfaces
57
+ * the error text without wiping the last-known data, and points the operator at
58
+ * the existing refresh/retry deck row below.
59
+ */
60
+ export declare function errorBanner(message: string, hint?: string): AppSceneLine[];
61
+ /**
62
+ * Typed reader for the background-refresh error string the data adapters write
63
+ * onto `state.data.lastRefreshError` (cleared on a successful refresh).
64
+ */
65
+ export declare function lastRefreshError(state: AppState): string | undefined;
14
66
  export declare function fitSceneLine(input: AppSceneLine, layout: StageLayout): AppSceneLine;
15
67
  export declare function fitSceneLines(lines: readonly AppSceneLine[], layout: StageLayout): AppSceneLine[];
16
68
  export declare function makeSceneFrame(input: AppSceneFrame): AppSceneFrame;
@@ -36,19 +36,25 @@ var RIG_UI = {
36
36
  bg: "#070809",
37
37
  bg2: "#0b0c0e",
38
38
  panel: "#101115",
39
- panel2: "#101115",
40
- glass: "#14161b",
41
- ink: "#f2f3f6",
42
- ink2: "#aeb0ba",
43
- ink3: "#6c6e79",
44
- ink4: "#44464f",
39
+ panel2: "#14161b",
40
+ glass: "#1e2230",
41
+ border: "#2a2e3a",
42
+ ink: "#f4f5f8",
43
+ ink2: "#c7c9d3",
44
+ ink3: "#9aa0ae",
45
+ ink4: "#787b86",
45
46
  lime: "#ccff4d",
46
47
  limeDim: "#a9d63f",
47
48
  cyan: "#56d8ff",
49
+ cyanDim: "#3f9fbd",
48
50
  red: "#ff5d5d",
49
51
  yellow: "#ffd24d",
50
52
  magenta: "#ff79b0"
51
53
  };
54
+ var SELECTION_MARKER = "\u258C";
55
+ var SELECTION_MARKER_IDLE = " ";
56
+ var LABEL_WIDTH = 14;
57
+ var COLUMN_GUTTER = " ";
52
58
  var styles = {
53
59
  ink: otuiFg(RIG_UI.ink),
54
60
  ink2: otuiFg(RIG_UI.ink2),
@@ -62,6 +68,134 @@ var styles = {
62
68
  magenta: otuiFg(RIG_UI.magenta)
63
69
  };
64
70
 
71
+ // packages/cli/src/app-opentui/drone.ts
72
+ import { RGBA, StyledText, TextAttributes as TextAttributes2 } from "@opentui/core";
73
+ var MINI_DRONE = [
74
+ "(!!!) (!!!)",
75
+ " \\%==%/ ",
76
+ " %%?%% ",
77
+ " /%==%\\ ",
78
+ "(!!!) (!!!)"
79
+ ];
80
+ var LEAD_MARK = [
81
+ " .-=-. ",
82
+ "=%%?%%=",
83
+ " '-=-' "
84
+ ];
85
+ var BLADE_FRAMES = ["---", "\\\\\\", "|||", "///"];
86
+ var EYE_FRAMES = ["o", "@", "\u2022", "."];
87
+ var COLOR = {
88
+ body: RGBA.fromHex(RIG_UI.lime),
89
+ mini: RGBA.fromHex(RIG_UI.limeDim),
90
+ rotor: RGBA.fromHex(RIG_UI.cyan),
91
+ path: RGBA.fromHex(RIG_UI.cyan),
92
+ eye: RGBA.fromHex(RIG_UI.ink),
93
+ dim: RGBA.fromHex(RIG_UI.ink4),
94
+ ink: RGBA.fromHex(RIG_UI.ink2)
95
+ };
96
+ function bladeForTick(tick, phase = 0) {
97
+ return BLADE_FRAMES[(Math.floor(tick / 3) + phase) % BLADE_FRAMES.length];
98
+ }
99
+ function eyeForTick(tick, phase = 0) {
100
+ const pulse = Math.sin(tick * 0.09 + phase);
101
+ return pulse > 0.55 ? EYE_FRAMES[1] : pulse > 0.1 ? EYE_FRAMES[0] : pulse > -0.45 ? EYE_FRAMES[2] : EYE_FRAMES[3];
102
+ }
103
+ function chunk(text, fg, bold = false, dim = false) {
104
+ let attributes = TextAttributes2.NONE;
105
+ if (bold)
106
+ attributes |= TextAttributes2.BOLD;
107
+ if (dim)
108
+ attributes |= TextAttributes2.DIM;
109
+ return { __isChunk: true, text, fg, ...attributes !== TextAttributes2.NONE ? { attributes } : {} };
110
+ }
111
+ function styledLine(text, colorFor) {
112
+ const chunks = [];
113
+ let run = "";
114
+ let runColor = null;
115
+ const flush = () => {
116
+ if (!run || !runColor)
117
+ return;
118
+ chunks.push(chunk(run, COLOR[runColor], runColor === "body" || runColor === "eye", runColor === "dim"));
119
+ run = "";
120
+ };
121
+ for (const char of text) {
122
+ const next = colorFor(char);
123
+ if (next !== runColor) {
124
+ flush();
125
+ runColor = next;
126
+ }
127
+ run += char;
128
+ }
129
+ flush();
130
+ return new StyledText(chunks.length > 0 ? chunks : [chunk("", COLOR.ink)]);
131
+ }
132
+ function droneColor(char) {
133
+ if (char === "?" || char === "o" || char === "@" || char === "\u2022")
134
+ return "eye";
135
+ if (char === "%" || char === "=")
136
+ return "mini";
137
+ if (char === "$")
138
+ return "body";
139
+ if (char === "(" || char === ")" || char === "/" || char === "\\" || char === "|" || char === "-")
140
+ return "rotor";
141
+ if (char === "\xB7" || char === "\u2022" || char === "'" || char === ".")
142
+ return "path";
143
+ if (char.trim() === "")
144
+ return "dim";
145
+ return "ink";
146
+ }
147
+ function motionColor(char) {
148
+ if (char === "\u25CF" || char === "\u25C6" || char === "\u25C9")
149
+ return "body";
150
+ if (char === "\u2022" || char === "\xB7" || char === "\u2500" || char === "\u2502" || char === "\u2571" || char === "\u2572" || char === "\u256D" || char === "\u256E" || char === "\u2570" || char === "\u256F")
151
+ return "path";
152
+ if (char === "\u258C" || char === "\u2590" || char === "\u2581" || char === "\u2594")
153
+ return "mini";
154
+ return droneColor(char);
155
+ }
156
+ function materializeDrone(lines, tick, phase = 0) {
157
+ const blade = bladeForTick(tick, phase);
158
+ const eye = eyeForTick(tick, phase);
159
+ return lines.map((line) => line.replaceAll("!!!", blade).replaceAll("?", eye));
160
+ }
161
+ function miniDroneLines(tick, align = "left", phase = 0) {
162
+ return materializeDrone(MINI_DRONE, tick, phase).map((text) => ({
163
+ text,
164
+ styledText: styledLine(text, droneColor),
165
+ fg: RIG_UI.limeDim,
166
+ align
167
+ }));
168
+ }
169
+ function brandFleetLines(tick, align = "center") {
170
+ const left = materializeDrone(MINI_DRONE, tick, 0);
171
+ const right = materializeDrone(MINI_DRONE, tick, 2);
172
+ const lead = materializeDrone(LEAD_MARK, tick, 1);
173
+ const packet = ["\xB7", "\u2022", "\u25CF", "\u2022"][Math.floor(tick / 2) % 4];
174
+ const bridge = [
175
+ ` ${left[0]} ${lead[0]} ${right[0]}`,
176
+ ` ${left[1]} \xB7\u2500\u2500${packet}\u2500\u2500\xB7 ${lead[1]} \xB7\u2500\u2500${packet}\u2500\u2500\xB7 ${right[1]}`,
177
+ ` ${left[2]} \xB7' '${lead[2]}' '\xB7 ${right[2]}`,
178
+ ` ${left[3]} \u2572 signal bus \u2571 ${right[3]}`,
179
+ ` ${left[4]} \xB7\u2500\u2500\u2500${packet}\u2500\u2500\u2500\u2500\u2500\u2500${packet}\u2500\u2500\u2500\xB7 ${right[4]}`
180
+ ];
181
+ return bridge.map((text) => ({
182
+ text,
183
+ styledText: styledLine(text, motionColor),
184
+ fg: RIG_UI.limeDim,
185
+ align
186
+ }));
187
+ }
188
+ function actionDrone(tick, phase = 0) {
189
+ const blade = bladeForTick(tick, phase);
190
+ const eye = eyeForTick(tick, phase);
191
+ return `(${blade})\u2572${eye}\u2571(${blade})`;
192
+ }
193
+ function actionDroneLine(tick, text, fg = RIG_UI.ink2) {
194
+ const prefix = actionDrone(tick);
195
+ const content = `${prefix} ${text}`;
196
+ return { text: content, styledText: styledLine(content, motionColor), fg, align: "center" };
197
+ }
198
+
65
199
  // packages/cli/src/app-opentui/render/scene.ts
66
200
  function line(text, options = {}) {
67
201
  return { text, ...options };
@@ -85,6 +219,52 @@ function deckRow(input) {
85
219
  function kv(label, value, fg = RIG_UI.ink2) {
86
220
  return line(` ${label.toUpperCase().padEnd(10)} ${value}`, { fg });
87
221
  }
222
+ function selectionLine(input) {
223
+ const marker = input.active ? SELECTION_MARKER : SELECTION_MARKER_IDLE;
224
+ return line(`${marker} ${input.text}`, {
225
+ fg: input.active ? RIG_UI.lime : RIG_UI.ink2,
226
+ bold: input.active,
227
+ bg: input.active ? RIG_UI.glass : undefined,
228
+ selectableIndex: input.index,
229
+ activateOnClick: input.activateOnClick
230
+ });
231
+ }
232
+ function tableHeaderLine(columns) {
233
+ return line(columns.join(COLUMN_GUTTER), { fg: RIG_UI.ink, bold: true, bg: RIG_UI.glass });
234
+ }
235
+ function labeledLine(label, value, fg = RIG_UI.ink2) {
236
+ return line(`${COLUMN_GUTTER}${label.toUpperCase().padEnd(LABEL_WIDTH)}${COLUMN_GUTTER}${value}`, { fg });
237
+ }
238
+ function loadingLine(message = "loading") {
239
+ return line(` \u27F2 ${message}`, { fg: RIG_UI.limeDim });
240
+ }
241
+ function emptyLine(message = "nothing here yet") {
242
+ return line(` ${message}`, { fg: RIG_UI.ink4 });
243
+ }
244
+ function errorLine(message) {
245
+ return line(` ! ${message}`, { fg: RIG_UI.magenta, bold: true });
246
+ }
247
+ function loadingRows(label, tick = 0, compact = false) {
248
+ const mascot = compact ? miniDroneLines(tick, "center") : brandFleetLines(tick, "center");
249
+ return [
250
+ blank(),
251
+ ...mascot,
252
+ blank(),
253
+ { ...actionDroneLine(tick, `loading ${label}\u2026`, RIG_UI.cyan), align: "center" }
254
+ ];
255
+ }
256
+ function errorBanner(message, hint) {
257
+ return [
258
+ line(`\u2717 failed to load \u2014 ${message}`, { fg: RIG_UI.red, bold: true }),
259
+ ...hint ? [line(` ${hint}`, { fg: RIG_UI.ink3 })] : [],
260
+ line(" select refresh/retry below", { fg: RIG_UI.ink4 }),
261
+ line("", { fg: RIG_UI.ink3 })
262
+ ];
263
+ }
264
+ function lastRefreshError(state) {
265
+ const value = state.data.lastRefreshError;
266
+ return typeof value === "string" && value.trim() ? value : undefined;
267
+ }
88
268
  function fitSceneLine(input, layout) {
89
269
  const fitted = truncateText(input.text, layout.centerWidth);
90
270
  return {
@@ -99,11 +279,20 @@ function makeSceneFrame(input) {
99
279
  return input;
100
280
  }
101
281
  export {
282
+ tableHeaderLine,
283
+ selectionLine,
102
284
  makeSceneFrame,
285
+ loadingRows,
286
+ loadingLine,
103
287
  line,
288
+ lastRefreshError,
289
+ labeledLine,
104
290
  kv,
105
291
  fitSceneLines,
106
292
  fitSceneLine,
293
+ errorLine,
294
+ errorBanner,
295
+ emptyLine,
107
296
  deckRow,
108
297
  center,
109
298
  blank
@@ -1,5 +1,11 @@
1
- import { TextRenderable, type CliRenderer, type MouseEvent } from "@opentui/core";
1
+ import { RGBA, TextRenderable, type CliRenderer, type MouseEvent } from "@opentui/core";
2
2
  import type { AppSceneLine } from "../types";
3
+ /** The "no background" sentinel: a line with no `bg` paints nothing and lets the
4
+ * opaque panel ground (render/panels.ts) show through. A line WITH a `bg` (e.g.
5
+ * a selected row, set via RIG_UI.glass) paints a raised bar on that ground —
6
+ * this is the one selection-highlight mechanism, plumbed end-to-end here so
7
+ * scenes only set `bg` on the AppSceneLine and never touch RGBA. */
8
+ export declare const TRANSPARENT: RGBA;
3
9
  export type TextLineRenderable = TextRenderable & {
4
10
  setRigSceneLine?(line: AppSceneLine | undefined): void;
5
11
  };
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // packages/cli/src/app-opentui/render/text.ts
3
- import { TextAttributes as TextAttributes2, TextRenderable } from "@opentui/core";
3
+ import { RGBA, TextAttributes as TextAttributes2, TextRenderable } from "@opentui/core";
4
4
 
5
5
  // packages/cli/src/app-opentui/theme.ts
6
6
  import {
@@ -14,15 +14,17 @@ var RIG_UI = {
14
14
  bg: "#070809",
15
15
  bg2: "#0b0c0e",
16
16
  panel: "#101115",
17
- panel2: "#101115",
18
- glass: "#14161b",
19
- ink: "#f2f3f6",
20
- ink2: "#aeb0ba",
21
- ink3: "#6c6e79",
22
- ink4: "#44464f",
17
+ panel2: "#14161b",
18
+ glass: "#1e2230",
19
+ border: "#2a2e3a",
20
+ ink: "#f4f5f8",
21
+ ink2: "#c7c9d3",
22
+ ink3: "#9aa0ae",
23
+ ink4: "#787b86",
23
24
  lime: "#ccff4d",
24
25
  limeDim: "#a9d63f",
25
26
  cyan: "#56d8ff",
27
+ cyanDim: "#3f9fbd",
26
28
  red: "#ff5d5d",
27
29
  yellow: "#ffd24d",
28
30
  magenta: "#ff79b0"
@@ -41,6 +43,7 @@ var styles = {
41
43
  };
42
44
 
43
45
  // packages/cli/src/app-opentui/render/text.ts
46
+ var TRANSPARENT = RGBA.fromInts(0, 0, 0, 0);
44
47
  function selectableMouseHandler(currentLineRef, onLineMouseDown) {
45
48
  return (event) => {
46
49
  const currentLine = currentLineRef();
@@ -91,6 +94,7 @@ function applyTextLine(renderable, line, top, left, width) {
91
94
  renderable.width = width;
92
95
  renderable.content = line?.styledText ?? line?.text ?? "";
93
96
  renderable.fg = line?.fg ?? RIG_UI.ink2;
97
+ renderable.bg = line?.bg ?? TRANSPARENT;
94
98
  renderable.attributes = line?.bold ? TextAttributes2.BOLD : line?.dim ? TextAttributes2.DIM : 0;
95
99
  }
96
100
  function applyFlowTextLine(renderable, line, width) {
@@ -100,6 +104,7 @@ function applyFlowTextLine(renderable, line, width) {
100
104
  renderable.width = Math.max(1, width);
101
105
  renderable.content = line?.styledText ?? line?.text ?? "";
102
106
  renderable.fg = line?.fg ?? RIG_UI.ink2;
107
+ renderable.bg = line?.bg ?? TRANSPARENT;
103
108
  renderable.attributes = line?.bold ? TextAttributes2.BOLD : line?.dim ? TextAttributes2.DIM : 0;
104
109
  }
105
110
  function clearTextLines(renderables, from = 0) {
@@ -110,6 +115,7 @@ function clearTextLines(renderables, from = 0) {
110
115
  renderable.top = -1;
111
116
  renderable.left = 0;
112
117
  renderable.width = 1;
118
+ renderable.bg = TRANSPARENT;
113
119
  }
114
120
  }
115
121
  export {
@@ -117,5 +123,6 @@ export {
117
123
  createFlowTextLine,
118
124
  clearTextLines,
119
125
  applyTextLine,
120
- applyFlowTextLine
126
+ applyFlowTextLine,
127
+ TRANSPARENT
121
128
  };
@@ -1,6 +1,7 @@
1
- import { InputRenderable, TextRenderable, type CliRenderer } from "@opentui/core";
1
+ import { BoxRenderable, InputRenderable, TextRenderable, type CliRenderer } from "@opentui/core";
2
2
  import type { AppFooterState, AppTypeBarState } from "../types";
3
3
  export type TypeBarRenderables = {
4
+ readonly background: BoxRenderable;
4
5
  readonly input: InputRenderable;
5
6
  readonly prefix: TextRenderable;
6
7
  readonly footer: TextRenderable;