llama-desktop 2.2.10

Desktop interface for Ollama
// TODO: move this mod into logics

use crate::protocol::ModelList;
use std::{env, fmt::Debug, panic, process};
use url::Url;

const DEFAULT_HOST: &'static str = "http://localhost:11434";

#[dynamic]
static HOST: String = get_ollama_host();

#[must_use]
pub fn path(path: &str) -> String {
    format!("{}{}", HOST.clone(), path)
}

#[must_use]
pub async fn get_models() -> Vec<String> {
    let uri = path("/api/tags");
    let mut models = panic(panic(reqwest::get(uri).await).json::<ModelList>().await).models;
    models.sort_by(|a, b| b.modified_at.cmp(&a.modified_at));
    let models = models
        .iter()
        .map(|model| model.name.to_owned())
        .collect::<Vec<_>>();

    if models.is_empty() {
        panic!("no model found");
    }
    models
}

fn get_ollama_host() -> String {
    let uri = env::var("OLLAMA_HOST").unwrap_or(DEFAULT_HOST.to_string());
    let uri = match Url::parse(&uri) {
        Ok(uri) => uri,
        Err(err) => {
            eprintln!(
                "error parsing \x1b[33m{}\x1b[0m: \x1b[31;1m{:?}\x1b[0m",
                uri, err
            );
            eprintln!("fallback to \x1b[33;1m{}\x1b[0m", DEFAULT_HOST);
            eprintln!(
                "please review the content of environment variable \x1b[32mOLLAMA_HOST\x1b[0m"
            );
            panic(Url::parse(DEFAULT_HOST))
        }
    };
    let host = match uri.host_str() {
        Some(host) => host,
        None => {
            eprintln!("fail to parse {}", uri);
            panic!("parsing error");
        }
    };
    format!(
        "{}://{}:{}",
        uri.scheme(),
        host,
        uri.port().unwrap_or(11434),
    )
}

fn panic<T, E>(value: Result<T, E>) -> T
where
    E: Debug,
{
    match value {
        Ok(value) => value,
        Err(err) => {
            eprintln!(
                "\x1b[31;1m[PANIC] couldn't initialise:\x1b[0m \x1b[1m{:?}\x1b[0m",
                err
            );
            process::exit(1);
        }
    }
}