4runr-os 2.9.57 → 2.9.59
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.
|
Binary file
|
package/mk3-tui/src/main.rs
CHANGED
|
@@ -7,6 +7,7 @@ use ratatui::prelude::*;
|
|
|
7
7
|
use std::time::{Duration, Instant};
|
|
8
8
|
|
|
9
9
|
mod app;
|
|
10
|
+
mod debug_log;
|
|
10
11
|
mod io;
|
|
11
12
|
mod screens;
|
|
12
13
|
mod storage;
|
|
@@ -600,9 +601,18 @@ fn main() -> Result<()> {
|
|
|
600
601
|
if is_switching {
|
|
601
602
|
#[cfg(debug_assertions)]
|
|
602
603
|
eprintln!("[MAIN] SCREEN SWITCH: {:?} -> {:?} (clearing)", previous_screen, current_screen);
|
|
604
|
+
debug_log::log_screen(
|
|
605
|
+
&format!("{:?}", previous_screen.as_ref().unwrap_or(¤t_screen)),
|
|
606
|
+
&format!("{:?}", current_screen),
|
|
607
|
+
);
|
|
603
608
|
terminal.clear()?;
|
|
604
609
|
}
|
|
605
610
|
|
|
611
|
+
// When on Setup Portal, sync terminal buffer to real console size (fixes windowed-mode corruption)
|
|
612
|
+
if matches!(current_screen, crate::screens::Screen::SetupPortal) {
|
|
613
|
+
let _ = terminal.autoresize();
|
|
614
|
+
}
|
|
615
|
+
|
|
606
616
|
let render_start = Instant::now();
|
|
607
617
|
terminal.draw(|f| app.render(f))?;
|
|
608
618
|
let render_duration = render_start.elapsed().as_millis() as u64;
|
|
@@ -618,8 +628,12 @@ fn main() -> Result<()> {
|
|
|
618
628
|
// OPTIMIZATION: Reduced poll timeout to 1ms for faster input detection
|
|
619
629
|
// This allows loop to run ~1000 times/second when idle, but input is detected immediately
|
|
620
630
|
if crossterm::event::poll(Duration::from_millis(1))? {
|
|
631
|
+
let on_setup = app.state.navigation.current_screen() == &screens::Screen::SetupPortal;
|
|
621
632
|
match event::read()? {
|
|
622
633
|
Event::Key(key) => {
|
|
634
|
+
if on_setup {
|
|
635
|
+
debug_log::log_input("Key", &format!("{:?}", key));
|
|
636
|
+
}
|
|
623
637
|
if key.kind == KeyEventKind::Press {
|
|
624
638
|
if app.handle_input(key, &mut io_handler, ws_client.as_ref())? {
|
|
625
639
|
break; // Exit requested
|
|
@@ -627,8 +641,11 @@ fn main() -> Result<()> {
|
|
|
627
641
|
}
|
|
628
642
|
}
|
|
629
643
|
Event::Mouse(mouse) => {
|
|
644
|
+
if on_setup {
|
|
645
|
+
debug_log::log_input("Mouse", &format!("{:?}", mouse));
|
|
646
|
+
}
|
|
630
647
|
// Handle mouse scroll events for Setup Portal
|
|
631
|
-
if
|
|
648
|
+
if on_setup {
|
|
632
649
|
if !app.state.setup_portal.detecting {
|
|
633
650
|
match mouse.kind {
|
|
634
651
|
MouseEventKind::ScrollUp => {
|
|
@@ -644,9 +661,11 @@ fn main() -> Result<()> {
|
|
|
644
661
|
}
|
|
645
662
|
}
|
|
646
663
|
}
|
|
647
|
-
Event::Resize(
|
|
664
|
+
Event::Resize(w, h) => {
|
|
665
|
+
if on_setup {
|
|
666
|
+
debug_log::log_input("Resize", &format!("{}x{}", w, h));
|
|
667
|
+
}
|
|
648
668
|
// Terminal was resized - force immediate re-render with correct dimensions
|
|
649
|
-
// This fixes the initial render issue where portal dimensions might be wrong
|
|
650
669
|
terminal.clear()?;
|
|
651
670
|
app.request_immediate_render("terminal_resize");
|
|
652
671
|
}
|
package/mk3-tui/src/ui/layout.rs
CHANGED
|
@@ -144,7 +144,7 @@ fn render_header(f: &mut Frame, area: Rect, state: &AppState) {
|
|
|
144
144
|
|
|
145
145
|
// Line 1: Brand + version + mode + uptime - Bug 3 fix: Use "4Runr." with dot (matches brand logo)
|
|
146
146
|
// Use npm package version (2.9.24) - matches package.json
|
|
147
|
-
const PACKAGE_VERSION: &str = "2.9.
|
|
147
|
+
const PACKAGE_VERSION: &str = "2.9.59";
|
|
148
148
|
let brand_line = Line::from(vec![
|
|
149
149
|
Span::styled("4Runr.", Style::default().fg(BRAND_PURPLE).add_modifier(Modifier::BOLD)),
|
|
150
150
|
Span::styled(" AI AGENT OS", Style::default().fg(BRAND_VIOLET)),
|
|
@@ -5,6 +5,20 @@ use ratatui::prelude::*;
|
|
|
5
5
|
use ratatui::widgets::{Block, Borders, Paragraph, Wrap, Clear, List, ListItem};
|
|
6
6
|
use crate::app::{AppState, GatewayOption};
|
|
7
7
|
|
|
8
|
+
/// When SETUP_PORTAL_DEBUG=1 or SETUP_PORTAL_DEBUG_FILE is set, log to file (and optionally stderr).
|
|
9
|
+
fn setup_debug_enabled() -> bool {
|
|
10
|
+
std::env::var("SETUP_PORTAL_DEBUG").as_deref() == Ok("1")
|
|
11
|
+
|| std::env::var("SETUP_PORTAL_DEBUG_FILE").is_ok()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
fn dbg_log(msg: &str) {
|
|
15
|
+
if setup_debug_enabled() {
|
|
16
|
+
crate::debug_log::log(msg);
|
|
17
|
+
#[cfg(debug_assertions)]
|
|
18
|
+
eprintln!("{}", msg);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
8
22
|
// === 4RUNR BRAND COLORS (matching layout.rs) ===
|
|
9
23
|
const BRAND_PURPLE: Color = Color::Rgb(138, 43, 226);
|
|
10
24
|
const CYBER_CYAN: Color = Color::Rgb(0, 255, 255);
|
|
@@ -27,14 +41,22 @@ pub fn render(f: &mut Frame, state: &mut AppState) {
|
|
|
27
41
|
|
|
28
42
|
let area = f.size();
|
|
29
43
|
|
|
30
|
-
// Debug: log dimensions when
|
|
31
|
-
|
|
32
|
-
{
|
|
44
|
+
// Debug: log dimensions when SETUP_PORTAL_DEBUG=1 (release) or in debug build
|
|
45
|
+
let do_dbg = setup_debug_enabled() || cfg!(debug_assertions);
|
|
46
|
+
if do_dbg {
|
|
33
47
|
static mut LAST_DIMS: Option<(u16, u16)> = None;
|
|
48
|
+
static mut FRAME_COUNT: u64 = 0;
|
|
49
|
+
static mut BANNER_SHOWN: bool = false;
|
|
34
50
|
unsafe {
|
|
51
|
+
if !BANNER_SHOWN {
|
|
52
|
+
eprintln!("[SETUP_PORTAL] Debug logging active (SETUP_PORTAL_DEBUG=1 or debug build). Redirect stderr to capture, e.g. 4r 2> setup-debug.log");
|
|
53
|
+
BANNER_SHOWN = true;
|
|
54
|
+
}
|
|
55
|
+
FRAME_COUNT += 1;
|
|
35
56
|
let changed = LAST_DIMS.map_or(true, |(w, h)| w != area.width || h != area.height);
|
|
36
|
-
if changed {
|
|
37
|
-
eprintln!("[SETUP_PORTAL] R#{} DIMS: {}x{} (
|
|
57
|
+
if changed || FRAME_COUNT <= 15 || FRAME_COUNT % 60 == 0 {
|
|
58
|
+
eprintln!("[SETUP_PORTAL] R#{} frame={} DIMS: {}x{} (changed={})",
|
|
59
|
+
render_id, FRAME_COUNT, area.width, area.height, changed);
|
|
38
60
|
LAST_DIMS = Some((area.width, area.height));
|
|
39
61
|
}
|
|
40
62
|
}
|
|
@@ -72,6 +94,28 @@ pub fn render(f: &mut Frame, state: &mut AppState) {
|
|
|
72
94
|
width: portal_width,
|
|
73
95
|
height: portal_height,
|
|
74
96
|
};
|
|
97
|
+
if do_dbg {
|
|
98
|
+
dbg_log(&format!("[SETUP_PORTAL] portal_area: x={} y={} w={} h={}",
|
|
99
|
+
portal_area.x, portal_area.y, portal_area.width, portal_area.height));
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// File strategy: one composite RENDER line per frame (throttled) so file has full trace
|
|
103
|
+
if setup_debug_enabled() {
|
|
104
|
+
static mut RENDER_LOG_COUNT: u64 = 0;
|
|
105
|
+
unsafe {
|
|
106
|
+
RENDER_LOG_COUNT += 1;
|
|
107
|
+
let throttle = RENDER_LOG_COUNT <= 25 || RENDER_LOG_COUNT % 30 == 0;
|
|
108
|
+
if throttle {
|
|
109
|
+
let sel = format!("{:?}", state.setup_portal.selected_option);
|
|
110
|
+
crate::debug_log::log_render(&format!(
|
|
111
|
+
"frame={} dims={}x{} portal=({},{},{},{}) selected={}",
|
|
112
|
+
RENDER_LOG_COUNT, area.width, area.height,
|
|
113
|
+
portal_area.x, portal_area.y, portal_area.width, portal_area.height,
|
|
114
|
+
sel
|
|
115
|
+
));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
75
119
|
|
|
76
120
|
// Split portal into sections
|
|
77
121
|
use ratatui::layout::{Constraint, Direction, Layout};
|
|
@@ -99,6 +143,23 @@ pub fn render(f: &mut Frame, state: &mut AppState) {
|
|
|
99
143
|
.direction(Direction::Vertical)
|
|
100
144
|
.constraints(constraints)
|
|
101
145
|
.split(portal_area);
|
|
146
|
+
if do_dbg {
|
|
147
|
+
let c = &chunks[2];
|
|
148
|
+
dbg_log(&format!("[SETUP_PORTAL] content chunk: x={} y={} w={} h={}", c.x, c.y, c.width, c.height));
|
|
149
|
+
}
|
|
150
|
+
if setup_debug_enabled() {
|
|
151
|
+
static mut N: u64 = 0;
|
|
152
|
+
unsafe {
|
|
153
|
+
N += 1;
|
|
154
|
+
if N <= 25 || N % 30 == 0 {
|
|
155
|
+
let c = &chunks[2];
|
|
156
|
+
crate::debug_log::log_render(&format!(
|
|
157
|
+
"content_chunk=({},{},{},{})",
|
|
158
|
+
c.x, c.y, c.width, c.height
|
|
159
|
+
));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
102
163
|
|
|
103
164
|
render_header(f, chunks[0], state);
|
|
104
165
|
render_description(f, chunks[1]);
|
|
@@ -165,6 +226,18 @@ fn render_content(f: &mut Frame, area: Rect, state: &mut AppState, render_id: u6
|
|
|
165
226
|
}
|
|
166
227
|
|
|
167
228
|
fn render_options_list(f: &mut Frame, area: Rect, state: &mut AppState, _render_id: u64) {
|
|
229
|
+
if setup_debug_enabled() {
|
|
230
|
+
static mut N: u64 = 0;
|
|
231
|
+
unsafe {
|
|
232
|
+
N += 1;
|
|
233
|
+
if N <= 10 || N % 30 == 0 {
|
|
234
|
+
crate::debug_log::log_render(&format!(
|
|
235
|
+
"list area=({},{},{},{})",
|
|
236
|
+
area.x, area.y, area.width, area.height
|
|
237
|
+
));
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
168
241
|
// Clear this rect first so no duplicate rows from previous frame
|
|
169
242
|
f.render_widget(Clear, area);
|
|
170
243
|
|
|
@@ -207,6 +280,18 @@ fn render_options_list(f: &mut Frame, area: Rect, state: &mut AppState, _render_
|
|
|
207
280
|
.style(Style::default().bg(BG_PANEL));
|
|
208
281
|
|
|
209
282
|
let inner = block.inner(area);
|
|
283
|
+
if setup_debug_enabled() {
|
|
284
|
+
static mut N: u64 = 0;
|
|
285
|
+
unsafe {
|
|
286
|
+
N += 1;
|
|
287
|
+
if N <= 10 || N % 30 == 0 {
|
|
288
|
+
crate::debug_log::log_render(&format!(
|
|
289
|
+
"list inner=({},{},{},{})",
|
|
290
|
+
inner.x, inner.y, inner.width, inner.height
|
|
291
|
+
));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
210
295
|
f.render_widget(block, area);
|
|
211
296
|
|
|
212
297
|
// Fill inner area
|
|
@@ -219,6 +304,18 @@ fn render_options_list(f: &mut Frame, area: Rect, state: &mut AppState, _render_
|
|
|
219
304
|
}
|
|
220
305
|
|
|
221
306
|
fn render_option_details(f: &mut Frame, area: Rect, state: &AppState, _render_id: u64) {
|
|
307
|
+
if setup_debug_enabled() {
|
|
308
|
+
static mut N: u64 = 0;
|
|
309
|
+
unsafe {
|
|
310
|
+
N += 1;
|
|
311
|
+
if N <= 10 || N % 30 == 0 {
|
|
312
|
+
crate::debug_log::log_render(&format!(
|
|
313
|
+
"details area=({},{},{},{})",
|
|
314
|
+
area.x, area.y, area.width, area.height
|
|
315
|
+
));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
222
319
|
// Clear this rect first so no leftover from previous option
|
|
223
320
|
f.render_widget(Clear, area);
|
|
224
321
|
|
|
@@ -315,12 +412,27 @@ fn render_option_details(f: &mut Frame, area: Rect, state: &AppState, _render_id
|
|
|
315
412
|
.style(Style::default().bg(BG_PANEL));
|
|
316
413
|
|
|
317
414
|
let inner = block.inner(area);
|
|
415
|
+
if setup_debug_enabled() {
|
|
416
|
+
static mut N: u64 = 0;
|
|
417
|
+
unsafe {
|
|
418
|
+
N += 1;
|
|
419
|
+
if N <= 10 || N % 30 == 0 {
|
|
420
|
+
crate::debug_log::log_render(&format!(
|
|
421
|
+
"details inner=({},{},{},{})",
|
|
422
|
+
inner.x, inner.y, inner.width, inner.height
|
|
423
|
+
));
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
318
427
|
f.render_widget(block, area);
|
|
319
428
|
|
|
320
429
|
// Validate area before rendering
|
|
321
430
|
let terminal_size = f.size();
|
|
322
431
|
if inner.width == 0 || inner.height == 0 ||
|
|
323
432
|
inner.x >= terminal_size.width || inner.y >= terminal_size.height {
|
|
433
|
+
if setup_debug_enabled() {
|
|
434
|
+
dbg_log("[DETAILS] SKIP render: inner or terminal invalid");
|
|
435
|
+
}
|
|
324
436
|
return;
|
|
325
437
|
}
|
|
326
438
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "4runr-os",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.59",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.
|
|
5
|
+
"description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.59: Setup Portal file debug (SETUP_PORTAL_DEBUG_FILE). v2.9.58: Autoresize + stderr debug. ⚠️ Pre-MVP / Development Phase",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"4runr": "dist/index.js",
|