4runr-os 2.3.5 → 2.3.7

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.
@@ -2,13 +2,17 @@ use crate::app::AppState;
2
2
  use ratatui::prelude::*;
3
3
  use ratatui::widgets::{Block, Borders, Gauge, Paragraph};
4
4
 
5
- // Color constants matching the TUI palette
5
+ // Color constants matching the TUI palette (exact match from layout.rs)
6
6
  const BRAND_PURPLE: Color = Color::Rgb(138, 43, 226);
7
+ #[allow(dead_code)]
8
+ const BRAND_VIOLET: Color = Color::Rgb(148, 103, 189);
7
9
  const CYBER_CYAN: Color = Color::Rgb(0, 255, 255);
8
10
  const NEON_GREEN: Color = Color::Rgb(57, 255, 20);
11
+ const TEXT_PRIMARY: Color = Color::Rgb(230, 230, 240);
9
12
  const TEXT_DIM: Color = Color::Rgb(100, 100, 120);
10
- const TEXT_PRIMARY: Color = Color::Rgb(220, 220, 240);
11
- const BG_DARK: Color = Color::Rgb(10, 10, 15);
13
+ #[allow(dead_code)]
14
+ const TEXT_MUTED: Color = Color::Rgb(60, 60, 80);
15
+ const BG_PANEL: Color = Color::Rgb(18, 18, 25);
12
16
 
13
17
  /// Exact logo from requirements (monospace, preserve spacing)
14
18
  const LOGO: &str = r#"██╗ ██╗██████╗ ██╗ ██╗███╗ ██╗██████╗ ██████╗ ███████╗
@@ -21,37 +25,42 @@ const LOGO: &str = r#"██╗ ██╗██████╗ ██╗ █
21
25
  pub fn render_boot(f: &mut Frame, area: Rect, state: &AppState) {
22
26
  // Clear background
23
27
  f.render_widget(
24
- Block::default().style(Style::default().bg(BG_DARK)),
28
+ Block::default().style(Style::default().bg(BG_PANEL)),
25
29
  area,
26
30
  );
27
31
 
28
32
  // Calculate layout: logo on top half, boot logs below, progress bar, footer
29
- let logo_height = 6; // Logo is 6 lines
30
- let boot_logs_height = state.boot_lines.len().min(10) as u16; // Max 10 lines visible
31
- let progress_height = 3;
32
- let footer_height = 1;
33
+ let logo_height: u16 = 6; // Logo is 6 lines
34
+ let boot_logs_height: u16 = state.boot_lines.len().min(10) as u16; // Max 10 lines visible
35
+ let progress_height: u16 = 3;
36
+ let footer_height: u16 = 1;
33
37
 
34
- let total_content_height = logo_height + 2 + boot_logs_height + 2 + progress_height + 2 + footer_height;
35
- let start_y = (area.height.saturating_sub(total_content_height)) / 2;
38
+ // Add extra top padding to move logo down from top edge
39
+ let top_padding: u16 = 3;
40
+ let total_content_height: u16 = logo_height + 2 + boot_logs_height + 2 + progress_height + 2 + footer_height;
41
+ let start_y: u16 = top_padding + (area.height.saturating_sub(total_content_height + top_padding)) / 2;
36
42
 
37
- // === LOGO (centered horizontally) ===
43
+ // === LOGO (centered horizontally and vertically) ===
38
44
  let logo_lines: Vec<&str> = LOGO.lines().collect();
39
- let logo_width = logo_lines.iter().map(|l| l.len()).max().unwrap_or(0) as u16;
40
- let logo_x = (area.width.saturating_sub(logo_width)) / 2;
45
+ let logo_width: u16 = logo_lines.iter().map(|l| l.len()).max().unwrap_or(0) as u16;
46
+ // Center horizontally: (area.width - logo_width) / 2
47
+ let logo_x: u16 = area.x + (area.width.saturating_sub(logo_width)) / 2;
41
48
 
42
49
  for (i, line) in logo_lines.iter().enumerate() {
43
- if start_y + i as u16 < area.height {
44
- let logo_rect = Rect {
50
+ let line_y = start_y + i as u16;
51
+ if line_y < area.height {
52
+ // Center each line within the available width
53
+ let line_rect = Rect {
45
54
  x: logo_x,
46
- y: start_y + i as u16,
55
+ y: line_y,
47
56
  width: logo_width.min(area.width.saturating_sub(logo_x)),
48
57
  height: 1,
49
58
  };
50
59
  f.render_widget(
51
60
  Paragraph::new(*line)
52
61
  .style(Style::default().fg(BRAND_PURPLE))
53
- .alignment(Alignment::Left),
54
- logo_rect,
62
+ .alignment(Alignment::Center), // Center alignment for perfect centering
63
+ line_rect,
55
64
  );
56
65
  }
57
66
  }
@@ -60,10 +69,14 @@ pub fn render_boot(f: &mut Frame, area: Rect, state: &AppState) {
60
69
 
61
70
  // === BOOT LOGS ===
62
71
  if !state.boot_lines.is_empty() && current_y < area.height {
72
+ // Center logs horizontally
73
+ let logs_width: u16 = (area.width * 60 / 100).min(area.width.saturating_sub(40)); // 60% width, safe margins
74
+ let logs_x: u16 = area.x + (area.width.saturating_sub(logs_width)) / 2;
75
+
63
76
  let logs_area = Rect {
64
- x: area.x + (area.width * 10 / 100), // 10% margin from left
77
+ x: logs_x,
65
78
  y: current_y,
66
- width: (area.width * 80 / 100).min(area.width.saturating_sub(20)), // 80% width, safe from right edge
79
+ width: logs_width,
67
80
  height: boot_logs_height,
68
81
  };
69
82
 
@@ -76,7 +89,7 @@ pub fn render_boot(f: &mut Frame, area: Rect, state: &AppState) {
76
89
  f.render_widget(
77
90
  Paragraph::new(log_text.trim())
78
91
  .style(Style::default().fg(TEXT_PRIMARY))
79
- .alignment(Alignment::Left),
92
+ .alignment(Alignment::Center), // Center logs too
80
93
  logs_area,
81
94
  );
82
95
  }
@@ -85,10 +98,14 @@ pub fn render_boot(f: &mut Frame, area: Rect, state: &AppState) {
85
98
 
86
99
  // === PROGRESS BAR ===
87
100
  if current_y < area.height {
101
+ // Center progress bar horizontally
102
+ let progress_width: u16 = (area.width * 60 / 100).min(area.width.saturating_sub(40));
103
+ let progress_x: u16 = area.x + (area.width.saturating_sub(progress_width)) / 2;
104
+
88
105
  let progress_area = Rect {
89
- x: area.x + (area.width * 10 / 100),
106
+ x: progress_x,
90
107
  y: current_y,
91
- width: (area.width * 80 / 100).min(area.width.saturating_sub(20)),
108
+ width: progress_width,
92
109
  height: 3,
93
110
  };
94
111
 
@@ -118,9 +135,9 @@ pub fn render_boot(f: &mut Frame, area: Rect, state: &AppState) {
118
135
  // === FOOTER: "Press any key to continue" (only when boot done) ===
119
136
  if state.boot_done && current_y < area.height {
120
137
  let footer_area = Rect {
121
- x: area.x + (area.width * 10 / 100),
138
+ x: area.x,
122
139
  y: current_y,
123
- width: (area.width * 80 / 100).min(area.width.saturating_sub(20)),
140
+ width: area.width,
124
141
  height: footer_height,
125
142
  };
126
143
 
@@ -120,7 +120,7 @@ fn render_header(f: &mut Frame, area: Rect, state: &AppState) {
120
120
 
121
121
  // Line 1: Brand + version + uptime - Bug 3 fix: Use "4Runr." with dot (matches brand logo)
122
122
  // Use npm package version (2.3.5) - matches package.json
123
- const PACKAGE_VERSION: &str = "2.3.5";
123
+ const PACKAGE_VERSION: &str = "2.3.7";
124
124
  let brand_line = Line::from(vec![
125
125
  Span::styled("4Runr.", Style::default().fg(BRAND_PURPLE).add_modifier(Modifier::BOLD)),
126
126
  Span::styled(" AI AGENT OS", Style::default().fg(BRAND_VIOLET)),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "4runr-os",
3
- "version": "2.3.5",
3
+ "version": "2.3.7",
4
4
  "type": "module",
5
5
  "description": "4Runr AI Agent OS - Secure terminal interface for AI agents. v2.3.5: Fixed boot screen logo rendering (restored original working version), fully functional Agent Builder with input handling and TUI styling. Built with Rust + Ratatui. ⚠️ Pre-MVP / Development Phase",
6
6
  "main": "dist/index.js",