mirror of
https://github.com/R0m1k3/Loki.git
synced 2026-10-21 22:18:13 +02:00
Purge du code de compatibilite jean, base bbolt et arborescence ajean
- suppression des migrations d'agencement, d'unites et de dossier de donnees - store bbolt unique (ajean.db) : config, prefs, conversation, cles, drapeaux - arborescence backends/ bin/ presets/ memory/ models/ workspace/ - plus aucune variable, unite ou asset nomme jean
This commit is contained in:
1 parent
081a88c846
commit
2455d9f402
78 files changed
+1160
-2293
No files matched your search
@@ -239,24 +239,23 @@
|
||||
</div>
|
||||
</details>
|
||||
<details id="lc-details"><summary><span class="stitle">Moteur</span></summary>
|
||||
<div class="subhead">Installation</div>
|
||||
<!-- Une seule carte : état, choix du mode et journal d'installation sont le
|
||||
même sujet. Les trois modes sont des LIGNES de cette carte (elles
|
||||
étaient des cartes dans une carte). -->
|
||||
<div class="slist">
|
||||
<!-- Texte de départ IDENTIQUE (à la variante près) à celui posé après le
|
||||
chargement : un simple « … » faisait grandir la carte sous les yeux dès
|
||||
que l'état arrivait. -->
|
||||
<div class="rowbody"><div id="lc-status" class="lc-head muted">Installez les moteurs ici. Vous choisissez lequel utiliser en éditant un modèle.</div></div>
|
||||
<!-- La pastille « conseillé » n'est PAS écrite ici : le bon choix dépend de
|
||||
la machine (voir lcRenderReco). Sur Linux + NVIDIA le précompilé ne
|
||||
donne que du Vulkan — llama.cpp ne publie aucun binaire CUDA Linux —
|
||||
alors que compiler donne du CUDA natif. -->
|
||||
<div class="lc-modes">
|
||||
<div class="lc-mode" id="lc-mode-fast" onclick="lcPick('fast')">
|
||||
<div class="lc-mode-t">llama.cpp précompilé <span class="lc-reco">conseillé</span></div>
|
||||
<div class="lc-mode-d">binaire officiel téléchargé tel quel, prêt en ~2 min</div>
|
||||
<div class="lc-mode-t">llama.cpp précompilé <span class="lc-reco" id="lc-reco-fast" hidden>conseillé</span></div>
|
||||
<div class="lc-mode-d" id="lc-desc-fast">binaire officiel téléchargé tel quel, prêt en ~2 min</div>
|
||||
<div class="lc-mode-state" id="lc-fast-state"></div>
|
||||
</div>
|
||||
<div class="lc-mode" id="lc-mode-opt" onclick="lcPick('opt')">
|
||||
<div class="lc-mode-t">llama.cpp compilé</div>
|
||||
<div class="lc-mode-d">compilé ici pour votre machine — plus rapide, plus long à installer</div>
|
||||
<div class="lc-mode-t">llama.cpp compilé <span class="lc-reco" id="lc-reco-opt" hidden>conseillé</span></div>
|
||||
<div class="lc-mode-d" id="lc-desc-opt">compilé ici pour votre machine — plus rapide, plus long à installer</div>
|
||||
<div class="lc-mode-state" id="lc-opt-state"></div>
|
||||
</div>
|
||||
<div class="lc-mode" id="lc-mode-custom" onclick="openCustomBackends()">
|
||||
@@ -489,6 +488,10 @@
|
||||
<div id="m-hf-progress" class="pe-note" style="display:none"></div>
|
||||
<button id="m-hf-cancel" class="pe-link" onclick="cancelDownload()" style="display:none">Annuler le téléchargement</button>
|
||||
</div>
|
||||
<div class="pe-row">
|
||||
<span class="pe-row-l">Destination</span>
|
||||
<span class="pe-selc"><select id="m-hf-dir"></select></span>
|
||||
</div>
|
||||
<div id="m-dirs-toggle" class="pe-row" style="cursor:pointer" onclick="toggleModelDirs()">
|
||||
<span class="pe-row-l">Dossiers de modèles<span class="pe-sub">chercher les .gguf ailleurs (disque externe…)</span></span>
|
||||
<span class="pe-row-c"><span id="m-dirs-caret" class="pe-caret"></span></span>
|
||||
@@ -499,7 +502,7 @@
|
||||
<input id="m-dir-path" class="pe-inp" placeholder="/media/disque-externe/models">
|
||||
<button id="m-dir-add" onclick="addModelDir()" title="Ajouter ce dossier">+</button>
|
||||
</div>
|
||||
<div class="pe-note">Les téléchargements, eux, vont toujours dans le dossier AJEAN.</div>
|
||||
<div class="pe-note">Ces dossiers servent aussi de destination de téléchargement.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -153,7 +153,7 @@ async function openItem(kind, key){
|
||||
document.getElementById('m-quant').value = currentQuantInTextarea();
|
||||
populateSettings();
|
||||
attachDownload(); // téléchargement encore en cours côté serveur ?
|
||||
await Promise.all([populateBackend(), populateModelPicker()]);
|
||||
await Promise.all([populateBackend(), populateModelPicker(), populateDlDirs()]);
|
||||
if(seq !== openSeq) return;
|
||||
}
|
||||
// On lève le voile SANS transition (voir la note dans styles.css), puis on rend
|
||||
@@ -252,7 +252,8 @@ async function populateModelDirs(){
|
||||
const info = document.createElement('span');
|
||||
info.className = 'muted';
|
||||
const n = x.count >= 0 ? (x.count + ' modèle' + (x.count>1?'s':'')) : 'illisible';
|
||||
info.textContent = '(' + n + (x.home ? ', dossier jean' : '') + ')';
|
||||
const free = x.free >= 0 ? ', ' + fmtSize(x.free) + ' libres' : '';
|
||||
info.textContent = '(' + n + free + (x.home ? ', dossier jean' : '') + ')';
|
||||
row.append(p, info);
|
||||
if(!x.home){
|
||||
const del = document.createElement('button');
|
||||
@@ -273,13 +274,13 @@ async function addModelDir(){
|
||||
if(!r.ok){ toast('erreur : ' + (r.error||'')); return; }
|
||||
inp.value = '';
|
||||
toast('dossier ajouté');
|
||||
await Promise.all([populateModelDirs(), populateModelPicker()]);
|
||||
await Promise.all([populateModelDirs(), populateModelPicker(), populateDlDirs()]);
|
||||
}
|
||||
async function removeModelDir(p){
|
||||
const r = await jpost('/api/models/dirs', {path: p, action: 'remove'});
|
||||
if(!r.ok){ toast('erreur : ' + (r.error||'')); return; }
|
||||
toast('dossier retiré');
|
||||
await Promise.all([populateModelDirs(), populateModelPicker()]);
|
||||
await Promise.all([populateModelDirs(), populateModelPicker(), populateDlDirs()]);
|
||||
}
|
||||
function onPickModel(){
|
||||
const val = document.getElementById('m-model').value;
|
||||
@@ -772,17 +773,50 @@ function resetDlUI(){
|
||||
e.prog.style.display='none'; e.bar.style.display='none';
|
||||
e.cancel.style.display='none'; e.btn.disabled=false;
|
||||
}
|
||||
// Remplit le sélecteur de destination avec les dossiers de modèles connus.
|
||||
// L'espace libre est dans le libellé de l'option : c'est l'info utile au moment
|
||||
// de choisir, et ça évite une ligne de plus dans une modale déjà chargée.
|
||||
// Même source que « Dossiers de modèles » : ajouter un disque externe là-bas le
|
||||
// rend aussitôt disponible ici.
|
||||
let dlDirList = [];
|
||||
async function populateDlDirs(){
|
||||
const sel = document.getElementById('m-hf-dir');
|
||||
if(!sel) return;
|
||||
let d = {};
|
||||
try{ d = await jget('/api/models/dirs'); }catch(_){ return; }
|
||||
dlDirList = d.dirs || [];
|
||||
const prev = sel.value;
|
||||
sel.innerHTML = '';
|
||||
for(const x of dlDirList){
|
||||
const o = document.createElement('option');
|
||||
o.value = x.path;
|
||||
o.textContent = x.path + (x.free >= 0 ? ' — ' + fmtSize(x.free) + ' libres' : '');
|
||||
sel.append(o);
|
||||
}
|
||||
if(prev && dlDirList.some(x => samePath(x.path, prev))) sel.value = prev;
|
||||
}
|
||||
async function startDownload(){
|
||||
const url = document.getElementById('m-hf-url').value.trim();
|
||||
if(!url){ toast('colle un lien .gguf'); return; }
|
||||
const dir = (document.getElementById('m-hf-dir')||{}).value || '';
|
||||
const e = dlEls();
|
||||
e.btn.disabled = true;
|
||||
e.prog.style.display = 'block';
|
||||
e.prog.textContent = 'démarrage…';
|
||||
e.prog.textContent = 'vérification de la taille et de l’espace disque…';
|
||||
e.bar.style.display = 'block';
|
||||
e.bar.className = 'pe-bar indet';
|
||||
e.bar.firstElementChild.style.width = '';
|
||||
const r = await jpost('/api/models/download', {url});
|
||||
// Sonde d'abord : on connaît la taille exacte du fichier et l'espace restant
|
||||
// AVANT d'écrire quoi que ce soit, plutôt que d'échouer à 90 % du transfert.
|
||||
const p = await jpost('/api/models/download/probe', {url, dir});
|
||||
if(!p.ok || !p.enough){
|
||||
e.prog.innerHTML = '<span style="color:var(--err)">erreur : '+escHtml(p.error||'espace insuffisant')+'</span>';
|
||||
e.bar.style.display = 'none'; e.btn.disabled=false;
|
||||
await populateDlDirs();
|
||||
return;
|
||||
}
|
||||
e.prog.textContent = fmtSize(p.size)+' à télécharger — '+fmtSize(p.free)+' libres';
|
||||
const r = await jpost('/api/models/download', {url, dir});
|
||||
if(!r.ok){
|
||||
e.prog.innerHTML = '<span style="color:var(--err)">erreur : '+(r.error||'')+'</span>';
|
||||
e.bar.style.display = 'none'; e.btn.disabled=false; return;
|
||||
@@ -825,8 +859,12 @@ function watchDownload(fname){
|
||||
e.prog.innerHTML = '<span style="color:var(--ok)">✓ '+fname+' téléchargé ('+fmtSize(st.done)+')</span>';
|
||||
e.bar.className = 'pe-bar done'; e.bar.firstElementChild.style.width = '100%';
|
||||
stop();
|
||||
await populateModelPicker();
|
||||
document.getElementById('m-model').value = fname; onPickModel();
|
||||
await Promise.all([populateModelPicker(), populateDlDirs()]);
|
||||
// Le modèle a pu atterrir hors du dossier jean : l'option porte alors le
|
||||
// chemin complet, pas le simple nom de fichier.
|
||||
const sel = document.getElementById('m-model');
|
||||
const opt = Array.from(sel.options).find(o => samePath(baseName(o.value), fname));
|
||||
if(opt){ sel.value = opt.value; onPickModel(); }
|
||||
return;
|
||||
}
|
||||
const pct = st.total>0 ? st.done*100/st.total : 0;
|
||||
|
||||
@@ -15,12 +15,7 @@ async function loadLlamacpp(){
|
||||
const fastInstalled = !!pb.bin;
|
||||
const optInstalled = !!s.bin;
|
||||
|
||||
const head = document.getElementById('lc-status');
|
||||
if(!fastInstalled && !optInstalled){
|
||||
head.innerHTML = 'Installez le moteur d\'IA. Le <b>précompilé</b> convient à presque tout le monde.';
|
||||
} else {
|
||||
head.innerHTML = 'Installez les moteurs ici. Vous choisissez lequel utiliser en éditant un modèle (bouton ⚙).';
|
||||
}
|
||||
lcRenderReco(s.reco);
|
||||
lcRenderMode('fast', fastInstalled);
|
||||
lcRenderMode('opt', optInstalled);
|
||||
lcRenderCustomCard();
|
||||
@@ -78,6 +73,23 @@ function lcChipOpen(){
|
||||
lcChipSync(null);
|
||||
}
|
||||
|
||||
// Place la pastille « conseillé » sur la carte que le SERVEUR recommande pour
|
||||
// cette machine (voir recommendedMode) : le précompilé partout, sauf sur Linux
|
||||
// avec une carte NVIDIA où il ne donnerait que du Vulkan. La raison est ajoutée
|
||||
// à la description de la carte, pour expliquer plutôt que d'imposer.
|
||||
function lcRenderReco(reco){
|
||||
const mode = (reco && reco.mode) || 'fast';
|
||||
for(const m of ['fast','opt']){
|
||||
const badge = document.getElementById('lc-reco-'+m);
|
||||
if(badge) badge.hidden = (m !== mode);
|
||||
}
|
||||
// La raison REMPLACE la description générique de la carte conseillée : elle
|
||||
// dit déjà ce que fait l'option et pourquoi c'est le bon choix ici. (loadAll
|
||||
// repasse par là, donc pas d'accumulation possible.)
|
||||
const desc = document.getElementById('lc-desc-'+mode);
|
||||
if(desc && reco && reco.why) desc.textContent = reco.why;
|
||||
}
|
||||
|
||||
function lcRenderMode(mode, installed){
|
||||
const card = document.getElementById(mode==='fast' ? 'lc-mode-fast' : 'lc-mode-opt');
|
||||
const state = document.getElementById(mode==='fast' ? 'lc-fast-state' : 'lc-opt-state');
|
||||
|
||||
Reference in new issue
Block a user