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.
- package/mk3-tui/src/ui/boot.rs +42 -25
- package/mk3-tui/src/ui/layout.rs +1 -1
- package/package.json +1 -1
package/mk3-tui/src/ui/boot.rs
CHANGED
|
@@ -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
|
-
|
|
11
|
-
const
|
|
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(
|
|
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
|
-
|
|
35
|
-
let
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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:
|
|
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::
|
|
54
|
-
|
|
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:
|
|
77
|
+
x: logs_x,
|
|
65
78
|
y: current_y,
|
|
66
|
-
width:
|
|
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::
|
|
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:
|
|
106
|
+
x: progress_x,
|
|
90
107
|
y: current_y,
|
|
91
|
-
width:
|
|
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
|
|
138
|
+
x: area.x,
|
|
122
139
|
y: current_y,
|
|
123
|
-
width:
|
|
140
|
+
width: area.width,
|
|
124
141
|
height: footer_height,
|
|
125
142
|
};
|
|
126
143
|
|
package/mk3-tui/src/ui/layout.rs
CHANGED
|
@@ -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.
|
|
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.
|
|
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",
|