Sélecteur de moteur par modèle : « Image » en conteneur, et mention du fork

Le sélecteur de l'éditeur de modèle proposait encore « Précompilé » et
« Compilé » — deux installations que Loki ne fait pas en conteneur : cliquer
répondait « installez d'abord llama.cpp… ». Pire, le moteur de l'image ne
correspondant à aucun des deux, il était classé « Personnalisé ».
En conteneur, ces deux options laissent place à « Image » (sélectionnée par
défaut, y compris pour un preset sans BIN) ; « Personnalisé » reste pour un
binaire déposé dans /data/backends.

Le moteur de l'image est désormais déclaré par l'image elle-même via
LOKI_ENGINE_BIN (Dockerfile + entrypoint) au lieu d'être deviné d'après le
chemin : /api/llamacpp expose provided et provided_bin.

Attribution : sous le nom Loki, « fork de AJEAN » avec lien vers le dépôt
d'origine.

Vérifié dans l'image : provided=true, provided_bin=/app/llama-server,
BIN semé identique ; build, vet et tests verts.
This commit is contained in:
Loki committed 2026-08-15 08:37:48 +00:00
1 parent 5b434a4a59
commit 1f24d8ccf5
7 files changed
+88 -31

No files matched your search

+7 -2
View File
@@ -37,6 +37,7 @@
<h1 id="brand" aria-label="loki" title="Loki — fork d'AJEAN (github.com/nathaninline/ajean, MIT)"><span id="brand-a"><svg viewBox="0 0 4 5" shape-rendering="crispEdges" fill="currentColor"><rect x="0" y="0" width="1" height="5"/><rect x="1" y="4" width="3" height="1"/></svg></span><span id="brand-word"><svg viewBox="0 0 11 5" shape-rendering="crispEdges" fill="currentColor"><rect x="0" y="0" width="3" height="1"/><rect x="0" y="1" width="1" height="3"/><rect x="2" y="1" width="1" height="3"/><rect x="0" y="4" width="3" height="1"/><rect x="4" y="0" width="1" height="5"/><rect x="6" y="0" width="1" height="2"/><rect x="5" y="2" width="1" height="1"/><rect x="6" y="3" width="1" height="2"/><rect x="8" y="0" width="3" height="1"/><rect x="9" y="1" width="1" height="3"/><rect x="8" y="4" width="3" height="1"/></svg></span><span id="ver"></span></h1>
<span id="status-svc" class="statuspill" onclick="toggleSvcLog()" title="voir le journal du moteur">…</span>
</div>
<div class="brand-fork">fork de <a href="https://github.com/nathaninline/ajean" target="_blank" rel="noopener noreferrer" title="AJEAN par nathaninline — licence MIT">AJEAN</a></div>
<!-- Avertissement de lancement (App Translocation macOS) — masqué par défaut. -->
<div id="app-warn" class="muted" style="display:none;font-size:11px;line-height:1.5;margin:0 0 10px;padding:8px 10px;border-radius:8px;color:var(--warn);border:1px solid color-mix(in srgb,var(--warn) 45%,transparent);background:color-mix(in srgb,var(--warn) 12%,transparent)"></div>
<div id="model-err" style="display:none;font-size:11px;line-height:1.5;margin:0 0 10px;padding:8px 10px;border-radius:8px;color:var(--err);border:1px solid color-mix(in srgb,var(--err) 45%,transparent);background:color-mix(in srgb,var(--err) 12%,transparent)"></div>
@@ -669,9 +670,13 @@
<div class="pe-group">
<div class="pe-gh">Moteur</div>
<!-- « Image » n'apparaît qu'en conteneur (moteur fourni), où
« Précompilé » et « Compilé » sont au contraire masqués : ils
désignent des installations que Loki ne fait pas ici. -->
<div class="pe-seg">
<label><input type="radio" name="m-be" value="fast" onchange="onBackendMode('fast')"><span>Précompilé</span><span class="be-note" id="be-fast-note"></span></label>
<label><input type="radio" name="m-be" value="opt" onchange="onBackendMode('opt')"><span>Compilé</span><span class="be-note" id="be-opt-note"></span></label>
<label id="be-lab-image" style="display:none"><input type="radio" name="m-be" value="image" onchange="onBackendMode('image')"><span>Image</span><span class="be-note" id="be-image-note"></span></label>
<label id="be-lab-fast"><input type="radio" name="m-be" value="fast" onchange="onBackendMode('fast')"><span>Précompilé</span><span class="be-note" id="be-fast-note"></span></label>
<label id="be-lab-opt"><input type="radio" name="m-be" value="opt" onchange="onBackendMode('opt')"><span>Compilé</span><span class="be-note" id="be-opt-note"></span></label>
<label><input type="radio" name="m-be" value="custom" onchange="onBackendMode('custom')"><span>Personnalisé</span></label>
</div>
<div id="m-backend-custom" class="pe-list" style="display:none;margin-top:8px">
+18 -3
View File
@@ -384,13 +384,21 @@ function underDir(p, dir){
const n = x => String(x||'').replace(/\\/g,'/').replace(/\/+$/,'').toLowerCase();
return !!p && !!dir && n(p).startsWith(n(dir)+'/');
}
let beFastPath = '', beOptPath = '', beFastDir = '';
let beFastPath = '', beOptPath = '', beFastDir = '', beImagePath = '';
async function populateBackend(){
// Chemins des deux moteurs gérés + liste des backends détectés (dossier loki).
let lc = {}; try{ lc = await jget('/api/llamacpp'); }catch(_){}
beFastPath = (lc.prebuilt && lc.prebuilt.bin) || '';
beFastDir = (lc.prebuilt && lc.prebuilt.dir) || '';
beOptPath = lc.bin || '';
// Conteneur : le moteur vient de l'image. « Précompilé » et « Compilé »
// désignent des installations que Loki ne fait pas ici — les proposer ne
// menait qu'à « installez d'abord… ». On les remplace par « Image ».
beImagePath = lc.provided ? (lc.provided_bin || '') : '';
document.getElementById('be-lab-image').style.display = beImagePath ? '' : 'none';
document.getElementById('be-lab-fast').style.display = beImagePath ? 'none' : '';
document.getElementById('be-lab-opt').style.display = beImagePath ? 'none' : '';
document.getElementById('be-image-note').textContent = beImagePath ? 'llama.cpp officiel' : '';
// Menu « backend détecté » du mode personnalisé : tout ce qu'on trouve dans
// le dossier backends de loki (l'utilisateur peut y déposer son propre build).
const detected = await jget('/api/backends');
@@ -403,7 +411,10 @@ async function populateBackend(){
// Sélectionne l'option correspondant au BIN actuel du preset.
const cur = currentBinInTextarea();
let mode = 'custom';
if(sameBinPath(cur, beFastPath) || underDir(cur, beFastDir)) mode = 'fast';
// Un preset sans BIN hérite du moteur global : en conteneur c'est celui de
// l'image, qu'on affiche comme tel plutôt qu'en « personnalisé ».
if(beImagePath && (sameBinPath(cur, beImagePath) || !cur)) mode = 'image';
else if(sameBinPath(cur, beFastPath) || underDir(cur, beFastDir)) mode = 'fast';
else if(sameBinPath(cur, beOptPath)) mode = 'opt';
const radio = document.querySelector('input[name=m-be][value='+mode+']');
if(radio) radio.checked = true;
@@ -419,7 +430,11 @@ function toggleBackendCustom(mode){
}
function onBackendMode(mode){
toggleBackendCustom(mode);
if(mode === 'fast'){
if(mode === 'image'){
if(!beImagePath){ toast('aucun moteur fourni par l\'image'); return; }
setBinInTextarea(beImagePath); toast('moteur : llama.cpp de l\'image');
loadGpuDevices();
} else if(mode === 'fast'){
if(!beFastPath){ toast('installez d\'abord llama.cpp précompilé (section MOTEUR)'); return; }
setBinInTextarea(beFastPath); toast('moteur : llama.cpp précompilé');
loadGpuDevices();
+6 -1
View File
@@ -107,7 +107,12 @@ h1{margin:0;font-size:18px;color:var(--accent)}
#brand svg{height:10px;width:auto;display:block;shape-rendering:crispEdges;fill:currentColor}
#brand-word{display:inline-flex;color:var(--accent)}
#ver{font-size:10px;font-weight:400;color:var(--dim);margin-left:7px;letter-spacing:0;align-self:flex-end;line-height:1;position:relative;top:1px}
.sidehead{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:18px}
.sidehead{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px}
/* Attribution : Loki est un fork d'AJEAN (MIT). Discrète mais permanente, et le
nom du projet d'origine renvoie à son dépôt. */
.brand-fork{font-size:10px;color:var(--dim);margin:0 0 14px;line-height:1.3}
.brand-fork a{color:var(--dim);text-decoration:underline;text-underline-offset:2px}
.brand-fork a:hover{color:var(--accent)}
/* pastille d'état service, en haut à droite de la barre latérale */
.statuspill{display:inline-flex;align-items:center;gap:6px;font-size:11px;padding:3px 10px;border-radius:999px;border:1px solid var(--border);background:var(--panel);color:var(--dim);font-weight:600;white-space:nowrap;cursor:pointer}
.statuspill.ok{color:var(--ok);border-color:color-mix(in srgb,var(--ok) 45%,transparent);background:color-mix(in srgb,var(--ok) 12%,transparent)}