Merge branch 'worktree-agent-a872d2361a1cdaa60' into wartung/helfer-nutzung-dienste

This commit is contained in:
Hitonabi
2026-09-25 13:31:32 +02:00
16 changed files with 1314 additions and 201 deletions
+6 -76
View File
@@ -6,18 +6,12 @@ zurückgegeben statt zu crashen.
"""
import logging
import os
import subprocess
import httpx
from config import GATEWAY_URL, HERMES_API_URL, LLAMA_SWAP_URL, V1_UPSTREAM, VOICE_SERVICE_URL
from fastapi import APIRouter
from pydantic import BaseModel
from services import backup as backup_svc
from services import maintenance, waechter
from services.agent import agent_status
from services.gateway import gateway_reachable
from services.llamaswap import engine_reachable, list_models
from services import dienste, maintenance
from services.llamaswap import list_models
from services.pricing import compute_savings
from services.system import system_status
from services.token_stats import get_stats
@@ -31,76 +25,12 @@ def status() -> dict:
return system_status()
def _voice_reachable() -> bool:
try:
return httpx.get(f"{VOICE_SERVICE_URL}/health", timeout=2).status_code == 200
except Exception:
return False
def _user_unit_active(unit: str) -> bool:
"""systemd-User-Unit ohne eigenen HTTP-Port (z. B. mc2-steward) — Zustand via is-active.
Auf Windows/Dev schlägt das harmlos fehl (False)."""
if os.name != "posix":
return False
try:
r = subprocess.run(["systemctl", "--user", "is-active", unit],
capture_output=True, text=True, timeout=3)
return r.stdout.strip() == "active"
except Exception:
return False
@router.get("/system/services")
def services() -> dict:
"""Aggregierte Erreichbarkeit aller Stack-Dienste — die EINE Quelle für Cockpit-Kachel,
Schubladen-Liste und Log-Auswahl (Frontend rendert diese Liste, keine UI-Kopie mehr).
`scope`: user|system (Restart-Weg), `unit`: echter systemd-Name (Restart/Logs/Matching)."""
a = agent_status()
gw_url = f"{GATEWAY_URL}/v1"
rows = [
{"name": "Engine (llama-swap)", "unit": "llama-swap", "url": LLAMA_SWAP_URL,
"ok": engine_reachable(), "scope": "system"},
]
# Seit UMBAU v3 P1 ist der LLM-Gateway ein EIGENER Prozess — ohne diese Zeile war er
# in der Dienste-Ampel unsichtbar (Kachel "6/6 grün" bei totem Denkpfad).
if V1_UPSTREAM:
rows.append({"name": "LLM-Gateway (Denkpfad)", "unit": "mc2-gateway", "url": V1_UPSTREAM,
"ok": gateway_reachable(), "scope": "user"})
# MC2 selbst antwortet gerade auf diesen Request — ok=True ist hier ehrlich;
# die Zeile existiert für Restart/Logs, nicht als Erreichbarkeits-Orakel.
rows.append({"name": "Box-Wart (MC2)", "unit": "mission-control-2", "url": gw_url,
"ok": True, "scope": "user"})
else:
rows.append({"name": "Gateway (integriert)", "unit": "mission-control-2", "url": gw_url,
"ok": gateway_reachable(), "scope": "user"})
rows += [
{"name": "Wächter (Steward)", "unit": "mc2-steward", "url": "",
"ok": _user_unit_active("mc2-steward"), "scope": "user"},
{"name": "Hermes-Gateway (Agent & Gedächtnis)", "unit": "hermes-gateway", "url": HERMES_API_URL,
"ok": a["gateway_reachable"], "scope": "user"},
{"name": "Hermes-Dashboard", "unit": "hermes-builtin-ui", "url": a["hermes_ui_url"],
"ok": a["hermes_ui_reachable"], "scope": "user"},
{"name": "Spracherkennung (Desktop-Lucy)", "unit": "voice-service", "url": VOICE_SERVICE_URL,
"ok": _voice_reachable(), "scope": "user"},
# Lucys Stimme (pocket-tts) spricht Telegram und Lucy-Desktop — bis 09/2026 fehlte
# sie hier; die Box-Konsole ist mit dem Box-Wart-Umbau aus MC2 raus.
{"name": "Lucys Stimme", "unit": "lucy-stimme", "url": "",
"ok": _user_unit_active("lucy-stimme"), "scope": "user"},
]
# Bewusst abgeschaltete Dienste (24.09.2026: Spracherkennung bis zur Android-App) sind kein
# Fehler — die Oberfläche zeigt sie als „schläft“ mit Knopf zum Wecken statt rot.
for row in rows:
row["schlaeft"] = (not row["ok"] and row["scope"] == "user"
and waechter.schlaeft(waechter.dienst_zustand(row["unit"])))
return {
"services": rows,
"links": {
"engine_ui": f"{LLAMA_SWAP_URL}/ui",
"gateway": gw_url,
"hermes_ui": a["hermes_ui_url"],
},
}
"""Alle Dienste der Box mit Erreichbarkeit, Zustand und Kennzahlen (Speicher, CPU, Laufzeit,
Neustarts) — die EINE Quelle für die Seite „Dienste und Protokolle“ und die MCP-Werkzeuge.
Logik in services/dienste.py; `scope`: user|system (Restart-Weg), `unit`: echter systemd-Name."""
return dienste.liste()
@router.post("/system/backup")