@h-rig/cli 0.0.6-alpha.80 → 0.0.6-alpha.81

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 (105) hide show
  1. package/dist/bin/rig.js +17034 -11249
  2. package/dist/src/app/board.js +32 -3
  3. package/dist/src/app/drone-ui.js +1 -1
  4. package/dist/src/app/theme.js +1 -0
  5. package/dist/src/app-opentui/adapters/common.d.ts +53 -0
  6. package/dist/src/app-opentui/adapters/common.js +149 -0
  7. package/dist/src/app-opentui/adapters/doctor.d.ts +11 -0
  8. package/dist/src/app-opentui/adapters/doctor.js +780 -0
  9. package/dist/src/app-opentui/adapters/fleet.d.ts +16 -0
  10. package/dist/src/app-opentui/adapters/fleet.js +874 -0
  11. package/dist/src/app-opentui/adapters/inbox.d.ts +33 -0
  12. package/dist/src/app-opentui/adapters/inbox.js +1454 -0
  13. package/dist/src/app-opentui/adapters/init.d.ts +13 -0
  14. package/dist/src/app-opentui/adapters/init.js +2357 -0
  15. package/dist/src/app-opentui/adapters/pi-attach.d.ts +16 -0
  16. package/dist/src/app-opentui/adapters/pi-attach.js +1295 -0
  17. package/dist/src/app-opentui/adapters/run-detail.d.ts +20 -0
  18. package/dist/src/app-opentui/adapters/run-detail.js +893 -0
  19. package/dist/src/app-opentui/adapters/server.d.ts +14 -0
  20. package/dist/src/app-opentui/adapters/server.js +798 -0
  21. package/dist/src/app-opentui/adapters/tasks.d.ts +55 -0
  22. package/dist/src/app-opentui/adapters/tasks.js +3472 -0
  23. package/dist/src/app-opentui/bootstrap.d.ts +16 -0
  24. package/dist/src/app-opentui/bootstrap.js +19509 -0
  25. package/dist/src/app-opentui/drone.d.ts +12 -0
  26. package/dist/src/app-opentui/drone.js +227 -0
  27. package/dist/src/app-opentui/events.d.ts +7 -0
  28. package/dist/src/app-opentui/events.js +28 -0
  29. package/dist/src/app-opentui/index.d.ts +8 -0
  30. package/dist/src/app-opentui/index.js +3477 -0
  31. package/dist/src/app-opentui/intent.d.ts +3 -0
  32. package/dist/src/app-opentui/intent.js +211 -0
  33. package/dist/src/app-opentui/layout.d.ts +15 -0
  34. package/dist/src/app-opentui/layout.js +44 -0
  35. package/dist/src/app-opentui/list-search.d.ts +8 -0
  36. package/dist/src/app-opentui/list-search.js +43 -0
  37. package/dist/src/app-opentui/pi-host-child.d.ts +2 -0
  38. package/dist/src/app-opentui/pi-host-child.js +778 -0
  39. package/dist/src/app-opentui/pi-pty-host.d.ts +64 -0
  40. package/dist/src/app-opentui/pi-pty-host.js +384 -0
  41. package/dist/src/app-opentui/registry.d.ts +4 -0
  42. package/dist/src/app-opentui/registry.js +6835 -0
  43. package/dist/src/app-opentui/render/graphics.d.ts +39 -0
  44. package/dist/src/app-opentui/render/graphics.js +537 -0
  45. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.d.ts +2 -0
  46. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.js +1480 -0
  47. package/dist/src/app-opentui/render/image-visual-layer-worker.d.ts +1 -0
  48. package/dist/src/app-opentui/render/image-visual-layer-worker.js +1541 -0
  49. package/dist/src/app-opentui/render/image-visual-layer.d.ts +93 -0
  50. package/dist/src/app-opentui/render/image-visual-layer.js +945 -0
  51. package/dist/src/app-opentui/render/panels.d.ts +10 -0
  52. package/dist/src/app-opentui/render/panels.js +201 -0
  53. package/dist/src/app-opentui/render/scene.d.ts +16 -0
  54. package/dist/src/app-opentui/render/scene.js +110 -0
  55. package/dist/src/app-opentui/render/text.d.ts +10 -0
  56. package/dist/src/app-opentui/render/text.js +121 -0
  57. package/dist/src/app-opentui/render/type-bar.d.ts +14 -0
  58. package/dist/src/app-opentui/render/type-bar.js +137 -0
  59. package/dist/src/app-opentui/runtime.d.ts +2 -0
  60. package/dist/src/app-opentui/runtime.js +3406 -0
  61. package/dist/src/app-opentui/scenes/doctor.d.ts +2 -0
  62. package/dist/src/app-opentui/scenes/doctor.js +91 -0
  63. package/dist/src/app-opentui/scenes/error.d.ts +2 -0
  64. package/dist/src/app-opentui/scenes/error.js +190 -0
  65. package/dist/src/app-opentui/scenes/fleet.d.ts +3 -0
  66. package/dist/src/app-opentui/scenes/fleet.js +207 -0
  67. package/dist/src/app-opentui/scenes/handoff.d.ts +2 -0
  68. package/dist/src/app-opentui/scenes/handoff.js +147 -0
  69. package/dist/src/app-opentui/scenes/help.d.ts +3 -0
  70. package/dist/src/app-opentui/scenes/help.js +138 -0
  71. package/dist/src/app-opentui/scenes/inbox.d.ts +2 -0
  72. package/dist/src/app-opentui/scenes/inbox.js +118 -0
  73. package/dist/src/app-opentui/scenes/init.d.ts +2 -0
  74. package/dist/src/app-opentui/scenes/init.js +94 -0
  75. package/dist/src/app-opentui/scenes/main.d.ts +2 -0
  76. package/dist/src/app-opentui/scenes/main.js +96 -0
  77. package/dist/src/app-opentui/scenes/run-detail.d.ts +2 -0
  78. package/dist/src/app-opentui/scenes/run-detail.js +139 -0
  79. package/dist/src/app-opentui/scenes/server.d.ts +2 -0
  80. package/dist/src/app-opentui/scenes/server.js +88 -0
  81. package/dist/src/app-opentui/scenes/tasks.d.ts +3 -0
  82. package/dist/src/app-opentui/scenes/tasks.js +230 -0
  83. package/dist/src/app-opentui/state.d.ts +4 -0
  84. package/dist/src/app-opentui/state.js +286 -0
  85. package/dist/src/app-opentui/theme.d.ts +36 -0
  86. package/dist/src/app-opentui/theme.js +88 -0
  87. package/dist/src/app-opentui/types.d.ts +188 -0
  88. package/dist/src/app-opentui/types.js +1 -0
  89. package/dist/src/commands/_async-ui.js +1 -1
  90. package/dist/src/commands/_operator-view.js +1 -1
  91. package/dist/src/commands/_pi-frontend.js +1 -1
  92. package/dist/src/commands/_spinner.js +1 -1
  93. package/dist/src/commands/browser.js +1 -1
  94. package/dist/src/commands/doctor.js +1 -1
  95. package/dist/src/commands/github.js +1 -1
  96. package/dist/src/commands/inbox.js +1 -1
  97. package/dist/src/commands/init.js +1 -1
  98. package/dist/src/commands/inspect.js +1 -1
  99. package/dist/src/commands/run.js +1 -1
  100. package/dist/src/commands/setup.js +1 -1
  101. package/dist/src/commands/stats.js +1 -1
  102. package/dist/src/commands/task.js +1 -1
  103. package/dist/src/commands.js +33 -4
  104. package/dist/src/index.js +33 -4
  105. package/package.json +11 -8
@@ -0,0 +1,10 @@
1
+ import { ScrollBoxRenderable, type CliRenderer, type MouseEvent } from "@opentui/core";
2
+ import type { StageLayout } from "../layout";
3
+ import type { AppSceneLine, AppScenePanel } from "../types";
4
+ import { type TextLineRenderable } from "./text";
5
+ export type ScrollPanelRenderable = ScrollBoxRenderable & {
6
+ __rigTextLines: TextLineRenderable[];
7
+ __rigPanelId?: string;
8
+ };
9
+ export declare function createScrollPanelLayer(renderer: CliRenderer, id: string, onLineMouseDown?: (line: AppSceneLine, event: MouseEvent) => void): ScrollPanelRenderable;
10
+ export declare function applyScrollPanels(panels: readonly ScrollPanelRenderable[], layout: StageLayout, scenePanels: readonly AppScenePanel[]): void;
@@ -0,0 +1,201 @@
1
+ // @bun
2
+ // packages/cli/src/app-opentui/render/panels.ts
3
+ import { RGBA, ScrollBoxRenderable } from "@opentui/core";
4
+
5
+ // packages/cli/src/app-opentui/theme.ts
6
+ import {
7
+ bold as otuiBold,
8
+ dim as otuiDim,
9
+ fg as otuiFg,
10
+ t,
11
+ TextAttributes
12
+ } from "@opentui/core";
13
+ var RIG_UI = {
14
+ bg: "#070809",
15
+ bg2: "#0b0c0e",
16
+ panel: "#101115",
17
+ panel2: "#101115",
18
+ glass: "#14161b",
19
+ ink: "#f2f3f6",
20
+ ink2: "#aeb0ba",
21
+ ink3: "#6c6e79",
22
+ ink4: "#44464f",
23
+ lime: "#ccff4d",
24
+ limeDim: "#a9d63f",
25
+ cyan: "#56d8ff",
26
+ red: "#ff5d5d",
27
+ yellow: "#ffd24d",
28
+ magenta: "#ff79b0"
29
+ };
30
+ var styles = {
31
+ ink: otuiFg(RIG_UI.ink),
32
+ ink2: otuiFg(RIG_UI.ink2),
33
+ ink3: otuiFg(RIG_UI.ink3),
34
+ ink4: otuiFg(RIG_UI.ink4),
35
+ lime: otuiFg(RIG_UI.lime),
36
+ limeDim: otuiFg(RIG_UI.limeDim),
37
+ cyan: otuiFg(RIG_UI.cyan),
38
+ red: otuiFg(RIG_UI.red),
39
+ yellow: otuiFg(RIG_UI.yellow),
40
+ magenta: otuiFg(RIG_UI.magenta)
41
+ };
42
+
43
+ // packages/cli/src/app-opentui/render/text.ts
44
+ import { TextAttributes as TextAttributes2, TextRenderable } from "@opentui/core";
45
+ function selectableMouseHandler(currentLineRef, onLineMouseDown) {
46
+ return (event) => {
47
+ const currentLine = currentLineRef();
48
+ if (currentLine?.selectableIndex === undefined)
49
+ return;
50
+ onLineMouseDown?.(currentLine, event);
51
+ };
52
+ }
53
+ function createFlowTextLine(renderer, id, onLineMouseDown) {
54
+ let currentLine;
55
+ const renderable = new TextRenderable(renderer, {
56
+ id,
57
+ content: "",
58
+ width: "100%",
59
+ height: 1,
60
+ flexShrink: 0,
61
+ fg: RIG_UI.ink2,
62
+ selectable: true,
63
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
64
+ });
65
+ renderable.setRigSceneLine = (line) => {
66
+ currentLine = line;
67
+ };
68
+ return renderable;
69
+ }
70
+ function applyFlowTextLine(renderable, line, width) {
71
+ renderable.setRigSceneLine?.(line);
72
+ renderable.visible = Boolean(line);
73
+ renderable.height = line ? 1 : 0;
74
+ renderable.width = Math.max(1, width);
75
+ renderable.content = line?.styledText ?? line?.text ?? "";
76
+ renderable.fg = line?.fg ?? RIG_UI.ink2;
77
+ renderable.attributes = line?.bold ? TextAttributes2.BOLD : line?.dim ? TextAttributes2.DIM : 0;
78
+ }
79
+
80
+ // packages/cli/src/app-opentui/render/panels.ts
81
+ var TRANSPARENT = RGBA.fromInts(0, 0, 0, 0);
82
+ var MAX_PANEL_LINES = 420;
83
+ function hexToRgba(hex, alpha) {
84
+ const clean = hex.replace(/^#/, "");
85
+ const full = clean.length === 3 ? clean.split("").map((part) => `${part}${part}`).join("") : clean;
86
+ const value = Number.parseInt(full, 16);
87
+ if (!Number.isFinite(value))
88
+ return RGBA.fromInts(14, 15, 17, alpha);
89
+ return RGBA.fromInts(value >> 16 & 255, value >> 8 & 255, value & 255, alpha);
90
+ }
91
+ function panelBackground(panel) {
92
+ return hexToRgba(panel.backgroundColor ?? RIG_UI.panel, panel.backgroundAlpha ?? 184);
93
+ }
94
+ function panelBorder(panel) {
95
+ return panel.borderColor ? hexToRgba(panel.borderColor, panel.borderAlpha ?? 54) : TRANSPARENT;
96
+ }
97
+ function createScrollPanelLayer(renderer, id, onLineMouseDown) {
98
+ const panel = new ScrollBoxRenderable(renderer, {
99
+ id,
100
+ position: "absolute",
101
+ left: 0,
102
+ top: -2,
103
+ width: 1,
104
+ height: 1,
105
+ backgroundColor: TRANSPARENT,
106
+ border: false,
107
+ shouldFill: true,
108
+ opacity: 1,
109
+ zIndex: 6,
110
+ scrollY: true,
111
+ scrollX: false,
112
+ stickyScroll: false,
113
+ viewportCulling: true,
114
+ paddingX: 2,
115
+ paddingY: 1,
116
+ verticalScrollbarOptions: {
117
+ showArrows: false,
118
+ visible: false,
119
+ width: 1,
120
+ trackOptions: {
121
+ backgroundColor: TRANSPARENT,
122
+ foregroundColor: hexToRgba(RIG_UI.ink4, 84)
123
+ }
124
+ },
125
+ horizontalScrollbarOptions: {
126
+ height: 0,
127
+ visible: false,
128
+ trackOptions: {
129
+ backgroundColor: TRANSPARENT,
130
+ foregroundColor: TRANSPARENT
131
+ }
132
+ }
133
+ });
134
+ panel.__rigTextLines = [];
135
+ for (let index = 0;index < MAX_PANEL_LINES; index += 1) {
136
+ const line = createFlowTextLine(renderer, `${id}-line-${index}`, onLineMouseDown);
137
+ panel.__rigTextLines.push(line);
138
+ panel.add(line);
139
+ }
140
+ return panel;
141
+ }
142
+ function hidePanel(panel) {
143
+ panel.visible = false;
144
+ panel.top = -2;
145
+ panel.left = 0;
146
+ panel.width = 1;
147
+ panel.height = 1;
148
+ panel.backgroundColor = TRANSPARENT;
149
+ panel.border = false;
150
+ panel.__rigPanelId = undefined;
151
+ panel.__rigTextLines.forEach((line) => applyFlowTextLine(line, undefined, 1));
152
+ }
153
+ function applyScrollPanels(panels, layout, scenePanels) {
154
+ panels.forEach((renderable, index) => {
155
+ const panel = scenePanels[index];
156
+ if (!panel || panel.height <= 0) {
157
+ hidePanel(renderable);
158
+ return;
159
+ }
160
+ const cardLeft = Math.max(0, Math.min(layout.width - 1, layout.centerLeft + (panel.left ?? 0)));
161
+ const desiredWidth = panel.width ?? layout.centerWidth;
162
+ const cardWidth = Math.max(1, Math.min(layout.width - cardLeft, desiredWidth));
163
+ const cardTop = Math.max(0, Math.min(layout.height - 1, layout.centerTop + panel.top));
164
+ const cardHeight = Math.max(1, Math.min(layout.height - cardTop, panel.height));
165
+ const headerHeight = panel.chrome === "ad-terminal" ? Math.max(3, Math.min(cardHeight - 2, panel.headerHeight ?? 3)) : 0;
166
+ const left = cardLeft + (panel.chrome === "ad-terminal" ? 1 : 0);
167
+ const top = cardTop + headerHeight + (panel.chrome === "ad-terminal" ? 1 : 0);
168
+ const width = Math.max(1, Math.min(layout.width - left, cardWidth - (panel.chrome === "ad-terminal" ? 2 : 0)));
169
+ const height = Math.max(1, Math.min(layout.height - top, cardHeight - headerHeight - (panel.chrome === "ad-terminal" ? 2 : 0)));
170
+ const paddingX = panel.paddingX ?? (panel.chrome === "ad-terminal" ? 5 : 2);
171
+ const paddingY = panel.paddingY ?? (panel.chrome === "ad-terminal" ? 2 : 1);
172
+ const contentWidth = Math.max(1, width - paddingX * 2 - 1);
173
+ renderable.visible = true;
174
+ renderable.left = left;
175
+ renderable.top = top;
176
+ renderable.width = width;
177
+ renderable.height = height;
178
+ renderable.zIndex = panel.zIndex ?? 6;
179
+ renderable.opacity = panel.opacity ?? 1;
180
+ renderable.backgroundColor = panel.chrome === "ad-terminal" ? TRANSPARENT : panelBackground(panel);
181
+ renderable.border = panel.chrome === "ad-terminal" ? false : panel.border ?? false;
182
+ renderable.borderColor = panelBorder(panel);
183
+ renderable.paddingX = paddingX;
184
+ renderable.paddingY = paddingY;
185
+ renderable.stickyScroll = panel.stickyScroll ?? false;
186
+ renderable.stickyStart = panel.stickyStart;
187
+ renderable.verticalScrollBar.visible = false;
188
+ renderable.horizontalScrollBar.visible = false;
189
+ if (renderable.__rigPanelId !== panel.id) {
190
+ renderable.__rigPanelId = panel.id;
191
+ renderable.scrollTo(0);
192
+ }
193
+ renderable.__rigTextLines.forEach((line, lineIndex) => {
194
+ applyFlowTextLine(line, panel.lines[lineIndex], contentWidth);
195
+ });
196
+ });
197
+ }
198
+ export {
199
+ createScrollPanelLayer,
200
+ applyScrollPanels
201
+ };
@@ -0,0 +1,16 @@
1
+ import { type StageLayout } from "../layout";
2
+ import type { AppSceneFrame, AppSceneLine } from "../types";
3
+ export declare function line(text: string, options?: Omit<AppSceneLine, "text">): AppSceneLine;
4
+ export declare function blank(): AppSceneLine;
5
+ export declare function center(text: string, fg?: string, bold?: boolean): AppSceneLine;
6
+ export declare function deckRow(input: {
7
+ readonly label: string;
8
+ readonly detail: string;
9
+ readonly index?: number;
10
+ readonly active?: boolean;
11
+ readonly activateOnClick?: boolean;
12
+ }): AppSceneLine;
13
+ export declare function kv(label: string, value: string, fg?: string): AppSceneLine;
14
+ export declare function fitSceneLine(input: AppSceneLine, layout: StageLayout): AppSceneLine;
15
+ export declare function fitSceneLines(lines: readonly AppSceneLine[], layout: StageLayout): AppSceneLine[];
16
+ export declare function makeSceneFrame(input: AppSceneFrame): AppSceneFrame;
@@ -0,0 +1,110 @@
1
+ // @bun
2
+ // packages/cli/src/app-opentui/layout.ts
3
+ function visibleWidth(text) {
4
+ return [...text].length;
5
+ }
6
+ function alignText(text, width, align = "left") {
7
+ const length = visibleWidth(text);
8
+ if (length >= width)
9
+ return text;
10
+ const pad = width - length;
11
+ if (align === "right")
12
+ return `${" ".repeat(pad)}${text}`;
13
+ if (align === "center") {
14
+ const left = Math.floor(pad / 2);
15
+ return `${" ".repeat(left)}${text}${" ".repeat(pad - left)}`;
16
+ }
17
+ return text;
18
+ }
19
+ function truncateText(text, width) {
20
+ if (visibleWidth(text) <= width)
21
+ return text;
22
+ if (width <= 1)
23
+ return "\u2026";
24
+ return `${[...text].slice(0, Math.max(0, width - 1)).join("")}\u2026`;
25
+ }
26
+
27
+ // packages/cli/src/app-opentui/theme.ts
28
+ import {
29
+ bold as otuiBold,
30
+ dim as otuiDim,
31
+ fg as otuiFg,
32
+ t,
33
+ TextAttributes
34
+ } from "@opentui/core";
35
+ var RIG_UI = {
36
+ bg: "#070809",
37
+ bg2: "#0b0c0e",
38
+ panel: "#101115",
39
+ panel2: "#101115",
40
+ glass: "#14161b",
41
+ ink: "#f2f3f6",
42
+ ink2: "#aeb0ba",
43
+ ink3: "#6c6e79",
44
+ ink4: "#44464f",
45
+ lime: "#ccff4d",
46
+ limeDim: "#a9d63f",
47
+ cyan: "#56d8ff",
48
+ red: "#ff5d5d",
49
+ yellow: "#ffd24d",
50
+ magenta: "#ff79b0"
51
+ };
52
+ var styles = {
53
+ ink: otuiFg(RIG_UI.ink),
54
+ ink2: otuiFg(RIG_UI.ink2),
55
+ ink3: otuiFg(RIG_UI.ink3),
56
+ ink4: otuiFg(RIG_UI.ink4),
57
+ lime: otuiFg(RIG_UI.lime),
58
+ limeDim: otuiFg(RIG_UI.limeDim),
59
+ cyan: otuiFg(RIG_UI.cyan),
60
+ red: otuiFg(RIG_UI.red),
61
+ yellow: otuiFg(RIG_UI.yellow),
62
+ magenta: otuiFg(RIG_UI.magenta)
63
+ };
64
+
65
+ // packages/cli/src/app-opentui/render/scene.ts
66
+ function line(text, options = {}) {
67
+ return { text, ...options };
68
+ }
69
+ function blank() {
70
+ return { text: "" };
71
+ }
72
+ function center(text, fg = RIG_UI.ink2, bold = false) {
73
+ return { text, fg, bold, align: "center" };
74
+ }
75
+ function deckRow(input) {
76
+ const prefix = input.active ? "\u25B8" : " ";
77
+ const label = input.label.toUpperCase().padEnd(10);
78
+ return line(`${prefix} ${label} ${input.detail}`, {
79
+ fg: input.active ? RIG_UI.lime : RIG_UI.ink2,
80
+ bold: input.active,
81
+ selectableIndex: input.index,
82
+ activateOnClick: input.activateOnClick
83
+ });
84
+ }
85
+ function kv(label, value, fg = RIG_UI.ink2) {
86
+ return line(` ${label.toUpperCase().padEnd(10)} ${value}`, { fg });
87
+ }
88
+ function fitSceneLine(input, layout) {
89
+ const fitted = truncateText(input.text, layout.centerWidth);
90
+ return {
91
+ ...input,
92
+ text: alignText(fitted, layout.centerWidth, input.align ?? "left")
93
+ };
94
+ }
95
+ function fitSceneLines(lines, layout) {
96
+ return lines.slice(0, layout.centerHeight).map((entry) => fitSceneLine(entry, layout));
97
+ }
98
+ function makeSceneFrame(input) {
99
+ return input;
100
+ }
101
+ export {
102
+ makeSceneFrame,
103
+ line,
104
+ kv,
105
+ fitSceneLines,
106
+ fitSceneLine,
107
+ deckRow,
108
+ center,
109
+ blank
110
+ };
@@ -0,0 +1,10 @@
1
+ import { TextRenderable, type CliRenderer, type MouseEvent } from "@opentui/core";
2
+ import type { AppSceneLine } from "../types";
3
+ export type TextLineRenderable = TextRenderable & {
4
+ setRigSceneLine?(line: AppSceneLine | undefined): void;
5
+ };
6
+ export declare function createTextLine(renderer: CliRenderer, id: string, top: number, onLineMouseDown?: (line: AppSceneLine, event: MouseEvent) => void): TextLineRenderable;
7
+ export declare function createFlowTextLine(renderer: CliRenderer, id: string, onLineMouseDown?: (line: AppSceneLine, event: MouseEvent) => void): TextLineRenderable;
8
+ export declare function applyTextLine(renderable: TextLineRenderable, line: AppSceneLine | undefined, top: number, left: number, width: number): void;
9
+ export declare function applyFlowTextLine(renderable: TextLineRenderable, line: AppSceneLine | undefined, width: number): void;
10
+ export declare function clearTextLines(renderables: readonly TextLineRenderable[], from?: number): void;
@@ -0,0 +1,121 @@
1
+ // @bun
2
+ // packages/cli/src/app-opentui/render/text.ts
3
+ import { TextAttributes as TextAttributes2, TextRenderable } from "@opentui/core";
4
+
5
+ // packages/cli/src/app-opentui/theme.ts
6
+ import {
7
+ bold as otuiBold,
8
+ dim as otuiDim,
9
+ fg as otuiFg,
10
+ t,
11
+ TextAttributes
12
+ } from "@opentui/core";
13
+ var RIG_UI = {
14
+ bg: "#070809",
15
+ bg2: "#0b0c0e",
16
+ panel: "#101115",
17
+ panel2: "#101115",
18
+ glass: "#14161b",
19
+ ink: "#f2f3f6",
20
+ ink2: "#aeb0ba",
21
+ ink3: "#6c6e79",
22
+ ink4: "#44464f",
23
+ lime: "#ccff4d",
24
+ limeDim: "#a9d63f",
25
+ cyan: "#56d8ff",
26
+ red: "#ff5d5d",
27
+ yellow: "#ffd24d",
28
+ magenta: "#ff79b0"
29
+ };
30
+ var styles = {
31
+ ink: otuiFg(RIG_UI.ink),
32
+ ink2: otuiFg(RIG_UI.ink2),
33
+ ink3: otuiFg(RIG_UI.ink3),
34
+ ink4: otuiFg(RIG_UI.ink4),
35
+ lime: otuiFg(RIG_UI.lime),
36
+ limeDim: otuiFg(RIG_UI.limeDim),
37
+ cyan: otuiFg(RIG_UI.cyan),
38
+ red: otuiFg(RIG_UI.red),
39
+ yellow: otuiFg(RIG_UI.yellow),
40
+ magenta: otuiFg(RIG_UI.magenta)
41
+ };
42
+
43
+ // packages/cli/src/app-opentui/render/text.ts
44
+ function selectableMouseHandler(currentLineRef, onLineMouseDown) {
45
+ return (event) => {
46
+ const currentLine = currentLineRef();
47
+ if (currentLine?.selectableIndex === undefined)
48
+ return;
49
+ onLineMouseDown?.(currentLine, event);
50
+ };
51
+ }
52
+ function createTextLine(renderer, id, top, onLineMouseDown) {
53
+ let currentLine;
54
+ const renderable = new TextRenderable(renderer, {
55
+ id,
56
+ content: "",
57
+ position: "absolute",
58
+ left: 0,
59
+ top,
60
+ width: 1,
61
+ fg: RIG_UI.ink2,
62
+ selectable: true,
63
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
64
+ });
65
+ renderable.setRigSceneLine = (line) => {
66
+ currentLine = line;
67
+ };
68
+ return renderable;
69
+ }
70
+ function createFlowTextLine(renderer, id, onLineMouseDown) {
71
+ let currentLine;
72
+ const renderable = new TextRenderable(renderer, {
73
+ id,
74
+ content: "",
75
+ width: "100%",
76
+ height: 1,
77
+ flexShrink: 0,
78
+ fg: RIG_UI.ink2,
79
+ selectable: true,
80
+ onMouseDown: selectableMouseHandler(() => currentLine, onLineMouseDown)
81
+ });
82
+ renderable.setRigSceneLine = (line) => {
83
+ currentLine = line;
84
+ };
85
+ return renderable;
86
+ }
87
+ function applyTextLine(renderable, line, top, left, width) {
88
+ renderable.setRigSceneLine?.(line);
89
+ renderable.top = top;
90
+ renderable.left = left;
91
+ renderable.width = width;
92
+ renderable.content = line?.styledText ?? line?.text ?? "";
93
+ renderable.fg = line?.fg ?? RIG_UI.ink2;
94
+ renderable.attributes = line?.bold ? TextAttributes2.BOLD : line?.dim ? TextAttributes2.DIM : 0;
95
+ }
96
+ function applyFlowTextLine(renderable, line, width) {
97
+ renderable.setRigSceneLine?.(line);
98
+ renderable.visible = Boolean(line);
99
+ renderable.height = line ? 1 : 0;
100
+ renderable.width = Math.max(1, width);
101
+ renderable.content = line?.styledText ?? line?.text ?? "";
102
+ renderable.fg = line?.fg ?? RIG_UI.ink2;
103
+ renderable.attributes = line?.bold ? TextAttributes2.BOLD : line?.dim ? TextAttributes2.DIM : 0;
104
+ }
105
+ function clearTextLines(renderables, from = 0) {
106
+ for (let index = from;index < renderables.length; index += 1) {
107
+ const renderable = renderables[index];
108
+ renderable.setRigSceneLine?.(undefined);
109
+ renderable.content = "";
110
+ renderable.top = -1;
111
+ renderable.left = 0;
112
+ renderable.width = 1;
113
+ }
114
+ }
115
+ export {
116
+ createTextLine,
117
+ createFlowTextLine,
118
+ clearTextLines,
119
+ applyTextLine,
120
+ applyFlowTextLine
121
+ };
@@ -0,0 +1,14 @@
1
+ import { InputRenderable, TextRenderable, type CliRenderer } from "@opentui/core";
2
+ import type { AppFooterState, AppTypeBarState } from "../types";
3
+ export type TypeBarRenderables = {
4
+ readonly input: InputRenderable;
5
+ readonly prefix: TextRenderable;
6
+ readonly footer: TextRenderable;
7
+ };
8
+ export declare function createTypeBar(renderer: CliRenderer): TypeBarRenderables;
9
+ export declare function positionTypeBar(renderables: TypeBarRenderables, input: AppTypeBarState, footer: AppFooterState, width: number, typeBarTop: number, footerTop: number): void;
10
+ export declare function hideTypeBar(renderables: TypeBarRenderables, height: number): void;
11
+ export declare function bindTypeBar(renderables: TypeBarRenderables, handlers: {
12
+ onInput(value: string): void;
13
+ onEnter(value: string): void;
14
+ }): void;
@@ -0,0 +1,137 @@
1
+ // @bun
2
+ // packages/cli/src/app-opentui/render/type-bar.ts
3
+ import { InputRenderable, InputRenderableEvents, TextRenderable } from "@opentui/core";
4
+
5
+ // packages/cli/src/app-opentui/theme.ts
6
+ import {
7
+ bold as otuiBold,
8
+ dim as otuiDim,
9
+ fg as otuiFg,
10
+ t,
11
+ TextAttributes
12
+ } from "@opentui/core";
13
+ var RIG_UI = {
14
+ bg: "#070809",
15
+ bg2: "#0b0c0e",
16
+ panel: "#101115",
17
+ panel2: "#101115",
18
+ glass: "#14161b",
19
+ ink: "#f2f3f6",
20
+ ink2: "#aeb0ba",
21
+ ink3: "#6c6e79",
22
+ ink4: "#44464f",
23
+ lime: "#ccff4d",
24
+ limeDim: "#a9d63f",
25
+ cyan: "#56d8ff",
26
+ red: "#ff5d5d",
27
+ yellow: "#ffd24d",
28
+ magenta: "#ff79b0"
29
+ };
30
+ var styles = {
31
+ ink: otuiFg(RIG_UI.ink),
32
+ ink2: otuiFg(RIG_UI.ink2),
33
+ ink3: otuiFg(RIG_UI.ink3),
34
+ ink4: otuiFg(RIG_UI.ink4),
35
+ lime: otuiFg(RIG_UI.lime),
36
+ limeDim: otuiFg(RIG_UI.limeDim),
37
+ cyan: otuiFg(RIG_UI.cyan),
38
+ red: otuiFg(RIG_UI.red),
39
+ yellow: otuiFg(RIG_UI.yellow),
40
+ magenta: otuiFg(RIG_UI.magenta)
41
+ };
42
+
43
+ // packages/cli/src/app-opentui/layout.ts
44
+ function visibleWidth(text) {
45
+ return [...text].length;
46
+ }
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
+
55
+ // packages/cli/src/app-opentui/render/type-bar.ts
56
+ function createTypeBar(renderer) {
57
+ const prefix = new TextRenderable(renderer, {
58
+ id: "rig-typebar-prefix",
59
+ content: " rig \u203A",
60
+ position: "absolute",
61
+ left: 0,
62
+ top: 0,
63
+ fg: RIG_UI.lime,
64
+ selectable: true
65
+ });
66
+ const input = new InputRenderable(renderer, {
67
+ id: "rig-typebar-input",
68
+ position: "absolute",
69
+ left: 7,
70
+ top: 0,
71
+ width: 40,
72
+ placeholder: "fleet \xB7 tasks \xB7 run next \xB7 help",
73
+ textColor: RIG_UI.ink,
74
+ cursorColor: RIG_UI.lime,
75
+ cursorStyle: { style: "block", blinking: false },
76
+ showCursor: true,
77
+ selectable: true
78
+ });
79
+ const footer = new TextRenderable(renderer, {
80
+ id: "rig-footer",
81
+ content: "",
82
+ position: "absolute",
83
+ left: 0,
84
+ top: 1,
85
+ width: "100%",
86
+ fg: RIG_UI.ink4,
87
+ selectable: true
88
+ });
89
+ input.focus();
90
+ return { input, prefix, footer };
91
+ }
92
+ function positionTypeBar(renderables, input, footer, width, typeBarTop, footerTop) {
93
+ renderables.prefix.content = " rig \u203A";
94
+ renderables.prefix.top = typeBarTop;
95
+ 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;
100
+ renderables.footer.top = footerTop;
101
+ renderables.footer.width = "100%";
102
+ renderables.footer.content = formatFooter(footer, width);
103
+ if (!renderables.input.focused)
104
+ renderables.input.focus();
105
+ }
106
+ function hideTypeBar(renderables, height) {
107
+ renderables.prefix.content = "";
108
+ renderables.prefix.top = height + 1;
109
+ renderables.input.value = "";
110
+ renderables.input.placeholder = "";
111
+ renderables.input.top = height + 1;
112
+ renderables.input.left = 0;
113
+ renderables.input.width = 1;
114
+ renderables.input.blur();
115
+ renderables.footer.content = "";
116
+ renderables.footer.top = height + 1;
117
+ }
118
+ function bindTypeBar(renderables, handlers) {
119
+ renderables.input.on(InputRenderableEvents.INPUT, (value) => handlers.onInput(value));
120
+ renderables.input.on(InputRenderableEvents.ENTER, (value) => handlers.onEnter(value));
121
+ }
122
+ 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))}`;
131
+ }
132
+ export {
133
+ positionTypeBar,
134
+ hideTypeBar,
135
+ createTypeBar,
136
+ bindTypeBar
137
+ };
@@ -0,0 +1,2 @@
1
+ import type { AppLaunchOptions } from "./types";
2
+ export declare function launchRigOpenTuiApp(options: AppLaunchOptions): Promise<void>;