v6: Toolbar zeigt AI-Engine-Update-Status + immer-sichtbare Badges
- /api/updates liefert zusaetzlich "engine" (llama.cpp-ROCm: neueste GitHub-Release vs. /opt/llamacpp-mtime, 1h gecacht) - Toolbar-Badges fuer OS/Engine/Modelle jetzt auch im "aktuell"-Zustand sichtbar (gruener .ok-Style) statt nur bei ausstehenden Updates - Guide: neuer Tutorial-Eintrag "Was passiert, wenn der Kontext volllaeuft?" Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+27
-2
@@ -72,9 +72,34 @@ def reboot(req: PwdReq):
|
|||||||
pass
|
pass
|
||||||
return {"ok": True, "note": "Reboot getriggert."}
|
return {"ok": True, "note": "Reboot getriggert."}
|
||||||
|
|
||||||
|
_engine_cache = {"ts": 0.0, "avail": False}
|
||||||
|
|
||||||
|
|
||||||
|
def _engine_update_available():
|
||||||
|
"""Heuristik: ist die neueste llama.cpp-ROCm-Release neuer als die installierte? (1h gecacht)"""
|
||||||
|
import time
|
||||||
|
now = time.time()
|
||||||
|
if now - _engine_cache["ts"] < 3600:
|
||||||
|
return _engine_cache["avail"]
|
||||||
|
avail = False
|
||||||
|
try:
|
||||||
|
import os as _os
|
||||||
|
import httpx
|
||||||
|
from datetime import datetime
|
||||||
|
rel = httpx.get("https://api.github.com/repos/lemonade-sdk/llamacpp-rocm/releases/latest",
|
||||||
|
timeout=6, headers={"User-Agent": "MissionControl"}).json()
|
||||||
|
pub = datetime.fromisoformat(rel["published_at"].replace("Z", "+00:00")).timestamp()
|
||||||
|
inst = _os.path.getmtime("/opt/llamacpp")
|
||||||
|
avail = pub > inst + 86400 # neuer als Installation (1 Tag Puffer)
|
||||||
|
except Exception: # noqa: BLE001
|
||||||
|
avail = False
|
||||||
|
_engine_cache.update(ts=now, avail=avail)
|
||||||
|
return avail
|
||||||
|
|
||||||
|
|
||||||
@router.get("/updates")
|
@router.get("/updates")
|
||||||
def updates():
|
def updates():
|
||||||
"""Ausstehende Updates für die Toolbar: OS-Pakete (apt-Cache) + Modell-Upgrades."""
|
"""Ausstehende Updates für die Toolbar: OS-Pakete (apt), AI-Engine (llama.cpp), Modell-Upgrades."""
|
||||||
import psutil
|
import psutil
|
||||||
from routers.cookbook import compute_upgrades
|
from routers.cookbook import compute_upgrades
|
||||||
os_count = 0
|
os_count = 0
|
||||||
@@ -89,7 +114,7 @@ def updates():
|
|||||||
models = len(compute_upgrades(psutil.virtual_memory().total / (1024 ** 3)))
|
models = len(compute_upgrades(psutil.virtual_memory().total / (1024 ** 3)))
|
||||||
except Exception: # noqa: BLE001
|
except Exception: # noqa: BLE001
|
||||||
models = 0
|
models = 0
|
||||||
return {"os": os_count, "models": models}
|
return {"os": os_count, "models": models, "engine": 1 if _engine_update_available() else 0}
|
||||||
|
|
||||||
@router.websocket("/logs/{service}")
|
@router.websocket("/logs/{service}")
|
||||||
async def stream_logs(websocket: WebSocket, service: str):
|
async def stream_logs(websocket: WebSocket, service: str):
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ textarea{resize:vertical;min-height:64px;font-family:var(--sans)}
|
|||||||
.upd-badge{font-size:11.5px;padding:4px 10px;border-radius:999px;cursor:pointer;white-space:nowrap;
|
.upd-badge{font-size:11.5px;padding:4px 10px;border-radius:999px;cursor:pointer;white-space:nowrap;
|
||||||
background:rgba(68,147,224,.14);color:#86b9ff;border:1px solid rgba(68,147,224,.25)}
|
background:rgba(68,147,224,.14);color:#86b9ff;border:1px solid rgba(68,147,224,.25)}
|
||||||
.upd-badge.warn{background:rgba(224,163,46,.14);color:#f0c570;border-color:rgba(224,163,46,.25)}
|
.upd-badge.warn{background:rgba(224,163,46,.14);color:#f0c570;border-color:rgba(224,163,46,.25)}
|
||||||
|
.upd-badge.ok{background:rgba(63,185,80,.12);color:#7ee29a;border-color:rgba(63,185,80,.22)}
|
||||||
.upd-badge:hover{filter:brightness(1.12)}
|
.upd-badge:hover{filter:brightness(1.12)}
|
||||||
.mono-sm{font-family:var(--mono);font-size:11.5px;color:var(--mut)}
|
.mono-sm{font-family:var(--mono);font-size:11.5px;color:var(--mut)}
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -87,8 +87,9 @@ async function pollUpdates() {
|
|||||||
const u = await api("/api/updates");
|
const u = await api("/api/updates");
|
||||||
const el = $("#update-badges"); if (!el) return;
|
const el = $("#update-badges"); if (!el) return;
|
||||||
el.innerHTML = "";
|
el.innerHTML = "";
|
||||||
if (u.os > 0) el.appendChild(badge(`${u.os} OS-Updates`, "warn", "server"));
|
el.appendChild(badge(u.os > 0 ? `OS: ${u.os} Updates` : "OS: aktuell", u.os > 0 ? "warn" : "ok", "server"));
|
||||||
if (u.models > 0) el.appendChild(badge(`${u.models} Modell-Upgrade${u.models > 1 ? "s" : ""}`, "", "news"));
|
el.appendChild(badge(u.engine > 0 ? "Engine: Update" : "Engine: aktuell", u.engine > 0 ? "warn" : "ok", "server"));
|
||||||
|
el.appendChild(badge(u.models > 0 ? `Modelle: ${u.models}` : "Modelle: aktuell", u.models > 0 ? "warn" : "ok", "news"));
|
||||||
} catch { /* still */ }
|
} catch { /* still */ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,17 @@ const TUTORIALS = [
|
|||||||
<p>Du musst nur selten eingreifen: wird ein Gespräch sehr lang, fang einen neuen an. <b>Wichtig:</b>
|
<p>Du musst nur selten eingreifen: wird ein Gespräch sehr lang, fang einen neuen an. <b>Wichtig:</b>
|
||||||
„Grafikspeicher leeren" (Tab Server) ist etwas anderes — das wirft das <i>Modell</i> aus dem Speicher,
|
„Grafikspeicher leeren" (Tab Server) ist etwas anderes — das wirft das <i>Modell</i> aus dem Speicher,
|
||||||
nicht den Gesprächsverlauf.</p>`],
|
nicht den Gesprächsverlauf.</p>`],
|
||||||
|
["Was passiert, wenn der Kontext volläuft?", `
|
||||||
|
<p>Ist das Kontextfenster voll, passiert je nach Tool eins von dreien: das Modell <b>vergisst den
|
||||||
|
Anfang</b> (älteste Nachrichten fallen raus), das Tool <b>kürzt automatisch</b>, oder du bekommst
|
||||||
|
einen Fehler wie „context length exceeded".</p>
|
||||||
|
<p><b>So gehst du vor:</b></p>
|
||||||
|
<ol class="tut-steps">
|
||||||
|
<li><b>Neuen Chat starten</b> — der einfachste Reset, Kontext ist wieder leer.</li>
|
||||||
|
<li><b>Zusammenfassen lassen:</b> „Fasse unseren Stand kurz zusammen", dann im neuen Chat einfügen.</li>
|
||||||
|
<li><b>Kontext vergrößern:</b> Tab <b>Modelle</b> → <b>Konfigurieren</b> → wir zeigen das Optimum
|
||||||
|
für deine Hardware (mehr Kontext = mehr Speicherbedarf).</li>
|
||||||
|
</ol>`],
|
||||||
["Brauche ich überhaupt einen Agenten?", `
|
["Brauche ich überhaupt einen Agenten?", `
|
||||||
<p>Kommt drauf an, was du willst:</p>
|
<p>Kommt drauf an, was du willst:</p>
|
||||||
<ul class="tut-steps" style="list-style:disc">
|
<ul class="tut-steps" style="list-style:disc">
|
||||||
|
|||||||
Reference in New Issue
Block a user