use ratatui::style::{Color, Modifier, Style};
use ratatui::text::{Line, Span};
use super::theme;
pub const CHEVRON_ROWS: [&str; 3] = ["▀█▄ ", " ██", "▄█▀ "];
fn dimmed(c: theme::C) -> Color {
let s = |v: u8| ((v as f64) * 0.45) as u8;
match c.color() {
Color::Rgb(r, g, b) => Color::Rgb(s(r), s(g), s(b)),
other => other, }
}
fn chevron_colors(wave: Option<usize>) -> [Color; 3] {
let brand = [theme::PURPLE, theme::CYAN, theme::GREEN];
match wave {
None => brand.map(|c| c.color()),
Some(step) => {
let bright = step % 3;
let mut out = [Color::Reset; 3];
for (i, c) in brand.iter().enumerate() {
out[i] = if i == bright { c.color() } else { dimmed(*c) };
}
out
}
}
}
pub fn one_line(wave: Option<usize>) -> Line<'static> {
let colors = chevron_colors(wave);
let mut spans: Vec<Span> = colors
.iter()
.map(|c| Span::styled("❯", Style::default().fg(*c).add_modifier(Modifier::BOLD)))
.collect();
spans.push(Span::styled(
" Metrale Engine",
theme::text().add_modifier(Modifier::BOLD),
));
Line::from(spans)
}
pub fn three_line(wave: Option<usize>) -> [Line<'static>; 3] {
let colors = chevron_colors(wave);
let row = |r: usize, with_wordmark: Option<(&'static str, Style)>| -> Line<'static> {
let mut spans: Vec<Span> = Vec::with_capacity(7);
spans.push(Span::raw(" "));
for (i, color) in colors.iter().enumerate() {
spans.push(Span::styled(CHEVRON_ROWS[r], Style::default().fg(*color)));
if i < 2 {
spans.push(Span::raw(" "));
}
}
if let Some((text, style)) = with_wordmark {
spans.push(Span::raw(" "));
spans.push(Span::styled(text, style));
}
Line::from(spans)
};
[
row(0, None),
row(
1,
Some(("M E T R A L E", theme::text().add_modifier(Modifier::BOLD))),
),
row(2, Some(("E N G I N E", theme::dim()))),
]
}
#[derive(Clone, Debug)]
pub struct Badge {
pub text: String,
pub tint: BadgeTint,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum BadgeTint {
Model,
Quant,
Role,
Neutral,
}
pub fn badges(a: &crate::cli::ServeArgs, awaiting_model: bool) -> Vec<Badge> {
let mut out = Vec::new();
if awaiting_model {
out.push(Badge {
text: "no model · press 4 for Library".into(),
tint: BadgeTint::Neutral,
});
out.push(Badge {
text: format!(":{}", a.port),
tint: BadgeTint::Neutral,
});
return out;
}
let model = a
.model_name
.clone()
.or_else(|| a.model.clone())
.unwrap_or_else(|| "<model>".into());
out.push(Badge {
text: model,
tint: BadgeTint::Model,
});
out.push(Badge {
text: format!(
"kv {} · lm {} · mtp {}",
a.kv_cache_dtype.as_deref().unwrap_or("auto"),
a.lm_head_dtype,
a.mtp_quantization
),
tint: BadgeTint::Quant,
});
if a.dflash {
out.push(Badge {
text: match a.dflash_gamma {
Some(g) => format!("DFlash γ={g}"),
None => "DFlash γ=auto".to_string(),
},
tint: BadgeTint::Quant,
});
} else if a.speculative || a.self_speculative || a.ngram_speculative {
out.push(Badge {
text: match a.num_drafts {
Some(n) => format!("MTP k={}", n + 1),
None => "MTP k=auto".to_string(),
},
tint: BadgeTint::Quant,
});
} else {
out.push(Badge {
text: "spec off".into(),
tint: BadgeTint::Neutral,
});
}
out.push(Badge {
text: format!("batch {}", a.max_batch_size),
tint: BadgeTint::Neutral,
});
out.push(Badge {
text: format!("ctx {}", human_tokens(a.max_seq_len)),
tint: BadgeTint::Neutral,
});
let role = if a.rank == 0 { "head" } else { "worker" };
out.push(Badge {
text: format!(
"{role} {}/{} · tp{} · ep{}",
a.rank, a.world_size, a.tp_size, a.ep_size
),
tint: BadgeTint::Role,
});
out.push(Badge {
text: format!("sched {}", a.scheduler),
tint: BadgeTint::Neutral,
});
if a.hermetic {
out.push(Badge {
text: "HERMETIC · KAT".to_string(),
tint: BadgeTint::Quant,
});
}
if a.prefix_caching_enabled() {
out.push(Badge {
text: format!(
"prefix-cache · ssm {}@{}",
a.ssm_cache_slots, a.ssm_checkpoint_interval
),
tint: BadgeTint::Neutral,
});
}
out.push(Badge {
text: format!(":{}", a.port),
tint: BadgeTint::Neutral,
});
out
}
fn human_tokens(n: usize) -> String {
if n >= 1024 && n.is_multiple_of(1024) {
format!("{}k", n / 1024)
} else {
n.to_string()
}
}
#[cfg(test)]
#[path = "logo_tests.rs"]
mod more_tests;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chevron_rows_are_uniform_width() {
let w = CHEVRON_ROWS[0].chars().count();
assert!(CHEVRON_ROWS.iter().all(|r| r.chars().count() == w));
}
#[test]
fn wave_brightens_one_chevron_at_a_time() {
unsafe { std::env::set_var("COLORTERM", "truecolor") };
for step in 0..3 {
let colors = chevron_colors(Some(step));
let brand: Vec<Color> = [theme::PURPLE, theme::CYAN, theme::GREEN]
.iter()
.map(|c| c.color())
.collect();
let bright = colors.iter().zip(&brand).filter(|(a, b)| a == b).count();
assert_eq!(bright, 1, "step {step}");
}
}
}