diff --git a/routers/cookbook.py b/routers/cookbook.py
index bae70b5..3b39600 100644
--- a/routers/cookbook.py
+++ b/routers/cookbook.py
@@ -185,10 +185,8 @@ def _pick_gguf(repo: str, quant: str = "Q4_K_M") -> str | None:
return (pref or nosplit or ggufs)[0]
-@router.get("/upgrades")
-def upgrades():
- """Schlägt für installierte 'alte' Modelle ein aktuelleres vor (UPGRADES-Map)."""
- ram_gb = psutil.virtual_memory().total / (1024 ** 3)
+def compute_upgrades(ram_gb):
+ """Liste relevanter Modell-Upgrades für die installierten Modelle (UPGRADES-Map)."""
installed = (read_config().get("models") or {})
out, seen = [], set()
for up in UPGRADES:
@@ -210,7 +208,12 @@ def upgrades():
"fit": evaluate_fit(up["params_b"], up["quant"], 8192, ram_gb),
"optimal_ctx": max_ctx_for(up["params_b"], up["quant"], ram_gb),
})
- return {"upgrades": out}
+ return out
+
+
+@router.get("/upgrades")
+def upgrades():
+ return {"upgrades": compute_upgrades(psutil.virtual_memory().total / (1024 ** 3))}
@router.post("/install-model")
diff --git a/routers/maintenance.py b/routers/maintenance.py
index 29fa28c..8e4ddee 100644
--- a/routers/maintenance.py
+++ b/routers/maintenance.py
@@ -72,6 +72,25 @@ def reboot(req: PwdReq):
pass
return {"ok": True, "note": "Reboot getriggert."}
+@router.get("/updates")
+def updates():
+ """Ausstehende Updates für die Toolbar: OS-Pakete (apt-Cache) + Modell-Upgrades."""
+ import psutil
+ from routers.cookbook import compute_upgrades
+ os_count = 0
+ try:
+ out = subprocess.run(
+ ["bash", "-c", "apt list --upgradable 2>/dev/null | grep -c upgradable || true"],
+ capture_output=True, text=True, timeout=10)
+ os_count = int((out.stdout or "0").strip() or 0)
+ except Exception: # noqa: BLE001
+ os_count = 0
+ try:
+ models = len(compute_upgrades(psutil.virtual_memory().total / (1024 ** 3)))
+ except Exception: # noqa: BLE001
+ models = 0
+ return {"os": os_count, "models": models}
+
@router.websocket("/logs/{service}")
async def stream_logs(websocket: WebSocket, service: str):
await websocket.accept()
diff --git a/static/css/components.css b/static/css/components.css
index 4cb8189..11a0f5e 100644
--- a/static/css/components.css
+++ b/static/css/components.css
@@ -148,6 +148,10 @@ textarea{resize:vertical;min-height:64px;font-family:var(--sans)}
.info-dot{display:inline-flex;vertical-align:-3px;color:var(--dim);cursor:help;margin-left:5px}
.info-dot svg{width:14px;height:14px}
.info-dot:hover{color:var(--accent)}
+.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)}
+.upd-badge.warn{background:rgba(224,163,46,.14);color:#f0c570;border-color:rgba(224,163,46,.25)}
+.upd-badge:hover{filter:brightness(1.12)}
.mono-sm{font-family:var(--mono);font-size:11.5px;color:var(--mut)}
/* ---- Buttons ---- */
diff --git a/static/index.html b/static/index.html
index c6e8125..7fe0128 100644
--- a/static/index.html
+++ b/static/index.html
@@ -33,6 +33,7 @@