4runr-os 2.1.11 → 2.1.13

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.
@@ -0,0 +1,70 @@
1
+ /**
2
+ * MK2 Layout Engine - Single Source of Truth for Layout Computation
3
+ *
4
+ * This engine properly accounts for:
5
+ * - Borders (consume 2 cols/rows)
6
+ * - Safe margins (browser terminals need extra space)
7
+ * - Gutters between panels
8
+ * - Compact layout fallback for small terminals
9
+ */
10
+ export interface LayoutRect {
11
+ x: number;
12
+ y: number;
13
+ w: number;
14
+ h: number;
15
+ }
16
+ export type LayoutMode = 'wide' | 'compact';
17
+ export interface LayoutSpec {
18
+ mode: LayoutMode;
19
+ safeW: number;
20
+ safeH: number;
21
+ cols: number;
22
+ rows: number;
23
+ rects: {
24
+ posture: LayoutRect;
25
+ resources: LayoutRect;
26
+ assets: LayoutRect;
27
+ operations: LayoutRect;
28
+ network: LayoutRect;
29
+ capabilities: LayoutRect;
30
+ command: LayoutRect;
31
+ };
32
+ debug: {
33
+ leftW: number;
34
+ centerW: number;
35
+ rightW: number;
36
+ leftX: number;
37
+ centerX: number;
38
+ rightX: number;
39
+ rightEdge: number;
40
+ };
41
+ }
42
+ export declare const SAFE_RIGHT_MARGIN = 2;
43
+ export declare const SAFE_BOTTOM_MARGIN = 1;
44
+ export declare const TOP_GUARD = 1;
45
+ export declare const GUTTER_X = 1;
46
+ export declare const GUTTER_Y = 1;
47
+ export declare const BORDER_PAD_X = 2;
48
+ export declare const BORDER_PAD_Y = 2;
49
+ export declare const MIN_CENTER_W = 60;
50
+ export declare const MIN_TERMINAL_COLS = 120;
51
+ export declare const MIN_TERMINAL_ROWS = 30;
52
+ /**
53
+ * Compute safe drawing area (accounts for margins)
54
+ */
55
+ export declare function getSafeCanvas(cols: number, rows: number): {
56
+ safeW: number;
57
+ safeH: number;
58
+ };
59
+ /**
60
+ * Validate that all rects fit within safe bounds
61
+ */
62
+ export declare function validateLayout(spec: LayoutSpec): {
63
+ valid: boolean;
64
+ errors: string[];
65
+ };
66
+ /**
67
+ * Compute layout - main entry point
68
+ */
69
+ export declare function computeLayout(cols: number, rows: number): LayoutSpec;
70
+ //# sourceMappingURL=layoutEngine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layoutEngine.d.ts","sourceRoot":"","sources":["../../../src/tui_mk2/layout/layoutEngine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE;QACL,OAAO,EAAE,UAAU,CAAC;QACpB,SAAS,EAAE,UAAU,CAAC;QACtB,MAAM,EAAE,UAAU,CAAC;QACnB,UAAU,EAAE,UAAU,CAAC;QACvB,OAAO,EAAE,UAAU,CAAC;QACpB,YAAY,EAAE,UAAU,CAAC;QACzB,OAAO,EAAE,UAAU,CAAC;KACrB,CAAC;IAEF,KAAK,EAAE;QACL,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;QACf,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAGD,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,kBAAkB,IAAI,CAAC;AACpC,eAAO,MAAM,SAAS,IAAI,CAAC;AAC3B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,QAAQ,IAAI,CAAC;AAC1B,eAAO,MAAM,YAAY,IAAI,CAAC;AAC9B,eAAO,MAAM,YAAY,IAAI,CAAC;AAG9B,eAAO,MAAM,YAAY,KAAK,CAAC;AAC/B,eAAO,MAAM,iBAAiB,MAAM,CAAC;AACrC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAI1F;AAwOD;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAyBrF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAsCpE"}
@@ -0,0 +1,297 @@
1
+ /**
2
+ * MK2 Layout Engine - Single Source of Truth for Layout Computation
3
+ *
4
+ * This engine properly accounts for:
5
+ * - Borders (consume 2 cols/rows)
6
+ * - Safe margins (browser terminals need extra space)
7
+ * - Gutters between panels
8
+ * - Compact layout fallback for small terminals
9
+ */
10
+ // Constants - DO NOT CHANGE without testing
11
+ export const SAFE_RIGHT_MARGIN = 2; // Browser terminals need 2 cols
12
+ export const SAFE_BOTTOM_MARGIN = 1; // Reserve bottom row
13
+ export const TOP_GUARD = 1; // Reserve top row for debug overlay
14
+ export const GUTTER_X = 1; // Horizontal spacing between columns
15
+ export const GUTTER_Y = 1; // Vertical spacing between panels
16
+ export const BORDER_PAD_X = 2; // Left + right border consume 2 cols
17
+ export const BORDER_PAD_Y = 2; // Top + bottom border consume 2 rows
18
+ // Minimum sizes
19
+ export const MIN_CENTER_W = 60; // Minimum center column width
20
+ export const MIN_TERMINAL_COLS = 120;
21
+ export const MIN_TERMINAL_ROWS = 30; // Reduced from 35 for graceful degradation
22
+ /**
23
+ * Compute safe drawing area (accounts for margins)
24
+ */
25
+ export function getSafeCanvas(cols, rows) {
26
+ const safeW = Math.max(0, cols - SAFE_RIGHT_MARGIN);
27
+ const safeH = Math.max(0, rows - TOP_GUARD - SAFE_BOTTOM_MARGIN);
28
+ return { safeW, safeH };
29
+ }
30
+ /**
31
+ * Clamp a value between min and max
32
+ */
33
+ function clamp(value, min, max) {
34
+ return Math.max(min, Math.min(max, value));
35
+ }
36
+ /**
37
+ * Compute wide layout (3 columns)
38
+ */
39
+ function computeWideLayout(cols, rows, safeW, safeH) {
40
+ // Column widths (percentage-based with clamps)
41
+ let leftW = clamp(Math.floor(safeW * 0.18), 26, 34);
42
+ let rightW = clamp(Math.floor(safeW * 0.20), 26, 34);
43
+ let centerW = safeW - leftW - rightW - (GUTTER_X * 2);
44
+ // If center too small, shrink side columns
45
+ if (centerW < MIN_CENTER_W) {
46
+ const deficit = MIN_CENTER_W - centerW;
47
+ const shrinkLeft = Math.min(deficit, leftW - 22);
48
+ leftW -= shrinkLeft;
49
+ const shrinkRight = Math.min(deficit - shrinkLeft, rightW - 22);
50
+ rightW -= shrinkRight;
51
+ centerW = safeW - leftW - rightW - (GUTTER_X * 2);
52
+ }
53
+ // Validate center is still big enough
54
+ if (centerW < MIN_CENTER_W) {
55
+ return null; // Fall back to compact
56
+ }
57
+ // X positions
58
+ const leftX = 0;
59
+ const centerX = leftW + GUTTER_X;
60
+ const rightX = leftW + GUTTER_X + centerW + GUTTER_X;
61
+ // Validate right edge doesn't exceed safeW
62
+ const rightEdge = rightX + rightW;
63
+ if (rightEdge > safeW) {
64
+ // Shrink center to make room
65
+ const overflow = rightEdge - safeW;
66
+ centerW = Math.max(MIN_CENTER_W, centerW - overflow);
67
+ const newRightX = leftW + GUTTER_X + centerW + GUTTER_X;
68
+ const newRightEdge = newRightX + rightW;
69
+ if (newRightEdge > safeW) {
70
+ // Still doesn't fit - shrink right column
71
+ rightW = safeW - newRightX;
72
+ if (rightW < 22) {
73
+ return null; // Fall back to compact
74
+ }
75
+ }
76
+ }
77
+ // Command bar height
78
+ const cmdH = 3;
79
+ const usableH = safeH - cmdH - GUTTER_Y;
80
+ // Left stack heights
81
+ const postureH = clamp(Math.floor(usableH * 0.22), 8, 12);
82
+ const resourcesH = clamp(Math.floor(usableH * 0.22), 8, 12);
83
+ const assetsH = Math.max(6, usableH - postureH - resourcesH - (GUTTER_Y * 2));
84
+ // Right stack heights
85
+ const networkH = clamp(Math.floor(usableH * 0.45), 10, 14);
86
+ const capabilitiesH = Math.max(6, usableH - networkH - GUTTER_Y);
87
+ // Center height
88
+ const operationsH = Math.max(6, usableH);
89
+ // Y positions (account for TOP_GUARD)
90
+ const leftY = TOP_GUARD;
91
+ const centerY = TOP_GUARD;
92
+ const rightY = TOP_GUARD;
93
+ const cmdY = TOP_GUARD + safeH - cmdH;
94
+ // Build rects
95
+ const rects = {
96
+ posture: {
97
+ x: leftX,
98
+ y: leftY,
99
+ w: leftW,
100
+ h: postureH,
101
+ },
102
+ resources: {
103
+ x: leftX,
104
+ y: leftY + postureH + GUTTER_Y,
105
+ w: leftW,
106
+ h: resourcesH,
107
+ },
108
+ assets: {
109
+ x: leftX,
110
+ y: leftY + postureH + GUTTER_Y + resourcesH + GUTTER_Y,
111
+ w: leftW,
112
+ h: assetsH,
113
+ },
114
+ operations: {
115
+ x: centerX,
116
+ y: centerY,
117
+ w: centerW,
118
+ h: operationsH,
119
+ },
120
+ network: {
121
+ x: rightX,
122
+ y: rightY,
123
+ w: rightW,
124
+ h: networkH,
125
+ },
126
+ capabilities: {
127
+ x: rightX,
128
+ y: rightY + networkH + GUTTER_Y,
129
+ w: rightW,
130
+ h: capabilitiesH,
131
+ },
132
+ command: {
133
+ x: 0,
134
+ y: cmdY,
135
+ w: safeW - 1, // Shrink by 1 for breathing room
136
+ h: cmdH,
137
+ },
138
+ };
139
+ return {
140
+ mode: 'wide',
141
+ safeW,
142
+ safeH,
143
+ cols,
144
+ rows,
145
+ rects,
146
+ debug: {
147
+ leftW,
148
+ centerW,
149
+ rightW,
150
+ leftX,
151
+ centerX,
152
+ rightX,
153
+ rightEdge: rightX + rightW,
154
+ },
155
+ };
156
+ }
157
+ /**
158
+ * Compute compact layout (vertical stack for small terminals)
159
+ */
160
+ function computeCompactLayout(cols, rows, safeW, safeH) {
161
+ // Compact: Stack everything vertically
162
+ // Top: OPERATIONS (biggest)
163
+ // Middle: NETWORK + CAPABILITIES (side by side)
164
+ // Bottom: POSTURE + RESOURCES + ASSETS (stacked)
165
+ const cmdH = 3;
166
+ const usableH = safeH - cmdH - GUTTER_Y;
167
+ // Operations takes 50% of usable height
168
+ const operationsH = Math.floor(usableH * 0.5);
169
+ // Middle section: NETWORK and CAPABILITIES side by side
170
+ const middleH = Math.floor(usableH * 0.3);
171
+ const middleW = Math.floor((safeW - GUTTER_X) / 2);
172
+ // Bottom section: POSTURE, RESOURCES, ASSETS stacked
173
+ const bottomH = usableH - operationsH - middleH - (GUTTER_Y * 2);
174
+ const bottomPanelH = Math.floor(bottomH / 3);
175
+ const y = TOP_GUARD;
176
+ const cmdY = TOP_GUARD + safeH - cmdH;
177
+ const rects = {
178
+ operations: {
179
+ x: 0,
180
+ y: y,
181
+ w: safeW - 1,
182
+ h: operationsH,
183
+ },
184
+ network: {
185
+ x: 0,
186
+ y: y + operationsH + GUTTER_Y,
187
+ w: middleW,
188
+ h: middleH,
189
+ },
190
+ capabilities: {
191
+ x: middleW + GUTTER_X,
192
+ y: y + operationsH + GUTTER_Y,
193
+ w: safeW - middleW - GUTTER_X - 1,
194
+ h: middleH,
195
+ },
196
+ posture: {
197
+ x: 0,
198
+ y: y + operationsH + GUTTER_Y + middleH + GUTTER_Y,
199
+ w: safeW - 1,
200
+ h: bottomPanelH,
201
+ },
202
+ resources: {
203
+ x: 0,
204
+ y: y + operationsH + GUTTER_Y + middleH + GUTTER_Y + bottomPanelH + GUTTER_Y,
205
+ w: safeW - 1,
206
+ h: bottomPanelH,
207
+ },
208
+ assets: {
209
+ x: 0,
210
+ y: y + operationsH + GUTTER_Y + middleH + GUTTER_Y + (bottomPanelH * 2) + (GUTTER_Y * 2),
211
+ w: safeW - 1,
212
+ h: Math.max(6, bottomH - (bottomPanelH * 2) - (GUTTER_Y * 2)),
213
+ },
214
+ command: {
215
+ x: 0,
216
+ y: cmdY,
217
+ w: safeW - 1,
218
+ h: cmdH,
219
+ },
220
+ };
221
+ return {
222
+ mode: 'compact',
223
+ safeW,
224
+ safeH,
225
+ cols,
226
+ rows,
227
+ rects,
228
+ debug: {
229
+ leftW: 0,
230
+ centerW: safeW - 1,
231
+ rightW: 0,
232
+ leftX: 0,
233
+ centerX: 0,
234
+ rightX: 0,
235
+ rightEdge: safeW - 1,
236
+ },
237
+ };
238
+ }
239
+ /**
240
+ * Validate that all rects fit within safe bounds
241
+ */
242
+ export function validateLayout(spec) {
243
+ const errors = [];
244
+ for (const [name, rect] of Object.entries(spec.rects)) {
245
+ const maxX = rect.x + rect.w;
246
+ const maxY = rect.y + rect.h;
247
+ if (rect.x < 0) {
248
+ errors.push(`${name}: x=${rect.x} < 0`);
249
+ }
250
+ if (rect.y < TOP_GUARD) {
251
+ errors.push(`${name}: y=${rect.y} < TOP_GUARD=${TOP_GUARD}`);
252
+ }
253
+ if (maxX > spec.safeW) {
254
+ errors.push(`${name}: maxX=${maxX} > safeW=${spec.safeW} (x=${rect.x} w=${rect.w})`);
255
+ }
256
+ if (maxY > spec.safeH + TOP_GUARD) {
257
+ errors.push(`${name}: maxY=${maxY} > safeMaxY=${spec.safeH + TOP_GUARD} (y=${rect.y} h=${rect.h})`);
258
+ }
259
+ }
260
+ return {
261
+ valid: errors.length === 0,
262
+ errors,
263
+ };
264
+ }
265
+ /**
266
+ * Compute layout - main entry point
267
+ */
268
+ export function computeLayout(cols, rows) {
269
+ // Minimum terminal size check (but don't hard fail - use compact)
270
+ if (cols < MIN_TERMINAL_COLS || rows < MIN_TERMINAL_ROWS) {
271
+ // Try compact layout even for very small terminals
272
+ const { safeW, safeH } = getSafeCanvas(cols, rows);
273
+ if (safeW < 40 || safeH < 10) {
274
+ throw new Error(`Terminal too small: ${cols}x${rows} (minimum ${MIN_TERMINAL_COLS}x${MIN_TERMINAL_ROWS})`);
275
+ }
276
+ }
277
+ const { safeW, safeH } = getSafeCanvas(cols, rows);
278
+ // Try wide layout first
279
+ const wideLayout = computeWideLayout(cols, rows, safeW, safeH);
280
+ if (wideLayout) {
281
+ // Validate wide layout
282
+ const validation = validateLayout(wideLayout);
283
+ if (validation.valid) {
284
+ return wideLayout;
285
+ }
286
+ // If validation fails, fall back to compact
287
+ }
288
+ // Fall back to compact layout
289
+ const compactLayout = computeCompactLayout(cols, rows, safeW, safeH);
290
+ const validation = validateLayout(compactLayout);
291
+ if (!validation.valid) {
292
+ // Even compact doesn't fit - this is a real error
293
+ throw new Error(`Layout validation failed: ${validation.errors.join('; ')}`);
294
+ }
295
+ return compactLayout;
296
+ }
297
+ //# sourceMappingURL=layoutEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layoutEngine.js","sourceRoot":"","sources":["../../../src/tui_mk2/layout/layoutEngine.ts"],"names":[],"mappings":"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"}
@@ -1,26 +1,33 @@
1
1
  /**
2
2
  * MK2 App - Main application entry point
3
3
  *
4
- * MK2 Phase 1B: Frame Lock + Placeholder Boxes
5
- * - 6 placeholder sections + bottom command bar
6
- * - Hard invariants, no scrollbars
7
- * - Stable across resize
4
+ * MK2 Hotfix: Kill Scrollbars + Fix Command Input
5
+ * - Increased guards (RIGHT_GUARD=4, BOTTOM_GUARD=3, TOP_GUARD=1)
6
+ * - Stricter clamping (>= not >)
7
+ * - Real command textbox with input handling
8
+ * - Focus and readInput() for server terminals
8
9
  */
9
10
  export declare class MK2App {
10
11
  private kernel;
11
12
  private boxes;
12
13
  private debugOverlay;
14
+ private commandBox;
15
+ private operationsBox;
13
16
  constructor();
14
17
  /**
15
18
  * Start MK2 App
16
19
  */
17
20
  start(): Promise<void>;
18
21
  /**
19
- * Render layout - Phase 1B: Frame Lock + Placeholder Boxes
22
+ * Render layout - MK2 Hotfix: Command textbox + input handling
20
23
  */
21
24
  private render;
22
25
  /**
23
- * Handle resize - Phase 1B: Hard rebuild
26
+ * Append text to operations box
27
+ */
28
+ private appendOps;
29
+ /**
30
+ * Handle resize - MK2 Hotfix: Preserve input focus
24
31
  */
25
32
  private handleResize;
26
33
  /**
@@ -29,6 +36,7 @@ export declare class MK2App {
29
36
  private destroyAll;
30
37
  /**
31
38
  * Create error box for terminal too small
39
+ * Shows required minimum and detected size, keeps app running
32
40
  */
33
41
  private createErrorBox;
34
42
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"mk2App.d.ts","sourceRoot":"","sources":["../../src/tui_mk2/mk2App.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,YAAY,CAA4B;;IAMhD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B;;OAEG;IACH,OAAO,CAAC,MAAM;IAiCd;;OAEG;YACW,YAAY;IAK1B;;OAEG;IACH,OAAO,CAAC,UAAU;IAyClB;;OAEG;IACH,OAAO,CAAC,cAAc;IAuBtB;;OAEG;IACH,IAAI,IAAI,IAAI;CAGb;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAuB9C"}
1
+ {"version":3,"file":"mk2App.d.ts","sourceRoot":"","sources":["../../src/tui_mk2/mk2App.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,aAAa,CAA4B;;IAMjD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAU5B;;OAEG;IACH,OAAO,CAAC,MAAM;IA4Hd;;OAEG;IACH,OAAO,CAAC,SAAS;IAgBjB;;OAEG;YACW,YAAY;IAM1B;;OAEG;IACH,OAAO,CAAC,UAAU;IAsDlB;;;OAGG;IACH,OAAO,CAAC,cAAc;IA4CtB;;OAEG;IACH,IAAI,IAAI,IAAI;CAGb;AAED;;GAEG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAuB9C"}
@@ -1,12 +1,14 @@
1
1
  /**
2
2
  * MK2 App - Main application entry point
3
3
  *
4
- * MK2 Phase 1B: Frame Lock + Placeholder Boxes
5
- * - 6 placeholder sections + bottom command bar
6
- * - Hard invariants, no scrollbars
7
- * - Stable across resize
4
+ * MK2 Hotfix: Kill Scrollbars + Fix Command Input
5
+ * - Increased guards (RIGHT_GUARD=4, BOTTOM_GUARD=3, TOP_GUARD=1)
6
+ * - Stricter clamping (>= not >)
7
+ * - Real command textbox with input handling
8
+ * - Focus and readInput() for server terminals
8
9
  */
9
10
  import { MK2Kernel } from './kernel.js';
11
+ import blessed from 'neo-blessed';
10
12
  import { computeLayout, getSafeCanvas } from './layout/computeLayout.js';
11
13
  import { applyLayout } from './layout/applyLayout.js';
12
14
  import { createDebugOverlay } from './debug/overlay.js';
@@ -14,6 +16,8 @@ export class MK2App {
14
16
  kernel;
15
17
  boxes = [];
16
18
  debugOverlay = null;
19
+ commandBox = null; // MK2 Hotfix: textbox type may not be in Widgets namespace
20
+ operationsBox = null;
17
21
  constructor() {
18
22
  this.kernel = new MK2Kernel();
19
23
  }
@@ -30,7 +34,7 @@ export class MK2App {
30
34
  });
31
35
  }
32
36
  /**
33
- * Render layout - Phase 1B: Frame Lock + Placeholder Boxes
37
+ * Render layout - MK2 Hotfix: Command textbox + input handling
34
38
  */
35
39
  render() {
36
40
  const screen = this.kernel.getScreen();
@@ -46,24 +50,122 @@ export class MK2App {
46
50
  const spec = computeLayout(cols, rows);
47
51
  // Create debug overlay (top line)
48
52
  this.debugOverlay = createDebugOverlay(screen, spec);
49
- // Apply layout - create all boxes
53
+ // Apply layout - create all boxes (except command)
50
54
  this.boxes = applyLayout(screen, spec);
55
+ // Find operations box for logging commands
56
+ this.operationsBox = this.boxes.find(b => {
57
+ const label = b.content || b.label || '';
58
+ return typeof label === 'string' && label.includes('OPERATIONS');
59
+ }) || this.boxes[3] || null;
60
+ // Create command textbox (MK2 Hotfix: Real textbox with input)
61
+ // Note: textbox may not be in blessed namespace directly, try (blessed as any).textbox
62
+ const Textbox = blessed.textbox || blessed.Textbox;
63
+ if (!Textbox) {
64
+ throw new Error('blessed.textbox not available - using fallback box');
65
+ }
66
+ this.commandBox = Textbox({
67
+ parent: screen,
68
+ top: spec.rects.command.y,
69
+ left: spec.rects.command.x,
70
+ width: spec.rects.command.w,
71
+ height: spec.rects.command.h,
72
+ border: { type: 'line' },
73
+ label: ' 4r ',
74
+ inputOnFocus: true,
75
+ keys: true,
76
+ mouse: false, // MK2 Hotfix: Don't rely on mouse
77
+ vi: false,
78
+ style: {
79
+ fg: 'cyan',
80
+ border: { fg: 'cyan' },
81
+ },
82
+ });
83
+ // MK2 Hotfix: Command submission handler
84
+ this.commandBox.on('submit', (value) => {
85
+ const text = (value || '').trim();
86
+ if (text) {
87
+ this.appendOps(`[CMD] ${text}`);
88
+ if (this.commandBox && typeof this.commandBox.clearValue === 'function') {
89
+ this.commandBox.clearValue();
90
+ }
91
+ screen.render();
92
+ }
93
+ });
94
+ // MK2 Hotfix: Keyboard handlers
95
+ screen.key([':', '/'], () => {
96
+ if (this.commandBox) {
97
+ this.commandBox.focus();
98
+ this.commandBox.readInput();
99
+ }
100
+ });
101
+ screen.key(['escape'], () => {
102
+ // Exit command mode - focus pop or next element
103
+ if (typeof screen.focusPop === 'function') {
104
+ screen.focusPop();
105
+ }
106
+ else if (typeof screen.focusNext === 'function') {
107
+ screen.focusNext();
108
+ }
109
+ screen.render();
110
+ });
111
+ screen.key(['C-c'], () => {
112
+ process.exit(0);
113
+ });
51
114
  // Render
52
115
  screen.render();
116
+ // MK2 Hotfix: Force focus and readInput after a short delay (critical for server terminals)
117
+ setTimeout(() => {
118
+ if (this.commandBox) {
119
+ if (typeof this.commandBox.focus === 'function') {
120
+ this.commandBox.focus();
121
+ }
122
+ if (typeof this.commandBox.readInput === 'function') {
123
+ this.commandBox.readInput();
124
+ }
125
+ screen.render();
126
+ }
127
+ }, 30);
53
128
  }
54
129
  catch (error) {
55
- // Terminal too small - show error box
130
+ // Terminal too small - show error overlay (don't crash)
56
131
  const { safeW, safeH } = getSafeCanvas(cols, rows);
57
- const errorBox = this.createErrorBox(screen, error instanceof Error ? error.message : String(error), safeW, safeH);
132
+ const errorMsg = error instanceof Error ? error.message : String(error);
133
+ const errorBox = this.createErrorBox(screen, errorMsg, cols, rows, safeW, safeH);
58
134
  screen.append(errorBox);
59
135
  screen.render();
136
+ // Keep app running so resizing fixes it
137
+ // Set up resize handler to retry layout
138
+ screen.on('resize', () => {
139
+ const newCols = screen.width || 80;
140
+ const newRows = screen.height || 24;
141
+ // Retry render on resize
142
+ setTimeout(() => {
143
+ this.render();
144
+ }, 100);
145
+ });
60
146
  }
61
147
  }
62
148
  /**
63
- * Handle resize - Phase 1B: Hard rebuild
149
+ * Append text to operations box
150
+ */
151
+ appendOps(text) {
152
+ if (!this.operationsBox) {
153
+ return;
154
+ }
155
+ const currentContent = this.operationsBox.content || '';
156
+ const lines = currentContent.split('\n').filter((l) => l.trim());
157
+ lines.push(text);
158
+ // Keep last 20 lines
159
+ const keepLines = lines.slice(-20);
160
+ this.operationsBox.setContent(keepLines.join('\n'));
161
+ this.kernel.getScreen()?.render();
162
+ }
163
+ /**
164
+ * Handle resize - MK2 Hotfix: Preserve input focus
64
165
  */
65
166
  async handleResize(cols, rows) {
66
167
  // Hard rebuild - destroy all, recompute, re-render
168
+ // Command box will be recreated and focused
67
169
  this.render();
68
170
  }
69
171
  /**
@@ -82,6 +184,18 @@ export class MK2App {
82
184
  }
83
185
  this.debugOverlay = null;
84
186
  }
187
+ // Destroy command box
188
+ if (this.commandBox) {
189
+ try {
190
+ if (typeof this.commandBox.destroy === 'function') {
191
+ this.commandBox.destroy();
192
+ }
193
+ }
194
+ catch {
195
+ // Ignore
196
+ }
197
+ this.commandBox = null;
198
+ }
85
199
  // Destroy all boxes
86
200
  this.boxes.forEach((box) => {
87
201
  try {
@@ -94,6 +208,7 @@ export class MK2App {
94
208
  }
95
209
  });
96
210
  this.boxes = [];
211
+ this.operationsBox = null;
97
212
  // Also clear screen children (safety)
98
213
  const screen = this.kernel.getScreen();
99
214
  if (screen) {
@@ -112,25 +227,38 @@ export class MK2App {
112
227
  }
113
228
  /**
114
229
  * Create error box for terminal too small
230
+ * Shows required minimum and detected size, keeps app running
115
231
  */
116
- createErrorBox(screen, message, safeW, safeH) {
117
- const blessed = require('neo-blessed');
118
- const errorW = Math.min(60, safeW - 4);
119
- const errorH = 5;
120
- const errorX = Math.floor((safeW - errorW) / 2);
121
- const errorY = Math.floor((safeH - errorH) / 2);
232
+ createErrorBox(screen, message, cols, rows, safeW, safeH) {
233
+ // Extract minimum requirements from error message if possible
234
+ const minMatch = message.match(/minimum (\d+)x(\d+)/);
235
+ const minCols = minMatch ? parseInt(minMatch[1], 10) : 80;
236
+ const minRows = minMatch ? parseInt(minMatch[2], 10) : 25;
237
+ const errorW = Math.min(70, Math.max(50, cols - 10));
238
+ const errorH = 8;
239
+ const errorX = Math.max(0, Math.floor((cols - errorW) / 2));
240
+ const errorY = Math.max(0, Math.floor((rows - errorH) / 2));
241
+ const content = [
242
+ ' TERMINAL TOO SMALL ',
243
+ '',
244
+ `Detected: ${cols} x ${rows}`,
245
+ `Required: ${minCols} x ${minRows}`,
246
+ '',
247
+ 'Resize terminal to continue',
248
+ 'App will auto-reload on resize',
249
+ ].join('\n');
122
250
  return blessed.box({
123
251
  parent: screen,
124
252
  top: errorY,
125
253
  left: errorX,
126
254
  width: errorW,
127
255
  height: errorH,
128
- content: message,
256
+ content,
129
257
  border: { type: 'line' },
130
258
  tags: false,
131
259
  style: {
132
- fg: 'red',
133
- border: { fg: 'red' },
260
+ fg: 'yellow',
261
+ border: { fg: 'yellow' },
134
262
  },
135
263
  });
136
264
  }