@h-rig/cli 0.0.6-alpha.83 → 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 (163) hide show
  1. package/dist/bin/rig.js +22085 -14618
  2. package/dist/src/app/board.js +155 -28
  3. package/dist/src/app-opentui/adapters/doctor.d.ts +0 -2
  4. package/dist/src/app-opentui/adapters/doctor.js +1 -25
  5. package/dist/src/app-opentui/adapters/family.d.ts +62 -0
  6. package/dist/src/app-opentui/adapters/family.js +14305 -0
  7. package/dist/src/app-opentui/adapters/fleet.d.ts +0 -2
  8. package/dist/src/app-opentui/adapters/fleet.js +6 -40
  9. package/dist/src/app-opentui/adapters/inbox.d.ts +12 -2
  10. package/dist/src/app-opentui/adapters/inbox.js +54 -59
  11. package/dist/src/app-opentui/adapters/init.d.ts +0 -2
  12. package/dist/src/app-opentui/adapters/init.js +0 -26
  13. package/dist/src/app-opentui/adapters/inspect.d.ts +52 -0
  14. package/dist/src/app-opentui/adapters/inspect.js +1024 -0
  15. package/dist/src/app-opentui/adapters/pi-attach.d.ts +15 -6
  16. package/dist/src/app-opentui/adapters/pi-attach.js +348 -93
  17. package/dist/src/app-opentui/adapters/pi.d.ts +23 -0
  18. package/dist/src/app-opentui/adapters/pi.js +363 -0
  19. package/dist/src/app-opentui/adapters/plugin.d.ts +84 -0
  20. package/dist/src/app-opentui/adapters/plugin.js +544 -0
  21. package/dist/src/app-opentui/adapters/repo.d.ts +37 -0
  22. package/dist/src/app-opentui/adapters/repo.js +186 -0
  23. package/dist/src/app-opentui/adapters/run-detail.d.ts +9 -2
  24. package/dist/src/app-opentui/adapters/run-detail.js +97 -44
  25. package/dist/src/app-opentui/adapters/server.d.ts +10 -2
  26. package/dist/src/app-opentui/adapters/server.js +96 -27
  27. package/dist/src/app-opentui/adapters/tasks.d.ts +0 -2
  28. package/dist/src/app-opentui/adapters/tasks.js +437 -105
  29. package/dist/src/app-opentui/adapters/workspace.d.ts +49 -0
  30. package/dist/src/app-opentui/adapters/workspace.js +333 -0
  31. package/dist/src/app-opentui/autocomplete.d.ts +20 -0
  32. package/dist/src/app-opentui/autocomplete.js +576 -0
  33. package/dist/src/app-opentui/bootstrap.js +24296 -16919
  34. package/dist/src/app-opentui/command-palette.d.ts +3 -0
  35. package/dist/src/app-opentui/command-palette.js +1010 -0
  36. package/dist/src/app-opentui/drone.js +8 -6
  37. package/dist/src/app-opentui/fleet-stats.d.ts +32 -0
  38. package/dist/src/app-opentui/fleet-stats.js +114 -0
  39. package/dist/src/app-opentui/index.js +3438 -1724
  40. package/dist/src/app-opentui/intent.js +71 -48
  41. package/dist/src/app-opentui/keymap.d.ts +6 -5
  42. package/dist/src/app-opentui/keymap.js +1064 -23
  43. package/dist/src/app-opentui/layout.d.ts +7 -0
  44. package/dist/src/app-opentui/layout.js +13 -6
  45. package/dist/src/app-opentui/list-search.d.ts +24 -0
  46. package/dist/src/app-opentui/list-search.js +88 -1
  47. package/dist/src/app-opentui/pi-host-child.js +33 -1
  48. package/dist/src/app-opentui/pi-pty-host.d.ts +5 -0
  49. package/dist/src/app-opentui/pi-pty-host.js +21 -3
  50. package/dist/src/app-opentui/react/App.d.ts +9 -0
  51. package/dist/src/app-opentui/react/App.js +5144 -0
  52. package/dist/src/app-opentui/react/Backdrop.d.ts +5 -0
  53. package/dist/src/app-opentui/react/Backdrop.js +1834 -0
  54. package/dist/src/app-opentui/react/ChromeHost.d.ts +5 -0
  55. package/dist/src/app-opentui/react/ChromeHost.js +2942 -0
  56. package/dist/src/app-opentui/react/SceneFrameView.d.ts +7 -0
  57. package/dist/src/app-opentui/react/SceneFrameView.js +529 -0
  58. package/dist/src/app-opentui/react/context.d.ts +17 -0
  59. package/dist/src/app-opentui/react/context.js +37 -0
  60. package/dist/src/app-opentui/react/launch.d.ts +2 -0
  61. package/dist/src/app-opentui/react/launch.js +5743 -0
  62. package/dist/src/app-opentui/react/nav.d.ts +18 -0
  63. package/dist/src/app-opentui/react/nav.js +54 -0
  64. package/dist/src/app-opentui/react/scroll.d.ts +12 -0
  65. package/dist/src/app-opentui/react/scroll.js +21 -0
  66. package/dist/src/app-opentui/react/syntax.d.ts +2 -0
  67. package/dist/src/app-opentui/react/syntax.js +64 -0
  68. package/dist/src/app-opentui/registry.js +19923 -5151
  69. package/dist/src/app-opentui/render/constants.d.ts +31 -0
  70. package/dist/src/app-opentui/render/constants.js +66 -0
  71. package/dist/src/app-opentui/render/graphics.d.ts +2 -1
  72. package/dist/src/app-opentui/render/graphics.js +106 -39
  73. package/dist/src/app-opentui/render/image-visual-layer-worker.js +108 -20
  74. package/dist/src/app-opentui/render/image-visual-layer.d.ts +7 -0
  75. package/dist/src/app-opentui/render/image-visual-layer.js +109 -20
  76. package/dist/src/app-opentui/render/native-host.d.ts +37 -0
  77. package/dist/src/app-opentui/render/native-host.js +179 -0
  78. package/dist/src/app-opentui/render/panels.js +18 -11
  79. package/dist/src/app-opentui/render/preloader.js +8 -6
  80. package/dist/src/app-opentui/render/scene.d.ts +50 -1
  81. package/dist/src/app-opentui/render/scene.js +183 -6
  82. package/dist/src/app-opentui/render/text.d.ts +7 -1
  83. package/dist/src/app-opentui/render/text.js +10 -7
  84. package/dist/src/app-opentui/render/type-bar.js +69 -30
  85. package/dist/src/app-opentui/runtime.d.ts +44 -1
  86. package/dist/src/app-opentui/runtime.js +3231 -1363
  87. package/dist/src/app-opentui/scenes/command.js +20 -6
  88. package/dist/src/app-opentui/scenes/doctor.js +176 -11
  89. package/dist/src/app-opentui/scenes/error.js +20 -10
  90. package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +2 -0
  91. package/dist/src/app-opentui/scenes/family-domains/agent.js +348 -0
  92. package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +2 -0
  93. package/dist/src/app-opentui/scenes/family-domains/browser.js +195 -0
  94. package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +2 -0
  95. package/dist/src/app-opentui/scenes/family-domains/dist.js +243 -0
  96. package/dist/src/app-opentui/scenes/family-domains/git.d.ts +2 -0
  97. package/dist/src/app-opentui/scenes/family-domains/git.js +195 -0
  98. package/dist/src/app-opentui/scenes/family-domains/github.d.ts +2 -0
  99. package/dist/src/app-opentui/scenes/family-domains/github.js +274 -0
  100. package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +2 -0
  101. package/dist/src/app-opentui/scenes/family-domains/harness.js +152 -0
  102. package/dist/src/app-opentui/scenes/family-domains/index.d.ts +4 -0
  103. package/dist/src/app-opentui/scenes/family-domains/index.js +1679 -0
  104. package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +76 -0
  105. package/dist/src/app-opentui/scenes/family-domains/kit.js +305 -0
  106. package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +2 -0
  107. package/dist/src/app-opentui/scenes/family-domains/profile.js +212 -0
  108. package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +2 -0
  109. package/dist/src/app-opentui/scenes/family-domains/queue.js +146 -0
  110. package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +2 -0
  111. package/dist/src/app-opentui/scenes/family-domains/remote.js +518 -0
  112. package/dist/src/app-opentui/scenes/family-domains/review.d.ts +2 -0
  113. package/dist/src/app-opentui/scenes/family-domains/review.js +280 -0
  114. package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +2 -0
  115. package/dist/src/app-opentui/scenes/family-domains/setup.js +267 -0
  116. package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +2 -0
  117. package/dist/src/app-opentui/scenes/family-domains/stats.js +370 -0
  118. package/dist/src/app-opentui/scenes/family.d.ts +3 -0
  119. package/dist/src/app-opentui/scenes/family.js +2144 -0
  120. package/dist/src/app-opentui/scenes/fleet.js +521 -31
  121. package/dist/src/app-opentui/scenes/handoff.js +204 -12
  122. package/dist/src/app-opentui/scenes/help.js +609 -40
  123. package/dist/src/app-opentui/scenes/inbox.js +278 -17
  124. package/dist/src/app-opentui/scenes/init.js +84 -39
  125. package/dist/src/app-opentui/scenes/inspect.d.ts +3 -0
  126. package/dist/src/app-opentui/scenes/inspect.js +793 -0
  127. package/dist/src/app-opentui/scenes/main.js +218 -39
  128. package/dist/src/app-opentui/scenes/pi.d.ts +3 -0
  129. package/dist/src/app-opentui/scenes/pi.js +508 -0
  130. package/dist/src/app-opentui/scenes/plugin.d.ts +3 -0
  131. package/dist/src/app-opentui/scenes/plugin.js +486 -0
  132. package/dist/src/app-opentui/scenes/repo.d.ts +3 -0
  133. package/dist/src/app-opentui/scenes/repo.js +424 -0
  134. package/dist/src/app-opentui/scenes/run-detail.js +333 -20
  135. package/dist/src/app-opentui/scenes/server.js +181 -15
  136. package/dist/src/app-opentui/scenes/tasks.js +486 -31
  137. package/dist/src/app-opentui/scenes/workspace.d.ts +3 -0
  138. package/dist/src/app-opentui/scenes/workspace.js +426 -0
  139. package/dist/src/app-opentui/selectable.d.ts +19 -0
  140. package/dist/src/app-opentui/selectable.js +79 -0
  141. package/dist/src/app-opentui/state.js +83 -30
  142. package/dist/src/app-opentui/surface-catalog.d.ts +20 -0
  143. package/dist/src/app-opentui/surface-catalog.js +540 -0
  144. package/dist/src/app-opentui/theme.d.ts +28 -6
  145. package/dist/src/app-opentui/theme.js +61 -8
  146. package/dist/src/app-opentui/types.d.ts +121 -4
  147. package/dist/src/commands/_authority-runs.d.ts +1 -1
  148. package/dist/src/commands/_authority-runs.js +2 -12
  149. package/dist/src/commands/_help-catalog.js +95 -15
  150. package/dist/src/commands/_operator-view.js +34 -2
  151. package/dist/src/commands/_pi-frontend.d.ts +2 -0
  152. package/dist/src/commands/_pi-frontend.js +34 -0
  153. package/dist/src/commands/_server-events.d.ts +26 -0
  154. package/dist/src/commands/_server-events.js +310 -0
  155. package/dist/src/commands/agent.js +2 -12
  156. package/dist/src/commands/run.js +34 -2
  157. package/dist/src/commands/server.js +2 -12
  158. package/dist/src/commands/stats.js +95 -15
  159. package/dist/src/commands/task-run-driver.js +2 -12
  160. package/dist/src/commands/task.js +131 -29
  161. package/dist/src/commands.js +192 -31
  162. package/dist/src/index.js +192 -31
  163. package/package.json +11 -9
@@ -0,0 +1,424 @@
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
+ function statusColor(status) {
42
+ switch (status) {
43
+ case "success":
44
+ case "completed":
45
+ case "merged":
46
+ return RIG_UI.lime;
47
+ case "running":
48
+ case "preparing":
49
+ case "created":
50
+ case "validating":
51
+ case "reviewing":
52
+ case "closing-out":
53
+ case "stopping":
54
+ case "loading":
55
+ case "action":
56
+ return RIG_UI.cyan;
57
+ case "needs-attention":
58
+ case "needs_attention":
59
+ return RIG_UI.yellow;
60
+ case "failed":
61
+ case "error":
62
+ return RIG_UI.red;
63
+ default:
64
+ return RIG_UI.ink3;
65
+ }
66
+ }
67
+ function statusGlyph(status) {
68
+ switch (status) {
69
+ case "success":
70
+ case "completed":
71
+ case "merged":
72
+ return "\u2713";
73
+ case "running":
74
+ return "\u25CF";
75
+ case "preparing":
76
+ case "created":
77
+ case "validating":
78
+ case "reviewing":
79
+ case "closing-out":
80
+ case "stopping":
81
+ case "loading":
82
+ case "action":
83
+ return "\u25D0";
84
+ case "needs-attention":
85
+ case "needs_attention":
86
+ return "\u26A0";
87
+ case "failed":
88
+ case "error":
89
+ return "\u2717";
90
+ default:
91
+ return "\xB7";
92
+ }
93
+ }
94
+ function noColorActive() {
95
+ const noColor = process.env.NO_COLOR;
96
+ if (noColor !== undefined && noColor !== "") {
97
+ return true;
98
+ }
99
+ return process.env.RIG_NO_COLOR !== undefined;
100
+ }
101
+ function statusLabel(status) {
102
+ return {
103
+ glyph: statusGlyph(status),
104
+ color: noColorActive() ? RIG_UI.ink : statusColor(status)
105
+ };
106
+ }
107
+
108
+ // packages/cli/src/app-opentui/drone.ts
109
+ import { RGBA, StyledText, TextAttributes as TextAttributes2 } from "@opentui/core";
110
+ var MINI_DRONE = [
111
+ "(!!!) (!!!)",
112
+ " \\%==%/ ",
113
+ " %%?%% ",
114
+ " /%==%\\ ",
115
+ "(!!!) (!!!)"
116
+ ];
117
+ var LEAD_MARK = [
118
+ " .-=-. ",
119
+ "=%%?%%=",
120
+ " '-=-' "
121
+ ];
122
+ var BLADE_FRAMES = ["---", "\\\\\\", "|||", "///"];
123
+ var EYE_FRAMES = ["o", "@", "\u2022", "."];
124
+ var COLOR = {
125
+ body: RGBA.fromHex(RIG_UI.lime),
126
+ mini: RGBA.fromHex(RIG_UI.limeDim),
127
+ rotor: RGBA.fromHex(RIG_UI.cyan),
128
+ path: RGBA.fromHex(RIG_UI.cyan),
129
+ eye: RGBA.fromHex(RIG_UI.ink),
130
+ dim: RGBA.fromHex(RIG_UI.ink4),
131
+ ink: RGBA.fromHex(RIG_UI.ink2)
132
+ };
133
+ function bladeForTick(tick, phase = 0) {
134
+ return BLADE_FRAMES[(Math.floor(tick / 3) + phase) % BLADE_FRAMES.length];
135
+ }
136
+ function eyeForTick(tick, phase = 0) {
137
+ const pulse = Math.sin(tick * 0.09 + phase);
138
+ return pulse > 0.55 ? EYE_FRAMES[1] : pulse > 0.1 ? EYE_FRAMES[0] : pulse > -0.45 ? EYE_FRAMES[2] : EYE_FRAMES[3];
139
+ }
140
+ function chunk(text, fg, bold = false, dim = false) {
141
+ let attributes = TextAttributes2.NONE;
142
+ if (bold)
143
+ attributes |= TextAttributes2.BOLD;
144
+ if (dim)
145
+ attributes |= TextAttributes2.DIM;
146
+ return { __isChunk: true, text, fg, ...attributes !== TextAttributes2.NONE ? { attributes } : {} };
147
+ }
148
+ function styledLine(text, colorFor) {
149
+ const chunks = [];
150
+ let run = "";
151
+ let runColor = null;
152
+ const flush = () => {
153
+ if (!run || !runColor)
154
+ return;
155
+ chunks.push(chunk(run, COLOR[runColor], runColor === "body" || runColor === "eye", runColor === "dim"));
156
+ run = "";
157
+ };
158
+ for (const char of text) {
159
+ const next = colorFor(char);
160
+ if (next !== runColor) {
161
+ flush();
162
+ runColor = next;
163
+ }
164
+ run += char;
165
+ }
166
+ flush();
167
+ return new StyledText(chunks.length > 0 ? chunks : [chunk("", COLOR.ink)]);
168
+ }
169
+ function droneColor(char) {
170
+ if (char === "?" || char === "o" || char === "@" || char === "\u2022")
171
+ return "eye";
172
+ if (char === "%" || char === "=")
173
+ return "mini";
174
+ if (char === "$")
175
+ return "body";
176
+ if (char === "(" || char === ")" || char === "/" || char === "\\" || char === "|" || char === "-")
177
+ return "rotor";
178
+ if (char === "\xB7" || char === "\u2022" || char === "'" || char === ".")
179
+ return "path";
180
+ if (char.trim() === "")
181
+ return "dim";
182
+ return "ink";
183
+ }
184
+ function motionColor(char) {
185
+ if (char === "\u25CF" || char === "\u25C6" || char === "\u25C9")
186
+ return "body";
187
+ if (char === "\u2022" || char === "\xB7" || char === "\u2500" || char === "\u2502" || char === "\u2571" || char === "\u2572" || char === "\u256D" || char === "\u256E" || char === "\u2570" || char === "\u256F")
188
+ return "path";
189
+ if (char === "\u258C" || char === "\u2590" || char === "\u2581" || char === "\u2594")
190
+ return "mini";
191
+ return droneColor(char);
192
+ }
193
+ function materializeDrone(lines, tick, phase = 0) {
194
+ const blade = bladeForTick(tick, phase);
195
+ const eye = eyeForTick(tick, phase);
196
+ return lines.map((line) => line.replaceAll("!!!", blade).replaceAll("?", eye));
197
+ }
198
+ function miniDroneLines(tick, align = "left", phase = 0) {
199
+ return materializeDrone(MINI_DRONE, tick, phase).map((text) => ({
200
+ text,
201
+ styledText: styledLine(text, droneColor),
202
+ fg: RIG_UI.limeDim,
203
+ align
204
+ }));
205
+ }
206
+ function brandFleetLines(tick, align = "center") {
207
+ const left = materializeDrone(MINI_DRONE, tick, 0);
208
+ const right = materializeDrone(MINI_DRONE, tick, 2);
209
+ const lead = materializeDrone(LEAD_MARK, tick, 1);
210
+ const packet = ["\xB7", "\u2022", "\u25CF", "\u2022"][Math.floor(tick / 2) % 4];
211
+ const bridge = [
212
+ ` ${left[0]} ${lead[0]} ${right[0]}`,
213
+ ` ${left[1]} \xB7\u2500\u2500${packet}\u2500\u2500\xB7 ${lead[1]} \xB7\u2500\u2500${packet}\u2500\u2500\xB7 ${right[1]}`,
214
+ ` ${left[2]} \xB7' '${lead[2]}' '\xB7 ${right[2]}`,
215
+ ` ${left[3]} \u2572 signal bus \u2571 ${right[3]}`,
216
+ ` ${left[4]} \xB7\u2500\u2500\u2500${packet}\u2500\u2500\u2500\u2500\u2500\u2500${packet}\u2500\u2500\u2500\xB7 ${right[4]}`
217
+ ];
218
+ return bridge.map((text) => ({
219
+ text,
220
+ styledText: styledLine(text, motionColor),
221
+ fg: RIG_UI.limeDim,
222
+ align
223
+ }));
224
+ }
225
+ function actionDrone(tick, phase = 0) {
226
+ const blade = bladeForTick(tick, phase);
227
+ const eye = eyeForTick(tick, phase);
228
+ return `(${blade})\u2572${eye}\u2571(${blade})`;
229
+ }
230
+ function actionDroneLine(tick, text, fg = RIG_UI.ink2) {
231
+ const prefix = actionDrone(tick);
232
+ const content = `${prefix} ${text}`;
233
+ return { text: content, styledText: styledLine(content, motionColor), fg, align: "center" };
234
+ }
235
+
236
+ // packages/cli/src/app-opentui/render/scene.ts
237
+ function line(text, options = {}) {
238
+ return { text, ...options };
239
+ }
240
+ function blank() {
241
+ return { text: "" };
242
+ }
243
+ function deckRow(input) {
244
+ const prefix = input.active ? "\u25B8" : " ";
245
+ const label = input.label.toUpperCase().padEnd(10);
246
+ return line(`${prefix} ${label} ${input.detail}`, {
247
+ fg: input.active ? RIG_UI.lime : RIG_UI.ink2,
248
+ bold: input.active,
249
+ selectableIndex: input.index,
250
+ activateOnClick: input.activateOnClick
251
+ });
252
+ }
253
+ function loadingRows(label, tick = 0, compact = false) {
254
+ const mascot = compact ? miniDroneLines(tick, "center") : brandFleetLines(tick, "center");
255
+ return [
256
+ blank(),
257
+ ...mascot,
258
+ blank(),
259
+ { ...actionDroneLine(tick, `loading ${label}\u2026`, RIG_UI.cyan), align: "center" }
260
+ ];
261
+ }
262
+ function errorBanner(message, hint) {
263
+ return [
264
+ line(`\u2717 failed to load \u2014 ${message}`, { fg: RIG_UI.red, bold: true }),
265
+ ...hint ? [line(` ${hint}`, { fg: RIG_UI.ink3 })] : [],
266
+ line(" select refresh/retry below", { fg: RIG_UI.ink4 }),
267
+ line("", { fg: RIG_UI.ink3 })
268
+ ];
269
+ }
270
+ function lastRefreshError(state) {
271
+ const value = state.data.lastRefreshError;
272
+ return typeof value === "string" && value.trim() ? value : undefined;
273
+ }
274
+ function makeSceneFrame(input) {
275
+ return input;
276
+ }
277
+
278
+ // packages/cli/src/app-opentui/selectable.ts
279
+ function selectableDeckRow(deck, item) {
280
+ return { ...deckRow({ ...deck, activateOnClick: true }), selectable: item };
281
+ }
282
+ function withSelectable(line2, item) {
283
+ return { ...line2, selectable: item, activateOnClick: true };
284
+ }
285
+
286
+ // packages/cli/src/app-opentui/scenes/repo.ts
287
+ var REPO_RESET_ITEM = {
288
+ id: "repo-reset",
289
+ label: "reset",
290
+ intent: { scene: "repo", argv: ["repo", "reset-baseline"], action: { kind: "refresh", label: "Reset baseline", payload: { repoReset: true, confirm: true } } },
291
+ message: "reset baseline to origin/main"
292
+ };
293
+ var REPO_ACTIONS = [
294
+ { detail: "re-read baseline pins, active task, and managed repos", item: { id: "repo-refresh", label: "refresh", intent: { scene: "repo", argv: ["repo", "status"], action: { kind: "refresh", label: "Refresh repo state" } }, message: "reload repo state" } },
295
+ { detail: "sync the repo baseline for the active task", item: { id: "repo-sync", label: "sync", intent: { scene: "command", argv: ["repo", "sync"], action: { kind: "command-run", label: "Sync repo baseline" } }, message: "sync repo baseline" } },
296
+ { detail: "show git status through the policy-gated harness helper", item: { id: "repo-git", label: "git status", intent: { scene: "command", argv: ["git", "status"], action: { kind: "command-run", label: "Git status" } }, message: "git status" } },
297
+ { detail: "reset the WHOLE baseline to origin/main (asks to confirm)", item: REPO_RESET_ITEM }
298
+ ];
299
+ function snapshot(state) {
300
+ const value = state.data.repo;
301
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
302
+ }
303
+ function selectedRepo(state) {
304
+ const value = state.data.selectedRepo;
305
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
306
+ }
307
+ var REPO_BACK_ITEM = {
308
+ id: "repo-back",
309
+ label: "back",
310
+ data: { selectedRepo: undefined },
311
+ message: "back to repo overview"
312
+ };
313
+ function gitStatusLine(git) {
314
+ if (!git || !git.available) {
315
+ return line(` git status not checked out`, { fg: RIG_UI.ink4 });
316
+ }
317
+ const drift = git.ahead === 0 && git.behind === 0 ? "in sync with pin" : `${git.ahead} ahead \xB7 ${git.behind} behind pin`;
318
+ const tree = git.clean ? "clean" : `${git.dirtyCount} change${git.dirtyCount === 1 ? "" : "s"}`;
319
+ return line(` git status ${git.branch}@${git.head} \xB7 ${tree} \xB7 ${drift}`, { fg: git.clean ? RIG_UI.ink2 : RIG_UI.yellow });
320
+ }
321
+ function gitBadge(git) {
322
+ if (!git || !git.available)
323
+ return "\xB7";
324
+ if (!git.clean)
325
+ return `\u2731${git.dirtyCount}`;
326
+ if (git.ahead > 0 || git.behind > 0)
327
+ return `\u2195${git.ahead}/${git.behind}`;
328
+ return "\u2713";
329
+ }
330
+ function repoDetail(repo, entry) {
331
+ const { glyph, color } = statusLabel(entry.git && entry.git.available && !entry.git.clean ? "needs-attention" : "success");
332
+ const pin = repo.baselinePins.find((candidate) => candidate.alias === entry.alias);
333
+ return [
334
+ line(`${glyph} ${entry.alias}`, { fg: color, bold: true }),
335
+ blank(),
336
+ line(` default branch ${entry.defaultBranch}`, { fg: RIG_UI.ink2 }),
337
+ line(` remote ${entry.defaultRemoteUrl}`, { fg: RIG_UI.ink3 }),
338
+ line(` baseline pin ${pin ? pin.commit.slice(0, 12) : "(none recorded)"}`, { fg: pin ? RIG_UI.ink2 : RIG_UI.ink4 }),
339
+ gitStatusLine(entry.git),
340
+ blank(),
341
+ line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
342
+ selectableDeckRow({ label: "sync", detail: `re-pin ${entry.alias} from ${entry.defaultBranch} (in-app)`, index: 0, active: false }, { id: `repo-sync:${entry.alias}`, label: `sync ${entry.alias}`, intent: { scene: "repo", argv: ["repo", "sync"], action: { kind: "refresh", label: `Sync ${entry.alias}`, payload: { repoSync: entry.alias } } }, message: `sync ${entry.alias}` }),
343
+ selectableDeckRow({ label: "reset", detail: `reset the whole baseline to origin/main (asks to confirm)`, index: 1, active: false }, { id: `repo-reset:${entry.alias}`, label: `reset baseline`, intent: { scene: "repo", argv: ["repo", "reset-baseline"], action: { kind: "refresh", label: "Reset baseline", payload: { repoReset: true, confirm: true } } }, message: `reset baseline to origin/main` }),
344
+ blank(),
345
+ selectableDeckRow({ label: "back", detail: "return to the repo overview", index: 2, active: false }, REPO_BACK_ITEM)
346
+ ];
347
+ }
348
+ function panelWidth(layout) {
349
+ return layout?.centerWidth ?? 118;
350
+ }
351
+ function panelHeight(layout) {
352
+ return Math.max(18, layout?.centerHeight ?? 34);
353
+ }
354
+ function statusRows(repo) {
355
+ const taskGlyph = statusLabel(repo.activeTaskId ? "success" : "created");
356
+ const rows = [
357
+ line(`${taskGlyph.glyph} active task ${repo.activeTaskId ?? "none"}`, { fg: repo.activeTaskId ? taskGlyph.color : RIG_UI.ink4 }),
358
+ line(` layout ${repo.flatLayout ? "flat (project root is the repo)" : `${repo.managedRepos.length} managed repos`}`, { fg: RIG_UI.ink3 }),
359
+ blank(),
360
+ line(`BASELINE PINS \xB7 ${repo.baselinePins.length}`, { fg: RIG_UI.ink3, bold: true }),
361
+ ...repo.baselinePins.length > 0 ? repo.baselinePins.map((pin) => {
362
+ const managed = repo.managedRepos.find((entry) => entry.alias === pin.alias);
363
+ const row = line(` ${pin.alias.padEnd(20)} ${pin.commit.slice(0, 12)}${managed ? " \u203A" : ""}`, { fg: RIG_UI.ink2 });
364
+ return managed ? withSelectable(row, { id: `repo-pin:${pin.alias}`, label: pin.alias, data: { selectedRepo: pin.alias }, message: `open ${pin.alias} (pinned ${pin.commit.slice(0, 12)})` }) : row;
365
+ }) : [line(" (none recorded)", { fg: RIG_UI.ink4 })]
366
+ ];
367
+ if (repo.managedRepos.length > 0) {
368
+ rows.push(blank(), line(`MANAGED REPOS \xB7 ${repo.managedRepos.length}`, { fg: RIG_UI.ink3, bold: true }), ...repo.managedRepos.map((entry) => withSelectable(line(` ${gitBadge(entry.git).padEnd(6)} ${entry.alias.padEnd(20)} ${entry.defaultBranch} \xB7 ${entry.defaultRemoteUrl} \u203A`, { fg: entry.git && entry.git.available && !entry.git.clean ? RIG_UI.yellow : RIG_UI.ink3 }), { id: `repo-detail:${entry.alias}`, label: entry.alias, data: { selectedRepo: entry.alias }, message: `open ${entry.alias} detail` })));
369
+ }
370
+ return rows;
371
+ }
372
+ function renderRepoScene(state, layout) {
373
+ const repo = snapshot(state);
374
+ const selected = Math.max(0, Math.min(REPO_ACTIONS.length - 1, state.selection.index));
375
+ const loading = state.status === "loading" && !repo;
376
+ const refreshError = lastRefreshError(state);
377
+ const drilled = selectedRepo(state);
378
+ const detailEntry = repo && drilled ? repo.managedRepos.find((entry) => entry.alias === drilled) : undefined;
379
+ const panelLines = detailEntry && repo ? [
380
+ ...refreshError && !state.error ? errorBanner(refreshError) : [],
381
+ line(`MANAGED REPO \xB7 ${detailEntry.alias}`, { fg: RIG_UI.ink3, bold: true }),
382
+ blank(),
383
+ ...repoDetail(repo, detailEntry)
384
+ ] : [
385
+ ...refreshError && !state.error ? errorBanner(refreshError) : [],
386
+ line("repo baseline + harness helpers", { fg: RIG_UI.ink3 }),
387
+ blank(),
388
+ line("ACTIONS", { fg: RIG_UI.ink3, bold: true }),
389
+ ...REPO_ACTIONS.map(({ detail, item }, index) => selectableDeckRow({ label: item.label, detail, index, active: selected === index }, item)),
390
+ blank(),
391
+ line("STATUS", { fg: RIG_UI.ink3, bold: true }),
392
+ ...loading ? loadingRows("repo state", state.tick) : repo ? statusRows(repo) : [line("repo state pending", { fg: RIG_UI.ink3 })],
393
+ blank(),
394
+ line("enter/click a managed repo to drill in \xB7 actions open the command PTY \xB7 refresh reloads in-app", { fg: RIG_UI.ink4 })
395
+ ];
396
+ return makeSceneFrame({
397
+ scene: "repo",
398
+ title: "Repo",
399
+ lines: [],
400
+ panels: [{
401
+ id: "repo-state",
402
+ top: 0,
403
+ width: panelWidth(layout),
404
+ height: panelHeight(layout),
405
+ lines: panelLines,
406
+ backgroundColor: RIG_UI.panel,
407
+ backgroundAlpha: 184,
408
+ opacity: 0.98,
409
+ border: false,
410
+ stickyScroll: true,
411
+ stickyStart: "top",
412
+ chrome: "ad-terminal",
413
+ headerText: detailEntry ? `rig repo \xB7 ${detailEntry.alias}` : repo ? `rig repo \xB7 ${repo.flatLayout ? "flat layout" : `${repo.managedRepos.length} managed`} \xB7 ${repo.baselinePins.length} pins` : "rig repo",
414
+ headerHeight: 3,
415
+ paddingX: layout?.compact ? 3 : 5,
416
+ paddingY: 2
417
+ }],
418
+ footer: { message: detailEntry ? `${detailEntry.alias} \u2014 back returns to overview` : repo ? repo.flatLayout ? "flat layout" : `${repo.managedRepos.length} managed repos` : "loading repo state" },
419
+ live: state.status === "action" || !repo
420
+ });
421
+ }
422
+ export {
423
+ renderRepoScene
424
+ };