feat: Cookbook-Download-Fix, Live-Update-Konsole, Profi-Highlight, OpenCode-Guide
Backend: - hf_bin() + HF_DOWNLOAD_ENV zentral in config.py; install-recipe und install-model in cookbook.py nutzten weiter das fehlende `hf` + falsches XET-Env -> Haupt-Installationsweg war ebenso kaputt, jetzt konsistent gefixt Frontend: - Server: laufende Updates (LLM-Engine/OS) live auf der Server-Seite mitlesbar, inkl. klarer Fertig-/Fehlgeschlagen-Meldung (onJobs + Aktueller-Vorgang-Karte) - Cookbook/Profi-Modus: meistgeladenes, passendes Modell wird als "★ Beste Wahl für dein System" hervorgehoben (analog zu den Templates) - Verbinden: OpenCode korrekt per opencode.json (@ai-sdk/openai-compatible) statt irrefuehrender Felder; erklaert "Connect to API"-Fehler (LAN-IP statt localhost) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,12 @@ function mount() {
|
||||
${row("w-reboot", "bolt", "red", "Server neustarten (Reboot)", "Bootet den ganzen Bosgame neu. Alles ist für ~1 Minute offline, auch dieses Dashboard.")}
|
||||
</div>
|
||||
|
||||
<div class="card" id="w-update-card" style="display:none">
|
||||
<div class="card-h"><h3>Aktueller Vorgang</h3><span id="w-update-badge" style="margin-left:auto"></span></div>
|
||||
<div class="card-sub" id="w-update-label">—</div>
|
||||
<div id="w-update-log" class="log" style="max-height:280px"></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-h"><h3>Live-Konsole</h3>
|
||||
<select id="w-console-sel" style="margin:0 0 0 auto;width:240px">
|
||||
@@ -93,8 +99,46 @@ async function selfUpdate() {
|
||||
catch (e) { toast(e.message, true); }
|
||||
}
|
||||
|
||||
// ---- Live-Verlauf laufender Vorgaenge (Updates) direkt auf der Server-Seite ----
|
||||
let activeJob = null; // { id, label }
|
||||
const notified = new Set(); // Job-IDs, fuer die schon eine Abschluss-Meldung kam
|
||||
|
||||
function watchJob(id, label) {
|
||||
activeJob = { id, label };
|
||||
const card = $("#w-update-card");
|
||||
if (!card) return;
|
||||
card.style.display = "";
|
||||
$("#w-update-label").textContent = label + " läuft…";
|
||||
$("#w-update-badge").innerHTML = '<span class="badge b-load">läuft…</span>';
|
||||
$("#w-update-log").textContent = "Starte…";
|
||||
card.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
||||
}
|
||||
|
||||
function onJobs(jobs) {
|
||||
if (!activeJob) return;
|
||||
const j = (jobs || []).find(x => x.id === activeJob.id);
|
||||
const card = $("#w-update-card");
|
||||
if (!j || !card) return;
|
||||
card.style.display = "";
|
||||
const logEl = $("#w-update-log");
|
||||
if (logEl) { logEl.textContent = (j.log || []).join("\n"); logEl.scrollTop = logEl.scrollHeight; }
|
||||
const badge = $("#w-update-badge");
|
||||
const done = j.state === "done", failed = j.state === "failed";
|
||||
if (badge) badge.innerHTML = done ? '<span class="badge b-run">✓ fertig</span>'
|
||||
: failed ? '<span class="badge b-err">✗ fehlgeschlagen</span>'
|
||||
: '<span class="badge b-load">läuft…</span>';
|
||||
if (done || failed) {
|
||||
$("#w-update-label").textContent = activeJob.label + (done ? " — erfolgreich abgeschlossen." : " — fehlgeschlagen (siehe Protokoll).");
|
||||
if (!notified.has(j.id)) {
|
||||
notified.add(j.id);
|
||||
toast(done ? "✓ " + activeJob.label + " abgeschlossen." : "✗ " + activeJob.label + " fehlgeschlagen.", failed);
|
||||
if (done) setTimeout(refreshSoon, 800);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function update() {
|
||||
try { const r = await api("/api/update", { method: "POST" }); toast("llama.cpp-Update läuft — siehe Aktivität."); track(r.job_id); }
|
||||
try { const r = await api("/api/update", { method: "POST" }); toast("LLM-Engine-Update läuft."); track(r.job_id); watchJob(r.job_id, "LLM-Engine-Update"); }
|
||||
catch (e) { toast(e.message, true); }
|
||||
}
|
||||
|
||||
@@ -102,7 +146,7 @@ async function osUpdate() {
|
||||
if (!await confirmModal({ title: "OS-Updates installieren?", body: "Führt <code>apt update & upgrade</code> aus. Das kann ein paar Minuten dauern; der Fortschritt erscheint in der Aktivität." })) return;
|
||||
const pwd = await promptModal({ title: "sudo-Passwort", body: "Für die System-Updates wird einmalig dein sudo-Passwort gebraucht.", placeholder: "sudo-Passwort", password: true, confirmLabel: "Installieren" });
|
||||
if (!pwd) return;
|
||||
try { const r = await api("/api/os-update", { method: "POST", body: JSON.stringify({ password: pwd }) }); toast("OS-Update gestartet."); track(r.job_id); }
|
||||
try { const r = await api("/api/os-update", { method: "POST", body: JSON.stringify({ password: pwd }) }); toast("OS-Update gestartet."); track(r.job_id); watchJob(r.job_id, "OS-Update"); }
|
||||
catch (e) { toast(e.message, true); }
|
||||
}
|
||||
|
||||
@@ -114,4 +158,4 @@ async function rebootServer() {
|
||||
catch (e) { toast(e.message, true); }
|
||||
}
|
||||
|
||||
export default { id: "server", mount };
|
||||
export default { id: "server", mount, onJobs };
|
||||
|
||||
Reference in New Issue
Block a user