4runr-os 1.4.2 → 2.0.2

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,124 @@
1
+ /**
2
+ * TUI Geometry - Single Source of Truth for Terminal Dimensions
3
+ *
4
+ * RULES (NEVER VIOLATE):
5
+ * 1. Always return integers
6
+ * 2. Clamp to minimums (prevents 0/undefined during resize)
7
+ * 3. Account for margins/borders
8
+ * 4. Never exceed these dimensions in any widget
9
+ */
10
+ // Absolute minimums (below this, TUI is unusable)
11
+ const MIN_COLS = 40;
12
+ const MIN_ROWS = 15;
13
+ // Margins (space reserved for borders/padding)
14
+ const HORIZONTAL_MARGIN = 0; // Blessed handles borders internally
15
+ const VERTICAL_MARGIN = 0; // Blessed handles borders internally
16
+ let lastGeometry = null;
17
+ /**
18
+ * Get current terminal geometry
19
+ *
20
+ * Priority:
21
+ * 1. Blessed screen object (most accurate)
22
+ * 2. process.stdout (fallback)
23
+ * 3. Clamped minimums (safety)
24
+ */
25
+ export function getTerminalGeometry(screen) {
26
+ let cols;
27
+ let rows;
28
+ let source;
29
+ // Try blessed screen first (most accurate)
30
+ if (screen && typeof screen.width === 'number' && typeof screen.height === 'number') {
31
+ cols = screen.width;
32
+ rows = screen.height;
33
+ source = 'screen';
34
+ }
35
+ // Fallback to stdout
36
+ else if (process.stdout.columns && process.stdout.rows) {
37
+ cols = process.stdout.columns;
38
+ rows = process.stdout.rows;
39
+ source = 'stdout';
40
+ }
41
+ // Safety fallback
42
+ else {
43
+ cols = MIN_COLS;
44
+ rows = MIN_ROWS;
45
+ source = 'clamped';
46
+ }
47
+ // Clamp to minimums (prevents transient 0/undefined during resize)
48
+ cols = Math.max(MIN_COLS, Math.floor(cols));
49
+ rows = Math.max(MIN_ROWS, Math.floor(rows));
50
+ // Calculate safe dimensions (accounting for margins)
51
+ const safeCols = Math.max(MIN_COLS, cols - HORIZONTAL_MARGIN);
52
+ const safeRows = Math.max(MIN_ROWS, rows - VERTICAL_MARGIN);
53
+ const geometry = {
54
+ cols,
55
+ rows,
56
+ safeCols,
57
+ safeRows,
58
+ source,
59
+ timestamp: Date.now(),
60
+ };
61
+ lastGeometry = geometry;
62
+ return geometry;
63
+ }
64
+ /**
65
+ * Get last known geometry (useful for comparisons)
66
+ */
67
+ export function getLastGeometry() {
68
+ return lastGeometry;
69
+ }
70
+ /**
71
+ * Check if geometry has changed significantly
72
+ */
73
+ export function hasGeometryChanged(screen) {
74
+ if (!lastGeometry)
75
+ return true;
76
+ const current = getTerminalGeometry(screen);
77
+ return (current.cols !== lastGeometry.cols ||
78
+ current.rows !== lastGeometry.rows);
79
+ }
80
+ /**
81
+ * Validate geometry is stable (not in resize storm)
82
+ */
83
+ export function isGeometryStable(screen) {
84
+ const geo = getTerminalGeometry(screen);
85
+ // Reject impossible sizes (transient during resize)
86
+ if (geo.cols < 20 || geo.rows < 10) {
87
+ return false;
88
+ }
89
+ return true;
90
+ }
91
+ /**
92
+ * Fit text to width (truncate with ellipsis, never exceed)
93
+ */
94
+ export function fitText(text, width) {
95
+ if (width <= 0)
96
+ return '';
97
+ if (text.length <= width)
98
+ return text;
99
+ // Reserve 3 chars for ellipsis
100
+ if (width <= 3)
101
+ return text.substring(0, width);
102
+ return text.substring(0, width - 3) + '...';
103
+ }
104
+ /**
105
+ * Clamp panel width to safe bounds
106
+ */
107
+ export function clampPanelWidth(width, minWidth = 10) {
108
+ const geo = lastGeometry || getTerminalGeometry();
109
+ return Math.max(minWidth, Math.min(width, geo.safeCols));
110
+ }
111
+ /**
112
+ * Clamp panel height to safe bounds
113
+ */
114
+ export function clampPanelHeight(height, minHeight = 3) {
115
+ const geo = lastGeometry || getTerminalGeometry();
116
+ return Math.max(minHeight, Math.min(height, geo.safeRows));
117
+ }
118
+ /**
119
+ * Format geometry for debug output
120
+ */
121
+ export function formatGeometry(geo) {
122
+ return `cols=${geo.cols} rows=${geo.rows} safeCols=${geo.safeCols} safeRows=${geo.safeRows} source=${geo.source}`;
123
+ }
124
+ //# sourceMappingURL=geometry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.js","sourceRoot":"","sources":["../../../../src/ui/v3/tui/geometry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Debug utilities for TUI lifecycle investigation
3
+ *
4
+ * Enable with TUI_DEBUG=1
5
+ * All debug output goes to Operations/eventBus, never stdout
6
+ */
7
+ import type { Widgets } from 'neo-blessed';
8
+ export declare const BOOT_ID: string;
9
+ export declare const isDebugMode: () => boolean;
10
+ /**
11
+ * Step 1A: Track widget creation
12
+ */
13
+ export declare function trackWidget(widget: any, type: string): void;
14
+ /**
15
+ * Step 1B: UI inventory dump
16
+ */
17
+ export declare function dumpUIInventory(screen: Widgets.Screen): void;
18
+ /**
19
+ * Step 2A: Track listener binding
20
+ */
21
+ export declare function trackListenerBinding(type: string): void;
22
+ /**
23
+ * Step 2B: Dump listener bindings
24
+ */
25
+ export declare function dumpListenerBindings(): void;
26
+ /**
27
+ * Step 3A: Track blocked stdout/stderr writes
28
+ */
29
+ export declare function trackBlockedWrite(stream: 'stdout' | 'stderr', content: string): void;
30
+ /**
31
+ * Step 3B: Dump blocked writes
32
+ */
33
+ export declare function dumpBlockedWrites(): void;
34
+ /**
35
+ * Monkeypatch stdout/stderr to catch writes
36
+ */
37
+ export declare function installStdoutMonkeypatch(): () => void;
38
+ export interface ResizeStats {
39
+ eventCount: number;
40
+ applyCount: number;
41
+ handlerBound: boolean;
42
+ }
43
+ /**
44
+ * Update resize stats (called from phase1RuntimeClean)
45
+ */
46
+ export declare function updateResizeStats(stats: Partial<ResizeStats>): void;
47
+ /**
48
+ * Get resize stats (exported for debug commands)
49
+ */
50
+ export declare function getResizeStats(): ResizeStats;
51
+ /**
52
+ * Get current statistics
53
+ */
54
+ export declare function getDebugStats(): {
55
+ bootId: string;
56
+ widgetCount: number;
57
+ listenerCount: number;
58
+ blockedWriteCount: number;
59
+ resizeStats: ResizeStats;
60
+ };
61
+ //# sourceMappingURL=debugUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugUtils.d.ts","sourceRoot":"","sources":["../../../../src/ui/v3/ui/debugUtils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG3C,eAAO,MAAM,OAAO,QAAgE,CAAC;AAkCrF,eAAO,MAAM,WAAW,QAAO,OAE9B,CAAC;AAUF;;GAEG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAsB3D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,GAAG,IAAI,CAqC5D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAqBvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CA2B3C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAsBpF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAcxC;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,IAAI,CAkCrD;AAGD,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;CACvB;AAQD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAEnE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,WAAW,CAAC;CAC1B,CAQA"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Debug utilities for TUI lifecycle investigation
3
+ *
4
+ * Enable with TUI_DEBUG=1
5
+ * All debug output goes to Operations/eventBus, never stdout
6
+ */
7
+ import { eventBus } from '../core/eventBus.js';
8
+ // Step 5: Single source of truth boot marker
9
+ export const BOOT_ID = `${Math.random().toString(36).substring(2, 8).toUpperCase()}`;
10
+ const widgetRegistry = new Map();
11
+ const listenerBindings = [];
12
+ let resizeHandlerCount = 0;
13
+ const blockedWrites = [];
14
+ const MAX_BLOCKED_WRITES = 50;
15
+ export const isDebugMode = () => {
16
+ return process.env.TUI_DEBUG === '1';
17
+ };
18
+ const log = (msg, level = 'INFO') => {
19
+ eventBus.emit({
20
+ tag: 'DBG',
21
+ msg: `[boot=${BOOT_ID}] ${msg}`,
22
+ level
23
+ });
24
+ };
25
+ /**
26
+ * Step 1A: Track widget creation
27
+ */
28
+ export function trackWidget(widget, type) {
29
+ if (!isDebugMode())
30
+ return;
31
+ const id = Math.random().toString(36).substring(2, 8);
32
+ const stack = new Error().stack || '';
33
+ const createdBy = stack.split('\n').slice(2, 5).join('\n ');
34
+ const meta = {
35
+ __id: id,
36
+ __createdAt: Date.now(),
37
+ __createdBy: createdBy,
38
+ __type: type
39
+ };
40
+ widget.__id = id;
41
+ widget.__createdAt = meta.__createdAt;
42
+ widget.__createdBy = meta.__createdBy;
43
+ widget.__type = type;
44
+ widgetRegistry.set(id, meta);
45
+ log(`created ${type} id=${id}`);
46
+ }
47
+ /**
48
+ * Step 1B: UI inventory dump
49
+ */
50
+ export function dumpUIInventory(screen) {
51
+ const children = screen.children || [];
52
+ const totalChildren = children.length;
53
+ log(`=== UI INVENTORY ===`);
54
+ log(`Total children: ${totalChildren}`);
55
+ // Count widgets by type
56
+ const typeCounts = new Map();
57
+ for (const child of children) {
58
+ const type = child.__type || 'unknown';
59
+ const id = child.__id || 'no-id';
60
+ const createdAt = child.__createdAt || 0;
61
+ const createdBy = child.__createdBy || 'unknown';
62
+ if (!typeCounts.has(type)) {
63
+ typeCounts.set(type, []);
64
+ }
65
+ typeCounts.get(type).push({ id, createdAt, createdBy });
66
+ }
67
+ // Report counts and duplicates
68
+ for (const [type, instances] of typeCounts.entries()) {
69
+ const count = instances.length;
70
+ log(`${type}: ${count} instance(s)`);
71
+ if (count > 1) {
72
+ log(` ⚠️ DUPLICATE DETECTED for ${type}:`, 'WARN');
73
+ for (const inst of instances) {
74
+ log(` - id=${inst.id} created at ${new Date(inst.createdAt).toISOString()}`);
75
+ log(` stack: ${inst.createdBy}`);
76
+ }
77
+ }
78
+ }
79
+ log(`=== END INVENTORY ===`);
80
+ }
81
+ /**
82
+ * Step 2A: Track listener binding
83
+ */
84
+ export function trackListenerBinding(type) {
85
+ if (!isDebugMode())
86
+ return;
87
+ if (type === 'resize') {
88
+ resizeHandlerCount++;
89
+ }
90
+ const stack = new Error().stack || '';
91
+ const boundBy = stack.split('\n').slice(2, 5).join('\n ');
92
+ const binding = {
93
+ type,
94
+ handlerNum: type === 'resize' ? resizeHandlerCount : listenerBindings.filter(b => b.type === type).length + 1,
95
+ boundAt: Date.now(),
96
+ stack: boundBy
97
+ };
98
+ listenerBindings.push(binding);
99
+ log(`bound ${type} handler#${binding.handlerNum} at ${new Date(binding.boundAt).toISOString()}`);
100
+ log(` stack: ${boundBy}`);
101
+ }
102
+ /**
103
+ * Step 2B: Dump listener bindings
104
+ */
105
+ export function dumpListenerBindings() {
106
+ log(`=== LISTENER BINDINGS ===`);
107
+ log(`Total bindings: ${listenerBindings.length}`);
108
+ // Group by type
109
+ const byType = new Map();
110
+ for (const binding of listenerBindings) {
111
+ if (!byType.has(binding.type)) {
112
+ byType.set(binding.type, []);
113
+ }
114
+ byType.get(binding.type).push(binding);
115
+ }
116
+ for (const [type, bindings] of byType.entries()) {
117
+ log(`${type}: ${bindings.length} binding(s)`);
118
+ if (bindings.length > 1) {
119
+ log(` ⚠️ MULTIPLE BINDINGS for ${type}:`, 'WARN');
120
+ }
121
+ for (const binding of bindings) {
122
+ log(` - handler#${binding.handlerNum} at ${new Date(binding.boundAt).toISOString()}`);
123
+ log(` stack: ${binding.stack}`);
124
+ }
125
+ }
126
+ log(`=== END LISTENER BINDINGS ===`);
127
+ }
128
+ /**
129
+ * Step 3A: Track blocked stdout/stderr writes
130
+ */
131
+ export function trackBlockedWrite(stream, content) {
132
+ const stack = new Error().stack || '';
133
+ const caller = stack.split('\n').slice(2, 5).join('\n ');
134
+ const blocked = {
135
+ ts: Date.now(),
136
+ content: content.substring(0, 120),
137
+ stack: caller,
138
+ stream
139
+ };
140
+ blockedWrites.push(blocked);
141
+ // Keep only last MAX_BLOCKED_WRITES
142
+ if (blockedWrites.length > MAX_BLOCKED_WRITES) {
143
+ blockedWrites.shift();
144
+ }
145
+ // Emit to operations (rate limited to prevent spam)
146
+ if (isDebugMode()) {
147
+ log(`[${stream.toUpperCase()} BLOCKED] "${blocked.content}" from: ${caller}`, 'WARN');
148
+ }
149
+ }
150
+ /**
151
+ * Step 3B: Dump blocked writes
152
+ */
153
+ export function dumpBlockedWrites() {
154
+ log(`=== BLOCKED STDOUT/STDERR WRITES ===`);
155
+ log(`Total tracked: ${blockedWrites.length} (showing last 10)`);
156
+ const recent = blockedWrites.slice(-10);
157
+ for (let i = 0; i < recent.length; i++) {
158
+ const write = recent[i];
159
+ log(`${i + 1}. [${write.stream}] at ${new Date(write.ts).toISOString()}`);
160
+ log(` content: "${write.content}"`);
161
+ log(` stack: ${write.stack}`);
162
+ }
163
+ log(`=== END BLOCKED WRITES ===`);
164
+ }
165
+ /**
166
+ * Monkeypatch stdout/stderr to catch writes
167
+ */
168
+ export function installStdoutMonkeypatch() {
169
+ const originalStdoutWrite = process.stdout.write.bind(process.stdout);
170
+ const originalStderrWrite = process.stderr.write.bind(process.stderr);
171
+ // Patch stdout
172
+ process.stdout.write = function (chunk, ...args) {
173
+ const content = String(chunk);
174
+ // Allow ANSI escape codes (cursor control) and blessed writes
175
+ const stack = new Error().stack || '';
176
+ const isBlessed = stack.includes('neo-blessed') || stack.includes('Program.prototype');
177
+ const isAnsiEscape = /^\x1b\[[\d;]*[A-Za-z]/.test(content);
178
+ if (isBlessed || isAnsiEscape) {
179
+ return originalStdoutWrite(chunk, ...args);
180
+ }
181
+ // Block and track
182
+ trackBlockedWrite('stdout', content);
183
+ return true; // Pretend success
184
+ };
185
+ // Patch stderr (less strict - allow it but track)
186
+ process.stderr.write = function (chunk, ...args) {
187
+ const content = String(chunk);
188
+ trackBlockedWrite('stderr', content);
189
+ return originalStderrWrite(chunk, ...args);
190
+ };
191
+ // Return cleanup function
192
+ return () => {
193
+ process.stdout.write = originalStdoutWrite;
194
+ process.stderr.write = originalStderrWrite;
195
+ };
196
+ }
197
+ let resizeStats = {
198
+ eventCount: 0,
199
+ applyCount: 0,
200
+ handlerBound: false
201
+ };
202
+ /**
203
+ * Update resize stats (called from phase1RuntimeClean)
204
+ */
205
+ export function updateResizeStats(stats) {
206
+ resizeStats = { ...resizeStats, ...stats };
207
+ }
208
+ /**
209
+ * Get resize stats (exported for debug commands)
210
+ */
211
+ export function getResizeStats() {
212
+ return { ...resizeStats };
213
+ }
214
+ /**
215
+ * Get current statistics
216
+ */
217
+ export function getDebugStats() {
218
+ return {
219
+ bootId: BOOT_ID,
220
+ widgetCount: widgetRegistry.size,
221
+ listenerCount: listenerBindings.length,
222
+ blockedWriteCount: blockedWrites.length,
223
+ resizeStats: getResizeStats()
224
+ };
225
+ }
226
+ //# sourceMappingURL=debugUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debugUtils.js","sourceRoot":"","sources":["../../../../src/ui/v3/ui/debugUtils.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,22 @@
1
1
  /**
2
- * Phase 1 Layout Calculator
2
+ * Phase 1 Layout Calculator - FINAL BULLETPROOF EDITION
3
3
  *
4
4
  * Fixed hub layout with 7 boxes:
5
5
  * - Left column (3 stacked): POSTURE, RESOURCES, ASSETS
6
6
  * - Center (1): OPERATIONS
7
7
  * - Right column (2 stacked): NETWORK, CAPABILITIES
8
8
  * - Bottom bar (1): COMMAND LINE
9
+ *
10
+ * CRITICAL RULES (NEVER VIOLATE):
11
+ * 1. Use geometry.ts for all dimension queries
12
+ * 2. Total width MUST NOT exceed safeCols
13
+ * 3. Total height MUST NOT exceed safeRows
14
+ * 4. No floating point math - only integers
15
+ * 5. Right column width calculated as REMAINDER (prevents rounding errors)
16
+ * 6. All positions validated before return
17
+ * 7. All text must use fitText() to prevent overflow
9
18
  */
19
+ import type { Widgets } from 'neo-blessed';
10
20
  export interface BoxRect {
11
21
  top: number;
12
22
  left: number;
@@ -27,10 +37,16 @@ export interface LayoutResult {
27
37
  errorMessage?: string;
28
38
  layout?: Phase1Layout;
29
39
  }
30
- export declare const MIN_WIDTH = 100;
31
- export declare const MIN_HEIGHT = 25;
40
+ export declare const MIN_WIDTH = 80;
41
+ export declare const MIN_HEIGHT = 24;
32
42
  /**
33
- * Compute Phase 1 layout
43
+ * Compute Phase 1 layout - FINAL BULLETPROOF IMPLEMENTATION
44
+ *
45
+ * This function GUARANTEES:
46
+ * - Never exceeds terminal dimensions
47
+ * - Works on ANY terminal size >= MIN_WIDTH x MIN_HEIGHT
48
+ * - Integer math only (no rounding errors)
49
+ * - Uses geometry.ts as single source of truth
34
50
  */
35
- export declare function computePhase1Layout(width: number, height: number): LayoutResult;
51
+ export declare function computePhase1Layout(width: number, height: number, screen?: Widgets.Screen): LayoutResult;
36
52
  //# sourceMappingURL=phase1Layout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"phase1Layout.d.ts","sourceRoot":"","sources":["../../../../../src/ui/v3/ui/layout/phase1Layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAID,eAAO,MAAM,SAAS,MAAM,CAAC;AAC7B,eAAO,MAAM,UAAU,KAAK,CAAC;AAQ7B;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAiG/E"}
1
+ {"version":3,"file":"phase1Layout.d.ts","sourceRoot":"","sources":["../../../../../src/ui/v3/ui/layout/phase1Layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,WAAW,OAAO;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAGD,eAAO,MAAM,SAAS,KAAK,CAAC;AAC5B,eAAO,MAAM,UAAU,KAAK,CAAC;AAM7B;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,GAAG,YAAY,CAwJxG"}