Feat: System-Wartung-Rework + Hermes-Update-Button
Wartungs-Tab im SystemDrawer neu strukturiert: - UPDATES: eine einheitliche Liste (OS, Engine, Hermes-Agent, Modell-Upgrades) mit Status + Aktion-Button, der nur aktiv ist wenn ein Update ansteht (statt Klick-Karten, die sofort updaten). Konsistent mit der Dashboard-UpdatesCard. - DIENSTE: neue Sektion, alle systemd-Units mit Status-Punkt (aus /api/system/services, jetzt inkl. mem0-service) + Restart + Logs-Sprung. - BACKUP: kompakt (letztes Backup + Snapshot-Button + Restore-Hinweis). - GEFAHRENZONE: Reboot abgetrennt. Jobs nur wenn vorhanden. Hermes-Update-Button: POST /api/maintenance/hermes-update -> Job (Backup -> `hermes update --yes` (git pull + deps) -> hermes-gateway restart). Backend: hermes_update_job + USER_SERVICES um mem0-service/hermes-terminal ergaenzt (Restart ging vorher nicht), mem0 in services-API. Live verifiziert: Button hat Hermes d470ed0 -> 3b44a3c aktualisiert, Integration intakt (memory.provider, Plugin laedt), Pre-Update-Backup angelegt, Drawer rendert fehlerfrei. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -45,6 +45,11 @@ def engine_update(body: SudoReq) -> dict:
|
||||
return res
|
||||
|
||||
|
||||
@router.post("/maintenance/hermes-update")
|
||||
def hermes_update() -> dict:
|
||||
return maintenance.hermes_update_job()
|
||||
|
||||
|
||||
@router.post("/maintenance/reboot")
|
||||
def reboot(body: SudoReq) -> dict:
|
||||
return maintenance.reboot(body.sudo_password)
|
||||
|
||||
@@ -12,7 +12,9 @@ import subprocess
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
from config import GATEWAY_URL, HERMES_API_URL, LLAMA_SWAP_URL
|
||||
import httpx
|
||||
|
||||
from config import GATEWAY_URL, HERMES_API_URL, LLAMA_SWAP_URL, MEM0_SERVICE_URL
|
||||
from services import backup as backup_svc
|
||||
from services.agent import agent_status
|
||||
from services.gateway import gateway_reachable
|
||||
@@ -36,6 +38,13 @@ def status() -> dict:
|
||||
return system_status()
|
||||
|
||||
|
||||
def _mem0_reachable() -> bool:
|
||||
try:
|
||||
return httpx.get(f"{MEM0_SERVICE_URL}/health", timeout=2).status_code == 200
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
@router.get("/system/services")
|
||||
def services() -> dict:
|
||||
"""Aggregierte Erreichbarkeit aller Stack-Dienste (für die Health-Anzeige)."""
|
||||
@@ -47,6 +56,7 @@ def services() -> dict:
|
||||
{"name": "Gateway (integriert)", "url": gw_url, "ok": gateway_reachable()},
|
||||
{"name": "Hermes-Gateway", "url": HERMES_API_URL, "ok": a["gateway_reachable"]},
|
||||
{"name": "Hermes-Terminal", "url": a["terminal_url"], "ok": a["terminal_reachable"]},
|
||||
{"name": "Mem0 (Gedächtnis)", "url": MEM0_SERVICE_URL, "ok": _mem0_reachable()},
|
||||
],
|
||||
"links": {
|
||||
"engine_ui": f"{LLAMA_SWAP_URL}/ui",
|
||||
|
||||
@@ -19,7 +19,7 @@ from services import catalog, discover, jobengine, llamaswap, system
|
||||
|
||||
# System-Dienste (root, via sudo -n NOPASSWD) vs. User-Dienste (systemctl --user).
|
||||
SYSTEM_SERVICES = {"llama-swap"}
|
||||
USER_SERVICES = {"mission-control-2", "hermes-gateway", "hermes-dashboard", "hermes-webui"}
|
||||
USER_SERVICES = {"mission-control-2", "hermes-gateway", "hermes-terminal", "mem0-service"}
|
||||
|
||||
# Engine-Update: lädt den neuesten Vulkan-Build (deploy/update-engine.sh, läuft als root).
|
||||
_REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
|
||||
@@ -346,6 +346,25 @@ def engine_update_job(sudo_password: str | None = None) -> dict | None:
|
||||
return {"ok": True, "job_id": job_id}
|
||||
|
||||
|
||||
def hermes_update_job() -> dict:
|
||||
"""Hermes-Agent aktualisieren wie die CLI (`hermes update` = git pull + Deps), danach
|
||||
den Gateway neu starten. Davor ein Sicherheits-Backup (unser deploy/backup.sh). Kein sudo
|
||||
(alles im User-Space). Läuft als Hintergrund-Job (kann ~1 Min dauern)."""
|
||||
git = system.find_hermes_agent_git()
|
||||
path = (git or {}).get("path") or os.path.expanduser("~/.hermes/hermes-agent")
|
||||
py = os.path.join(path, "venv", "bin", "python")
|
||||
backup = os.path.join(_REPO_ROOT, "deploy", "backup.sh")
|
||||
cmd = (f"bash {backup} || true; "
|
||||
f"cd {path} && {py} -m hermes_cli.main update --yes "
|
||||
f"&& systemctl --user restart hermes-gateway")
|
||||
|
||||
def on_done():
|
||||
_comp_cache.update(ts=0.0, data=[]) # Update-Status neu berechnen lassen
|
||||
|
||||
job_id = jobengine.start_job(["bash", "-c", cmd], "Hermes-Agent-Update", on_done=on_done)
|
||||
return {"ok": True, "job_id": job_id}
|
||||
|
||||
|
||||
def reboot(sudo_password: str | None = None) -> dict:
|
||||
if err := check_sudo_needs_password(sudo_password):
|
||||
return err
|
||||
|
||||
Reference in New Issue
Block a user