Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com> Reviewed-on: #5
93 lines
2.5 KiB
Rust
93 lines
2.5 KiB
Rust
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<String>,
|
|
}
|
|
|
|
/// Response from Ollama's `GET /api/tags` endpoint.
|
|
#[cfg(feature = "server")]
|
|
#[derive(Deserialize)]
|
|
struct OllamaTagsResponse {
|
|
models: Vec<OllamaModel>,
|
|
}
|
|
|
|
/// 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 <ollama_url>/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<OllamaStatus, ServerFnError> {
|
|
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,
|
|
})
|
|
}
|