mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-21 14:08:11 +02:00
Lot 4 : /api/status, /api/service/log, /api/paths, /api/model/layers en Rust
L'en-tête de l'interface interroge /api/status en boucle : il est désormais assemblé par la façade, à partir des aides portées (état du service par le fichier PID, sonde /health, preset externe, cause d'un échec de chargement lue dans le journal, pourcentage de chargement, preset actif, alertes de volume et de FUSE). Sur une base réelle, sa réponse est octet pour octet celle du Go. Journal du moteur, emplacements et nombre de couches du modèle suivent. L'état du moteur s'appuie sur la résolution des modèles de gguf.rs plutôt que sur sa propre copie. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d805d9f1ba
commit
73db4459d7
6 files changed
+293
-261
No files matched your search
@@ -189,11 +189,11 @@ async fn api_interne_fermee_de_l_exterieur() {
|
||||
#[tokio::test]
|
||||
async fn jeton_entrant_efface_avant_relais() {
|
||||
let b = banc(Some("")).await;
|
||||
let (code, _, body) = get(&b, "/api/status", &[("x-loki-internal", JETON)]).await;
|
||||
let (code, _, body) = get(&b, "/api/relayee-au-go", &[("x-loki-internal", JETON)]).await;
|
||||
assert_eq!(code, StatusCode::OK);
|
||||
assert_eq!(&body[..], b"go:/api/status");
|
||||
assert_eq!(&body[..], b"go:/api/relayee-au-go");
|
||||
let vus = b.etat.vus.lock().unwrap().clone();
|
||||
assert_eq!(vus, vec![("/api/status".to_string(), None)]);
|
||||
assert_eq!(vus, vec![("/api/relayee-au-go".to_string(), None)]);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -80,3 +80,91 @@ async fn ram_et_vram() {
|
||||
assert!(v.is_array(), "{v}");
|
||||
assert!(go.relayed.lock().unwrap().is_empty());
|
||||
}
|
||||
|
||||
fn json(body: &[u8]) -> serde_json::Value {
|
||||
serde_json::from_slice(body).unwrap()
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn statut_moteur_arrete_puis_preset_externe() {
|
||||
let t = tempfile::tempdir().unwrap();
|
||||
let (f, go, _stop) = fakego::start(t.path().into()).await;
|
||||
go.set("config", "CTX", "65536");
|
||||
go.set("config", "PORT", "8099");
|
||||
let (code, _, body) = fakego::get(f, "/api/status", &[]).await;
|
||||
assert_eq!(code, StatusCode::OK);
|
||||
let v = json(&body);
|
||||
assert_eq!(v["state"], "inactive");
|
||||
assert_eq!(v["active"], false);
|
||||
assert_eq!(v["health"], false);
|
||||
assert_eq!(v["ctx"], 65536);
|
||||
assert_eq!(v["port"], 8099);
|
||||
assert_eq!(v["version"], "0.15.0");
|
||||
assert_eq!(v["load_pct"], -1);
|
||||
assert_eq!(v["external"], false);
|
||||
for k in ["warn", "load_error", "preset", "hint"] {
|
||||
assert!(v[k].is_string(), "{k} : {v}");
|
||||
}
|
||||
// Preset externe : prêt sans moteur local.
|
||||
go.set("config", "EXTERNAL", "1");
|
||||
let (_, _, body) = fakego::get(f, "/api/status", &[]).await;
|
||||
let v = json(&body);
|
||||
assert_eq!(
|
||||
(v["active"].clone(), v["health"].clone(), v["state"].clone()),
|
||||
(true.into(), true.into(), "active".into())
|
||||
);
|
||||
assert_eq!(v["external"], true);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn statut_explique_un_echec_de_chargement() {
|
||||
let t = tempfile::tempdir().unwrap();
|
||||
let (f, _go, _stop) = fakego::start(t.path().into()).await;
|
||||
std::fs::write(
|
||||
t.path().join("loki-engine.log"),
|
||||
"llama_model_load: loading model\nllama_model_load: error loading model: unknown model architecture: 'qwen9'\n",
|
||||
)
|
||||
.unwrap();
|
||||
let (_, _, body) = fakego::get(f, "/api/status", &[]).await;
|
||||
let v = json(&body);
|
||||
assert!(
|
||||
v["load_error"]
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.starts_with("Modèle incompatible avec le moteur"),
|
||||
"{v}"
|
||||
);
|
||||
let (_, _, body) = fakego::get(f, "/api/service/log?n=1", &[]).await;
|
||||
assert_eq!(
|
||||
json(&body)["log"],
|
||||
"llama_model_load: error loading model: unknown model architecture: 'qwen9'\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn emplacements_et_couches() {
|
||||
let t = tempfile::tempdir().unwrap();
|
||||
let (f, _go, _stop) = fakego::start(t.path().into()).await;
|
||||
let (code, _, body) = fakego::get(f, "/api/paths", &[]).await;
|
||||
assert_eq!(code, StatusCode::OK);
|
||||
let v = json(&body);
|
||||
for k in [
|
||||
"home",
|
||||
"database",
|
||||
"exe",
|
||||
"installed",
|
||||
"workspace",
|
||||
"memory",
|
||||
"scripts",
|
||||
"presets",
|
||||
"models",
|
||||
"backends",
|
||||
] {
|
||||
assert!(v[k].is_string(), "{k} : {v}");
|
||||
}
|
||||
let (_, _, body) = fakego::get(f, "/api/model/layers", &[]).await;
|
||||
assert_eq!(
|
||||
&body[..],
|
||||
b"{\"error\":\"aucun mod\xc3\xa8le\",\"ok\":false}\n"
|
||||
);
|
||||
}
|
||||
@@ -208,7 +208,7 @@ async fn backend_absent_donne_502() {
|
||||
.unwrap();
|
||||
let (f, _stop) = facade(dead).await;
|
||||
// Route relayée au Go (« / » est servie par la façade elle-même).
|
||||
let req = Request::get(format!("http://{f}/api/status"))
|
||||
let req = Request::get(format!("http://{f}/api/relayee-au-go"))
|
||||
.body(Full::new(Bytes::new()))
|
||||
.unwrap();
|
||||
let resp = client().request(req).await.unwrap();
|
||||
|
||||
Reference in new issue
Block a user