@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
@@ -1,6 +1,6 @@
1
1
  // @bun
2
2
  // packages/cli/src/app-opentui/render/type-bar.ts
3
- import { InputRenderable, InputRenderableEvents, TextRenderable } from "@opentui/core";
3
+ import { BoxRenderable, InputRenderable, InputRenderableEvents, RGBA, StyledText, 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"
@@ -44,66 +46,101 @@ var styles = {
44
46
  function visibleWidth(text) {
45
47
  return [...text].length;
46
48
  }
47
- function truncateText(text, width) {
48
- if (visibleWidth(text) <= width)
49
- return text;
50
- if (width <= 1)
51
- return "\u2026";
52
- return `${[...text].slice(0, Math.max(0, width - 1)).join("")}\u2026`;
53
- }
54
49
 
55
50
  // packages/cli/src/app-opentui/render/type-bar.ts
51
+ var TYPEBAR_BG = RGBA.fromInts(20, 25, 14, 224);
52
+ var TYPEBAR_BORDER = RGBA.fromInts(204, 255, 77, 92);
56
53
  function createTypeBar(renderer) {
57
- const prefix = new TextRenderable(renderer, {
58
- id: "rig-typebar-prefix",
59
- content: " rig \u203A",
54
+ const background = new BoxRenderable(renderer, {
55
+ id: "typebar-card",
60
56
  position: "absolute",
61
57
  left: 0,
62
58
  top: 0,
59
+ width: 1,
60
+ height: 1,
61
+ backgroundColor: TYPEBAR_BG,
62
+ border: true,
63
+ borderColor: TYPEBAR_BORDER,
64
+ zIndex: 4
65
+ });
66
+ const prefix = new TextRenderable(renderer, {
67
+ id: "typebar-prefix",
68
+ content: " \u203A",
69
+ position: "absolute",
70
+ left: 1,
71
+ top: 0,
63
72
  fg: RIG_UI.lime,
73
+ zIndex: 7,
64
74
  selectable: true
65
75
  });
66
76
  const input = new InputRenderable(renderer, {
67
- id: "rig-typebar-input",
77
+ id: "typebar-input",
68
78
  position: "absolute",
69
- left: 7,
79
+ left: 4,
70
80
  top: 0,
71
81
  width: 40,
72
- placeholder: "fleet \xB7 tasks \xB7 run next \xB7 help",
82
+ placeholder: "runs \xB7 tasks \xB7 run next \xB7 help",
73
83
  textColor: RIG_UI.ink,
74
84
  cursorColor: RIG_UI.lime,
75
85
  cursorStyle: { style: "block", blinking: false },
76
86
  showCursor: true,
87
+ zIndex: 7,
77
88
  selectable: true
78
89
  });
79
90
  const footer = new TextRenderable(renderer, {
80
- id: "rig-footer",
91
+ id: "footer",
81
92
  content: "",
82
93
  position: "absolute",
83
94
  left: 0,
84
95
  top: 1,
85
96
  width: "100%",
86
- fg: RIG_UI.ink4,
97
+ fg: RIG_UI.ink3,
98
+ zIndex: 7,
87
99
  selectable: true
88
100
  });
89
- input.focus();
90
- return { input, prefix, footer };
101
+ return { background, input, prefix, footer };
102
+ }
103
+ function modePrefix(mode) {
104
+ switch (mode) {
105
+ case "search":
106
+ return { glyph: " /", color: RIG_UI.cyan };
107
+ case "command":
108
+ return { glyph: " /", color: RIG_UI.lime };
109
+ case "prompt":
110
+ return { glyph: " ?", color: RIG_UI.yellow };
111
+ default:
112
+ return { glyph: " \u203A", color: RIG_UI.ink3 };
113
+ }
91
114
  }
92
115
  function positionTypeBar(renderables, input, footer, width, typeBarTop, footerTop) {
93
- renderables.prefix.content = " rig \u203A";
116
+ const mode = input.mode ?? "nav";
117
+ const editing = mode !== "nav";
118
+ const { glyph, color } = modePrefix(mode);
119
+ renderables.background.visible = true;
120
+ const cardTop = Math.max(0, typeBarTop - 1);
121
+ renderables.background.left = 0;
122
+ renderables.background.top = cardTop;
123
+ renderables.background.width = width;
124
+ renderables.background.height = Math.max(3, footerTop - cardTop + 1);
125
+ renderables.prefix.content = glyph;
126
+ renderables.prefix.fg = color;
127
+ renderables.prefix.left = 2;
94
128
  renderables.prefix.top = typeBarTop;
95
129
  renderables.input.top = typeBarTop;
96
- renderables.input.left = 7;
97
- renderables.input.width = Math.max(10, width - 9);
98
- renderables.input.placeholder = input.placeholder;
99
- renderables.input.showCursor = true;
130
+ renderables.input.left = 5;
131
+ renderables.input.width = Math.max(10, width - 8);
132
+ renderables.input.value = editing ? input.value : "";
133
+ renderables.input.placeholder = editing ? mode === "prompt" ? input.prompt?.label ?? "type a value" : mode === "command" ? "rig \u2026" : "filter\u2026" : input.placeholder;
134
+ renderables.input.showCursor = editing;
135
+ if (renderables.input.focused)
136
+ renderables.input.blur();
100
137
  renderables.footer.top = footerTop;
101
138
  renderables.footer.width = "100%";
102
139
  renderables.footer.content = formatFooter(footer, width);
103
- if (!renderables.input.focused)
104
- renderables.input.focus();
105
140
  }
106
141
  function hideTypeBar(renderables, height) {
142
+ renderables.background.visible = false;
143
+ renderables.background.top = height + 1;
107
144
  renderables.prefix.content = "";
108
145
  renderables.prefix.top = height + 1;
109
146
  renderables.input.value = "";
@@ -119,15 +156,52 @@ function bindTypeBar(renderables, handlers) {
119
156
  renderables.input.on(InputRenderableEvents.INPUT, (value) => handlers.onInput(value));
120
157
  renderables.input.on(InputRenderableEvents.ENTER, (value) => handlers.onEnter(value));
121
158
  }
159
+ function safeFooterMessage(message) {
160
+ const trimmed = message?.trim();
161
+ if (!trimmed)
162
+ return null;
163
+ if (/https?:|\b[a-z0-9-]+\.[a-z]{2,}\b|\brig\b/i.test(trimmed))
164
+ return null;
165
+ return trimmed;
166
+ }
167
+ function liveCell(live) {
168
+ const connected = live.trimStart().startsWith("\u25CF");
169
+ return { text: live, style: connected ? styles.cyan : styles.ink3 };
170
+ }
171
+ function footerCells(footer) {
172
+ const safeMessage = safeFooterMessage(footer.message);
173
+ const cells = [
174
+ footer.section ? { text: `\u25B8 ${footer.section}`, style: (s) => otuiBold(styles.ink2(s)) } : null,
175
+ footer.live ? liveCell(footer.live) : null,
176
+ footer.project ? { text: "workspace", style: styles.ink3 } : null,
177
+ footer.server ? { text: "server selected", style: styles.ink3 } : null,
178
+ footer.auth ? { text: "auth ready", style: styles.ink3 } : null,
179
+ footer.run ? { text: `run ${footer.run}`, style: styles.ink3 } : null,
180
+ safeMessage ? { text: safeMessage, style: styles.ink2 } : null,
181
+ footer.updated ? { text: footer.updated, style: styles.ink3 } : null
182
+ ];
183
+ return cells.filter((cell) => cell !== null);
184
+ }
185
+ var FOOTER_SEPARATOR = " \xB7 ";
122
186
  function formatFooter(footer, width) {
123
- const parts = [
124
- footer.project ? `project ${footer.project}` : null,
125
- footer.server ? `server ${footer.server}` : null,
126
- footer.auth ? `auth ${footer.auth}` : null,
127
- footer.run ? `run ${footer.run}` : null,
128
- footer.message ?? null
129
- ].filter((part) => Boolean(part));
130
- return ` ${truncateText(parts.join(" \xB7 "), Math.max(8, width - 2))}`;
187
+ const budget = Math.max(8, width - 2);
188
+ const chunks = [styles.ink3(" ")];
189
+ let used = 1;
190
+ footerCells(footer).forEach((cell, index) => {
191
+ const sep = index === 0 ? "" : FOOTER_SEPARATOR;
192
+ const remaining = budget - used - visibleWidth(sep);
193
+ if (remaining <= 0)
194
+ return;
195
+ if (sep) {
196
+ chunks.push(styles.ink4(sep));
197
+ used += visibleWidth(sep);
198
+ }
199
+ const fits = visibleWidth(cell.text) <= remaining;
200
+ const text = fits ? cell.text : remaining <= 1 ? "\u2026" : `${[...cell.text].slice(0, Math.max(0, remaining - 1)).join("")}\u2026`;
201
+ chunks.push(cell.style(text));
202
+ used += visibleWidth(text);
203
+ });
204
+ return new StyledText(chunks);
131
205
  }
132
206
  export {
133
207
  positionTypeBar,
@@ -0,0 +1,16 @@
1
+ export type Disposer = () => void;
2
+ export declare class RuntimeResources {
3
+ private readonly disposers;
4
+ private disposed;
5
+ add(disposer: Disposer): Disposer;
6
+ setTimeout(callback: () => void, delayMs: number): ReturnType<typeof setTimeout>;
7
+ setInterval(callback: () => void, delayMs: number): ReturnType<typeof setInterval>;
8
+ clearTimeout(timer: ReturnType<typeof setTimeout> | null | undefined): void;
9
+ on<TEmitter extends {
10
+ on(event: string, listener: (...args: never[]) => void): unknown;
11
+ off?(event: string, listener: (...args: never[]) => void): unknown;
12
+ removeListener?(event: string, listener: (...args: never[]) => void): unknown;
13
+ }>(emitter: TEmitter, event: string, listener: (...args: never[]) => void): void;
14
+ disposeAll(): void;
15
+ private remove;
16
+ }
@@ -0,0 +1,62 @@
1
+ // @bun
2
+ // packages/cli/src/app-opentui/runtime-resources.ts
3
+ class RuntimeResources {
4
+ disposers = [];
5
+ disposed = false;
6
+ add(disposer) {
7
+ if (this.disposed) {
8
+ disposer();
9
+ return () => {
10
+ return;
11
+ };
12
+ }
13
+ this.disposers.push(disposer);
14
+ return disposer;
15
+ }
16
+ setTimeout(callback, delayMs) {
17
+ const timer = setTimeout(() => {
18
+ this.remove(dispose);
19
+ callback();
20
+ }, delayMs);
21
+ const dispose = () => clearTimeout(timer);
22
+ this.add(dispose);
23
+ return timer;
24
+ }
25
+ setInterval(callback, delayMs) {
26
+ const timer = setInterval(callback, delayMs);
27
+ this.add(() => clearInterval(timer));
28
+ return timer;
29
+ }
30
+ clearTimeout(timer) {
31
+ if (timer)
32
+ clearTimeout(timer);
33
+ }
34
+ on(emitter, event, listener) {
35
+ emitter.on(event, listener);
36
+ this.add(() => {
37
+ if (typeof emitter.off === "function")
38
+ emitter.off(event, listener);
39
+ else
40
+ emitter.removeListener?.(event, listener);
41
+ });
42
+ }
43
+ disposeAll() {
44
+ if (this.disposed)
45
+ return;
46
+ this.disposed = true;
47
+ for (let index = this.disposers.length - 1;index >= 0; index -= 1) {
48
+ try {
49
+ this.disposers[index]?.();
50
+ } catch {}
51
+ }
52
+ this.disposers.length = 0;
53
+ }
54
+ remove(disposer) {
55
+ const index = this.disposers.indexOf(disposer);
56
+ if (index >= 0)
57
+ this.disposers.splice(index, 1);
58
+ }
59
+ }
60
+ export {
61
+ RuntimeResources
62
+ };
@@ -1,2 +1,45 @@
1
- import type { AppLaunchOptions } from "./types";
1
+ import { StyledText, type CliRenderer } from "@opentui/core";
2
+ import { createAppStore } from "./state";
3
+ import type { AppIntent, AppLaunchOptions, AppRuntime, AppSceneId, AppSelectableItem, AppState } from "./types";
4
+ import { type NativeHost } from "./render/native-host";
5
+ /** Total per-scene entry intent for back-navigation (#13). Every AppSceneId
6
+ * resolves to an intent that re-enters THAT scene with its real data refresh —
7
+ * so popping the back-stack restores the exact prior scene, never dumping home
8
+ * from an unrelated origin. Transient PTY scenes (command/handoff) can't be
9
+ * "restored" from a closed terminal, so they re-enter their owning section. */
10
+ export declare function entryIntentForScene(scene: AppSceneId): AppIntent;
11
+ /** Readable section name for the persistent footer breadcrumb. */
12
+ export declare function sceneSectionLabel(scene: AppSceneId): string;
13
+ /** Footer freshness indicator (#6): push-connected vs polling fallback, so the
14
+ * UI never silently lies about whether it is live. */
15
+ export declare function liveLinkLabel(status: "connecting" | "connected" | "disconnected"): string;
16
+ /** Build the persistent top-nav strip as styled text: every section label with
17
+ * the ACTIVE one highlighted (lime + bold), Inbox carrying a live pending-count
18
+ * badge. Rendered on every scene so the operator always sees the sections and
19
+ * where they are (#2). Returns a StyledText for a single absolute TextRenderable. */
20
+ export declare function buildNavStrip(state: AppState): StyledText;
21
+ /** Test-only: the id of the nav section that should light up for a scene (#2). */
22
+ export declare function __activeNavSectionIdForTest(scene: AppSceneId): string;
23
+ /** Test-only: the intent esc/back resolves to given a back-stack — proving back
24
+ * restores the ACTUAL prior scene, never dumping home from an unrelated origin
25
+ * (#13). Mirrors runtime.goBack's resolution (pop → entryIntentForScene). */
26
+ export declare function __backTargetIntentForTest(history: readonly AppSceneId[]): AppIntent;
27
+ /** Test-only: whether a scene resolves to a REAL renderer (false ⇒ it would hit
28
+ * the redirect stub). Asserts the stub is unreachable for every real scene (#3). */
29
+ export declare function __sceneHasRendererForTest(scene: AppSceneId, sceneRenderers?: AppLaunchOptions["sceneRenderers"]): boolean;
30
+ export declare function selectIndex(store: ReturnType<typeof createAppStore>, index: number, renderedItems?: readonly AppSelectableItem[]): boolean;
31
+ export declare function moveSelection(store: ReturnType<typeof createAppStore>, delta: number, renderedItems?: readonly AppSelectableItem[]): boolean;
32
+ /** Select the item with this stable id (#12). Clicks resolve by id so a render
33
+ * between mouse-down and the click callback can't misfire on a shifted row. */
34
+ export declare function selectById(store: ReturnType<typeof createAppStore>, id: string, renderedItems?: readonly AppSelectableItem[]): boolean;
35
+ export declare function activateSelection(runtime: AppRuntime, renderedItems?: readonly AppSelectableItem[]): Promise<boolean>;
36
+ /** Test-only: render a single scene's state to a renderer headlessly so the
37
+ * FULL scene render path (scene renderer → panels + lines + native mounts) can
38
+ * be snapshot-verified via @opentui/core's createTestRenderer + captureCharFrame,
39
+ * without launching the live app. Mirrors the renderable pool the live app
40
+ * builds, then calls the real `renderNow`. Returns the derived selectable list. */
41
+ export declare function __renderSceneForTest(renderer: CliRenderer, state: AppState, sceneRenderers?: AppLaunchOptions["sceneRenderers"]): {
42
+ readonly selectables: readonly AppSelectableItem[];
43
+ readonly nativeHost: NativeHost | null;
44
+ };
2
45
  export declare function launchRigOpenTuiApp(options: AppLaunchOptions): Promise<void>;