use codewhale_config::model_reference::ModelReferenceDatabase;
use ratatui::style::{Modifier, Style};
use ratatui::text::Line;
use crate::commands::traits::{CommandInfo, RegisterCommand};
use crate::localization::MessageId;
use crate::tui::app::App;
use crate::tui::pager::PagerView;
use super::CommandResult;
pub(in crate::commands) const COMMAND_INFO: CommandInfo = CommandInfo {
name: "modeldb",
aliases: &["model-reference", "modelref"],
usage: "/modeldb",
description_id: MessageId::CmdModelDbDescription,
};
pub(in crate::commands) struct ModelDbCmd;
impl RegisterCommand for ModelDbCmd {
fn info() -> &'static CommandInfo {
&COMMAND_INFO
}
fn execute(app: &mut App, _arg: Option<&str>) -> CommandResult {
let db = ModelReferenceDatabase::bundled();
let title = format!(
"Model Reference — {} offerings · {} providers",
db.len(),
db.providers().len()
);
app.view_stack
.push(PagerView::new(title, reference_lines(&db)));
CommandResult::ok()
}
}
fn reference_lines(db: &ModelReferenceDatabase) -> Vec<Line<'static>> {
let bold = Style::default().add_modifier(Modifier::BOLD);
let dim = Style::default().add_modifier(Modifier::DIM);
let mut lines: Vec<Line<'static>> = Vec::new();
lines.push(Line::styled(
"Bundled curated model reference catalog.".to_string(),
bold,
));
lines.push(Line::styled(
"Attributes are stated facts; \"unknown\" means the catalog did not state it (never guessed)."
.to_string(),
dim,
));
lines.push(Line::from(String::new()));
if db.is_empty() {
lines.push(Line::from("(no models in catalog)".to_string()));
return lines;
}
let cards = db.cards();
let id_w = cards
.iter()
.map(|card| card.model_id.chars().count())
.chain(std::iter::once("MODEL ID".len()))
.max()
.unwrap_or(8)
.clamp(8, 46);
let ctx_w = cards
.iter()
.map(|card| card.context_window_label().chars().count())
.chain(std::iter::once("CTX".len()))
.max()
.unwrap_or(3);
let out_w = cards
.iter()
.map(|card| card.max_output_label().chars().count())
.chain(std::iter::once("MAX OUT".len()))
.max()
.unwrap_or(7);
let mod_w = "multimodal".len();
lines.push(Line::styled(
format!(
" {} {} {} {} {}",
pad("MODEL ID", id_w),
pad("CTX", ctx_w),
pad("MAX OUT", out_w),
pad("MODALITY", mod_w),
"PRICE (USD/Mtok)"
),
bold,
));
let mut current_provider: Option<&str> = None;
for card in cards {
if current_provider != Some(card.provider.as_str()) {
lines.push(Line::from(String::new()));
lines.push(Line::styled(
format!(
"{} · kind: {}",
card.provider,
card.provider_kind_label()
),
bold,
));
current_provider = Some(card.provider.as_str());
}
lines.push(Line::from(format!(
" {} {} {} {} {}",
pad(&truncate_to(&card.model_id, id_w), id_w),
pad(&card.context_window_label(), ctx_w),
pad(&card.max_output_label(), out_w),
pad(card.modality.as_str(), mod_w),
card.price_label(),
)));
}
lines
}
fn pad(s: &str, width: usize) -> String {
let len = s.chars().count();
if len >= width {
s.to_string()
} else {
format!("{s}{}", " ".repeat(width - len))
}
}
fn truncate_to(s: &str, width: usize) -> String {
let count = s.chars().count();
if count <= width {
return s.to_string();
}
if width <= 1 {
return s.chars().take(width).collect();
}
let mut truncated: String = s.chars().take(width - 1).collect();
truncated.push('…');
truncated
}
#[cfg(test)]
mod tests {
use super::*;
fn rendered(db: &ModelReferenceDatabase) -> Vec<String> {
reference_lines(db)
.iter()
.map(|line| {
line.spans
.iter()
.map(|span| span.content.as_ref())
.collect::<String>()
})
.collect()
}
#[test]
fn bundled_reference_lists_models_with_factual_columns() {
let db = ModelReferenceDatabase::bundled();
let text = rendered(&db).join("\n");
assert!(text.contains("never guessed"));
assert!(text.contains("MODEL ID"));
assert!(text.contains("MODALITY"));
assert!(text.contains("PRICE (USD/Mtok)"));
assert!(text.contains("kind: deepseek"));
assert!(text.contains("deepseek-v4-pro"));
assert!(text.contains("text"));
assert!(text.contains("unknown"));
assert!(text.contains("$0.30 / $1.20 per Mtok"));
}
#[test]
fn empty_database_renders_placeholder_not_a_crash() {
let db = ModelReferenceDatabase::from_offerings(&[]);
let text = rendered(&db).join("\n");
assert!(text.contains("(no models in catalog)"));
}
#[test]
fn pad_and_truncate_are_width_safe() {
assert_eq!(pad("ab", 5), "ab ");
assert_eq!(pad("abcde", 3), "abcde");
assert_eq!(truncate_to("short", 10), "short");
assert_eq!(truncate_to("abcdefghij", 5), "abcd…");
}
}