4runr-os 2.9.38 → 2.9.39

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.
@@ -646,6 +646,12 @@ fn main() -> Result<()> {
646
646
  }
647
647
  }
648
648
  }
649
+ Event::Resize(_width, _height) => {
650
+ // Terminal was resized - force immediate re-render with correct dimensions
651
+ // This fixes the initial render issue where portal dimensions might be wrong
652
+ terminal.clear()?;
653
+ app.request_immediate_render("terminal_resize");
654
+ }
649
655
  _ => {}
650
656
  }
651
657
  }
@@ -33,6 +33,20 @@ pub fn render(f: &mut Frame, state: &AppState) {
33
33
 
34
34
  let area = f.size();
35
35
 
36
+ // CRITICAL: Validate terminal size before rendering
37
+ // This prevents character corruption when terminal size is wrong on initial render
38
+ if area.width == 0 || area.height == 0 {
39
+ // Terminal not ready - skip render
40
+ return;
41
+ }
42
+
43
+ // Ensure minimum size for portal (60x22)
44
+ if area.width < 60 || area.height < 22 {
45
+ // Render "too small" message
46
+ render_too_small_connection(f, area);
47
+ return;
48
+ }
49
+
36
50
  // CRITICAL: Clear the ENTIRE screen first - this is a standalone screen, not an overlay
37
51
  f.render_widget(Clear, area);
38
52
 
@@ -481,3 +495,40 @@ fn render_actions(f: &mut Frame, area: Rect, state: &AppState) {
481
495
 
482
496
  f.render_widget(paragraph, area);
483
497
  }
498
+
499
+ fn render_too_small_connection(f: &mut Frame, area: Rect) {
500
+ // Clear screen
501
+ f.render_widget(Clear, area);
502
+
503
+ // Render background
504
+ let bg = Block::default()
505
+ .style(Style::default().bg(BG_PANEL));
506
+ f.render_widget(bg, area);
507
+
508
+ // Center the message
509
+ let msg = vec![
510
+ Line::from(""),
511
+ Line::from(Span::styled("Connection Portal", Style::default().fg(BRAND_PURPLE).bold())),
512
+ Line::from(""),
513
+ Line::from(Span::styled("Terminal too small", Style::default().fg(ERROR_RED))),
514
+ Line::from(""),
515
+ Line::from(Span::styled(
516
+ format!("Current: {}x{}", area.width, area.height),
517
+ Style::default().fg(TEXT_DIM)
518
+ )),
519
+ Line::from(Span::styled(
520
+ "Required: 60x22",
521
+ Style::default().fg(TEXT_PRIMARY)
522
+ )),
523
+ ];
524
+
525
+ let paragraph = Paragraph::new(msg)
526
+ .alignment(Alignment::Center);
527
+
528
+ f.render_widget(paragraph, Rect {
529
+ x: area.x,
530
+ y: area.y + (area.height / 3),
531
+ width: area.width,
532
+ height: area.height / 3,
533
+ });
534
+ }
@@ -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.38";
147
+ const PACKAGE_VERSION: &str = "2.9.39";
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)),
@@ -20,6 +20,20 @@ const ERROR_RED: Color = Color::Rgb(255, 69, 69);
20
20
  pub fn render(f: &mut Frame, state: &AppState) {
21
21
  let area = f.size();
22
22
 
23
+ // CRITICAL: Validate terminal size before rendering
24
+ // This prevents character corruption when terminal size is wrong on initial render
25
+ if area.width == 0 || area.height == 0 {
26
+ // Terminal not ready - skip render
27
+ return;
28
+ }
29
+
30
+ // Ensure minimum size for portal (85x25)
31
+ if area.width < 85 || area.height < 25 {
32
+ // Render "too small" message
33
+ render_too_small(f, area);
34
+ return;
35
+ }
36
+
23
37
  // CRITICAL: Clear the ENTIRE screen first - this is a standalone screen, not an overlay
24
38
  f.render_widget(Clear, area);
25
39
 
@@ -345,3 +359,40 @@ fn render_actions(f: &mut Frame, area: Rect, state: &AppState) {
345
359
 
346
360
  f.render_widget(paragraph, inner);
347
361
  }
362
+
363
+ fn render_too_small(f: &mut Frame, area: Rect) {
364
+ // Clear screen
365
+ f.render_widget(Clear, area);
366
+
367
+ // Render background
368
+ let bg = Block::default()
369
+ .style(Style::default().bg(BG_PANEL));
370
+ f.render_widget(bg, area);
371
+
372
+ // Center the message
373
+ let msg = vec![
374
+ Line::from(""),
375
+ Line::from(Span::styled("Setup Portal", Style::default().fg(BRAND_PURPLE).bold())),
376
+ Line::from(""),
377
+ Line::from(Span::styled("Terminal too small", Style::default().fg(ERROR_RED))),
378
+ Line::from(""),
379
+ Line::from(Span::styled(
380
+ format!("Current: {}x{}", area.width, area.height),
381
+ Style::default().fg(TEXT_DIM)
382
+ )),
383
+ Line::from(Span::styled(
384
+ "Required: 85x25",
385
+ Style::default().fg(TEXT_PRIMARY)
386
+ )),
387
+ ];
388
+
389
+ let paragraph = Paragraph::new(msg)
390
+ .alignment(ratatui::layout::Alignment::Center);
391
+
392
+ f.render_widget(paragraph, Rect {
393
+ x: area.x,
394
+ y: area.y + (area.height / 3),
395
+ width: area.width,
396
+ height: area.height / 3,
397
+ });
398
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "4runr-os",
3
- "version": "2.9.38",
3
+ "version": "2.9.39",
4
4
  "type": "module",
5
- "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.38: Fixed Setup Portal character corruption - removed redundant Clear widget causing buffer corruption during navigation. ⚠️ Pre-MVP / Development Phase",
5
+ "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.9.39: Fixed Setup Portal initial render bug - added Event::Resize handler and terminal size validation to prevent character corruption on first open. v2.9.38: Fixed Setup Portal character corruption. ⚠️ Pre-MVP / Development Phase",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "4runr": "dist/index.js",