llm-manager 1.1.0

Terminal UI for managing LLMs
Documentation
use ratatui::{
    style::{Color, Modifier, Style},
    text::{Line, Span},
};

pub fn render_api_endpoints(app: &crate::tui::app::App) -> Vec<Line<'static>> {
    let mut lines = Vec::new();
    let y = Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD);
    let g = Style::default().fg(Color::Green);
    let c = Style::default().fg(Color::Cyan);
    let d = Style::default().fg(Color::DarkGray);
    let magenta = Style::default().fg(Color::Magenta);

    let enabled = app.settings.api_endpoint_enabled;

    lines.push(Line::from(vec![
        Span::styled("API Endpoints", y),
        Span::raw(""),
        Span::styled("Esc / ⌃A to close", d),
    ]));
    lines.push(Line::from(""));

    if enabled {
        let host = app.settings.host.clone();
        let port = app.settings.api_endpoint_port;
        let url = format!("http://{}:{}", host, port);
        lines.push(Line::from(vec![
            Span::styled("Base URL: ", d),
            Span::raw(url).style(c),
        ]));
        lines.push(Line::from(vec![
            Span::styled("Auth: ", d),
            Span::styled("Bearer token required", magenta),
        ]));
    } else {
        lines.push(Line::from(vec![
            Span::styled("API proxy: ", d),
            Span::styled("Disabled", g),
        ]));
        lines.push(Line::from(vec![
            Span::styled("Enable in Server Settings (F2) to expose endpoints", d),
        ]));
    }

    lines.push(Line::from(""));

    lines.push(Line::from(vec![
        Span::styled("Explicitly handled endpoints:", y),
    ]));
    lines.push(Line::from(""));
    lines.push(Line::from(format!(
        "  {:<6} {:<30} {}",
        Span::styled("METHOD", y),
        Span::styled("PATH", y),
        Span::styled("DESCRIPTION", y),
    )));
    lines.push(Line::from(vec![
        Span::raw("  "),
        Span::styled("GET", g),
        Span::raw("  "),
        Span::raw("/health"),
        Span::raw("            Health check"),
    ]));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("GET", g),
        Span::raw("/metrics"),
        Span::raw("Prometheus metrics"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/v1/chat/completions"),
        Span::raw("Chat completions (OpenAI)"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/v1/completions"),
        Span::raw("Completions (OpenAI)"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/v1/embeddings"),
        Span::raw("Embeddings"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("GET", g),
        Span::raw("/v1/models"),
        Span::raw("List models"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("GET", g),
        Span::raw("/api/status"),
        Span::raw("Server status (pid, uptime, loaded models)"),
    )));
    lines.push(Line::from(""));

    lines.push(Line::from(vec![
        Span::styled("llama.cpp endpoints (proxied via fallback):", y),
    ]));
    lines.push(Line::from(""));
    lines.push(Line::from(format!(
        "  {:<6} {:<30} {}",
        Span::styled("METHOD", y),
        Span::styled("PATH", y),
        Span::styled("DESCRIPTION", y),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/completion"),
        Span::raw("Legacy completion"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/infill"),
        Span::raw("Code completion (FIM)"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/reranking"),
        Span::raw("Re-ranking"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/tokenize"),
        Span::raw("Tokenize text"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/detokenize"),
        Span::raw("Detokenize tokens"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/apply-template"),
        Span::raw("Apply chat template"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("GET", g),
        Span::raw("/v1/health"),
        Span::raw("Health check (alias)"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("GET/POST", magenta),
        Span::raw("/props"),
        Span::raw("Get/set server properties"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("GET", g),
        Span::raw("/slots"),
        Span::raw("Slot monitoring"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("GET/POST", magenta),
        Span::raw("/lora-adapters"),
        Span::raw("List/load LoRA adapters"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/models/load"),
        Span::raw("Load a model (router mode)"),
    )));
    lines.push(Line::from(format!(
        "  {}  {:<30} {}",
        Span::styled("POST", y),
        Span::raw("/models/unload"),
        Span::raw("Unload a model (router mode)"),
    )));
    lines.push(Line::from(""));
    lines.push(Line::from(vec![
        Span::styled("Note: ", d),
        Span::raw("Any other path not listed above is also proxied to llama.cpp."),
    ]));
    lines.push(Line::from(""));
    lines.push(Line::from(vec![
        Span::styled("j/k scroll", d),
        Span::raw("  "),
        Span::styled("Esc / ⌃A close", d),
    ]));

    lines
}