inferno-ai 0.10.3

Enterprise AI/ML model runner with automatic updates, real-time monitoring, and multi-interface support
use ratatui::{
    Frame,
    layout::Rect,
    style::{Color, Modifier, Style},
    widgets::{Block, Borders, Gauge, List, ListItem, Paragraph, Wrap},
};

pub struct ProgressBar {
    pub label: String,
    pub progress: f64,
    pub color: Color,
}

impl ProgressBar {
    pub fn new(label: String, progress: f64) -> Self {
        let color = if progress < 0.3 {
            Color::Red
        } else if progress < 0.7 {
            Color::Yellow
        } else {
            Color::Green
        };

        Self {
            label,
            progress,
            color,
        }
    }

    pub fn render(&self, f: &mut Frame, area: Rect) {
        let gauge = Gauge::default()
            .block(
                Block::default()
                    .borders(Borders::ALL)
                    .title(self.label.clone()),
            )
            .gauge_style(Style::default().fg(self.color))
            .percent((self.progress * 100.0) as u16)
            .label(format!("{:.1}%", self.progress * 100.0));

        f.render_widget(gauge, area);
    }
}

#[allow(dead_code)]
pub struct StatusDisplay {
    pub items: Vec<(String, String)>,
    pub title: String,
}

#[allow(dead_code)]
impl StatusDisplay {
    pub fn new(title: String) -> Self {
        Self {
            items: Vec::new(),
            title,
        }
    }

    pub fn add_item(&mut self, key: String, value: String) {
        self.items.push((key, value));
    }

    pub fn render(&self, f: &mut Frame, area: Rect) {
        let text = self
            .items
            .iter()
            .map(|(key, value)| format!("{}: {}", key, value))
            .collect::<Vec<_>>()
            .join("\n");

        let paragraph = Paragraph::new(text)
            .block(
                Block::default()
                    .borders(Borders::ALL)
                    .title(self.title.clone()),
            )
            .wrap(Wrap { trim: true });

        f.render_widget(paragraph, area);
    }
}

#[allow(dead_code)]
pub struct ModelCard {
    pub name: String,
    pub path: String,
    pub size: String,
    pub backend: String,
    pub is_loaded: bool,
}

#[allow(dead_code)]
impl ModelCard {
    pub fn render(&self, f: &mut Frame, area: Rect) {
        let status_indicator = if self.is_loaded { "" } else { "" };
        let status_color = if self.is_loaded {
            Color::Green
        } else {
            Color::Gray
        };

        let content = format!(
            "{} {}\n\
             Backend: {}\n\
             Size: {}\n\
             Path: {}",
            status_indicator, self.name, self.backend, self.size, self.path
        );

        let card = Paragraph::new(content)
            .block(
                Block::default()
                    .borders(Borders::ALL)
                    .title(" Model Info ")
                    .border_style(Style::default().fg(status_color)),
            )
            .style(Style::default().fg(Color::White))
            .wrap(Wrap { trim: true });

        f.render_widget(card, area);
    }
}

#[allow(dead_code)]
pub struct TokenStream {
    pub tokens: Vec<String>,
    pub max_display: usize,
}

#[allow(dead_code)]
impl TokenStream {
    pub fn new(max_display: usize) -> Self {
        Self {
            tokens: Vec::new(),
            max_display,
        }
    }

    pub fn add_token(&mut self, token: String) {
        self.tokens.push(token);
        if self.tokens.len() > self.max_display {
            self.tokens.remove(0);
        }
    }

    pub fn render(&self, f: &mut Frame, area: Rect) {
        let items: Vec<ListItem> = self
            .tokens
            .iter()
            .enumerate()
            .map(|(i, token)| {
                let style = if i == self.tokens.len() - 1 {
                    Style::default()
                        .fg(Color::Yellow)
                        .add_modifier(Modifier::BOLD)
                } else {
                    Style::default()
                };
                ListItem::new(token.as_str()).style(style)
            })
            .collect();

        let list = List::new(items).block(
            Block::default()
                .borders(Borders::ALL)
                .title(" Token Stream "),
        );

        f.render_widget(list, area);
    }
}