minor UI fixes

This commit is contained in:
itsamejms
2026-07-13 10:39:51 +01:00
parent a24f3615e0
commit a6171a8158
31 changed files with 1528 additions and 508 deletions
+66
View File
@@ -81,6 +81,72 @@ pub fn set_llm_config(state: tauri::State<'_, AppState>, config: crate::llm::Llm
Ok(())
}
// ─── Connection test: list models from the configured endpoint ──
// ponytail: Ollama exposes GET /api/tags, OpenAI-compatible exposes
// GET /v1/models. Returns the model names so Settings can show a list and
// a green/red pill. Best-effort — surface the error string on failure.
#[derive(serde::Serialize)]
pub struct ConnectionTest {
pub ok: bool,
pub models: Vec<String>,
pub error: String,
}
#[tauri::command]
pub async fn test_connection(state: tauri::State<'_, AppState>) -> Result<ConnectionTest, String> {
let config = state.config.lock().map_err(|e| e.to_string())?.clone();
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(8))
.build()
.map_err(|e| e.to_string())?;
if llm::is_ollama(&config.api_url) {
let url = format!("{}/api/tags", config.api_url.trim_end_matches('/'));
let res = client.get(&url).send().await.map_err(|e| e.to_string())?;
if !res.status().is_success() {
return Ok(ConnectionTest {
ok: false,
models: vec![],
error: format!("HTTP {}", res.status()),
});
}
let body: serde_json::Value = res.json().await.map_err(|e| e.to_string())?;
let models = body["models"]
.as_array()
.map(|a| {
a.iter()
.filter_map(|m| m["name"].as_str().map(|s| s.to_string()))
.collect()
})
.unwrap_or_default();
Ok(ConnectionTest { ok: true, models, error: String::new() })
} else {
let url = format!("{}/v1/models", config.api_url.trim_end_matches('/'));
let mut req = client.get(&url);
if !config.api_key.is_empty() {
req = req.bearer_auth(&config.api_key);
}
let res = req.send().await.map_err(|e| e.to_string())?;
if !res.status().is_success() {
return Ok(ConnectionTest {
ok: false,
models: vec![],
error: format!("HTTP {}", res.status()),
});
}
let body: serde_json::Value = res.json().await.map_err(|e| e.to_string())?;
let models = body["data"]
.as_array()
.map(|a| {
a.iter()
.filter_map(|m| m["id"].as_str().map(|s| s.to_string()))
.collect()
})
.unwrap_or_default();
Ok(ConnectionTest { ok: true, models, error: String::new() })
}
}
// ─── Lore RAG injection (shared by generate + generate_stream) ─
/// Best-effort: if `rag_query` is set, retrieve top lore chunks and fold them
+1
View File
@@ -36,6 +36,7 @@ pub fn run() {
commands::llm_commands::generate_stream,
commands::llm_commands::get_llm_config,
commands::llm_commands::set_llm_config,
commands::llm_commands::test_connection,
commands::image_commands::generate_image,
commands::rag_commands::rag_add,
commands::rag_commands::rag_search,