use dioxus::prelude::*; use serde::{Deserialize, Serialize}; /// Status of a local Ollama instance, including connectivity and loaded models. /// /// # Fields /// /// * `online` - Whether the Ollama API responded successfully /// * `models` - List of model names currently available on the instance #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct OllamaStatus { pub online: bool, pub models: Vec, } /// Response from Ollama's `GET /api/tags` endpoint. #[cfg(feature = "server")] #[derive(Deserialize)] struct OllamaTagsResponse { models: Vec, } /// A single model entry from Ollama's tags API. #[cfg(feature = "server")] #[derive(Deserialize)] struct OllamaModel { name: String, } /// Check the status of a local Ollama instance by querying its tags endpoint. /// /// Calls `GET /api/tags` to list available models and determine /// whether the instance is reachable. /// /// # Arguments /// /// * `ollama_url` - Base URL of the Ollama instance (e.g. "http://localhost:11434") /// /// # Returns /// /// An `OllamaStatus` with `online: true` and model names if reachable, /// or `online: false` with an empty model list on failure /// /// # Errors /// /// Returns `ServerFnError` only on serialization issues; network failures /// are caught and returned as `online: false` #[post("/api/ollama-status")] pub async fn get_ollama_status(ollama_url: String) -> Result { let state: crate::infrastructure::ServerState = dioxus_fullstack::FullstackContext::extract().await?; let base_url = if ollama_url.is_empty() { state.services.ollama_url.clone() } else { ollama_url }; let url = format!("{}/api/tags", base_url.trim_end_matches('/')); let client = reqwest::Client::builder() .timeout(std::time::Duration::from_secs(5)) .build() .map_err(|e| ServerFnError::new(format!("HTTP client error: {e}")))?; let resp = match client.get(&url).send().await { Ok(r) if r.status().is_success() => r, _ => { return Ok(OllamaStatus { online: false, models: Vec::new(), }); } }; let body: OllamaTagsResponse = match resp.json().await { Ok(b) => b, Err(_) => { return Ok(OllamaStatus { online: true, models: Vec::new(), }); } }; let models = body.models.into_iter().map(|m| m.name).collect(); Ok(OllamaStatus { online: true, models, }) }