umbau(boxwart): Backend auf Box-Wart umgestellt – Waechter, Modell-Nutzung, Zeitplan

MC2 wird Updater, Waechter und Modell-Radar (Konzept „MC2 als Box-Wart“, 23.09.2026).

- Neuer Waechter (services/waechter.py) loest sentry.py ab: Dienste, Timer-Laeufe,
  Hermes-Jobs samt Werkzeugfehlern, Kern-HTTP-Proben, Platte. Abgestuerzte Dienste
  startet er selbst neu (max. 2/h), rote Hinweise gehen an Telegram und Lucy.
  Laeuft im mc2-steward; waehrend eines Updates haelt er still.
- Neue Schnittstellen (routers/boxwart.py): /api/start, /api/hinweise (+ Aktionen),
  /api/modelle/nutzung, /api/zeitplan.
- Modell-Nutzung aus dem llama-swap-Journal (wer fragt wie oft, 24 h je Stunde).
- Entfernt: Ideen, Wissen, Chronik, Skills, Verbinden, Konsolen-Proxy, /api/events;
  Lucys Werkzeug idee_notieren; box_status nennt jetzt die offenen Hinweise.
- Behoben: projekte-sync ueberspringt leere Gitea-Repos (lief seit 07.09. stuendlich rot);
  Motor-Version kam aus dem verwaisten /opt/llamacpp statt /opt/llamacpp-vulkan.
- Erste Backend-Tests (8) fuer Waechter und Modell-Nutzung.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-09-23 21:16:18 +02:00
co-authored by Claude Opus 5.5
parent 3669a6e7dc
commit 12dadfe6ef
25 changed files with 1131 additions and 2179 deletions
+6 -24
View File
@@ -1,14 +1,10 @@
"""Ereignisstrom — ein Kanal sagt der Zentrale, WANN neu laden lohnt, und schickt Metriken.
Zwei Endpunkte, ein Sammler:
GET /api/stream (v3-Umbau P4, 28.08.2026) — der aktuelle Kanal. Zwei Ereignisarten:
GET /api/stream (v3-Umbau P4, 28.08.2026) — zwei Ereignisarten:
· `invalidate` Nur bei Änderung, mit den betroffenen React-Query-Schlüsseln.
· `metrik` Jede Sekunde ein Messpunkt (CPU/RAM/GPU/Temp/Token-Zähler).
GET /api/events — der alte Kanal, nur `invalidate`. Bleibt EINE Fassung lang stehen,
weil ein Browser-Tab nach einem Deploy noch das vorige Bündel halten kann und dieses
nur `/api/events` kennt. Danach entfernen.
Der alte Kanal /api/events ist mit dem Box-Wart-Umbau (09/2026) entfallen.
WARUM METRIKEN JETZT MITKOMMEN: Bis P4 pollte das Frontend `/api/system/status` und
`/api/system/token-stats` im 3-Sekunden-Takt — zwei Dauer-Anfragen, unabhängig davon, ob
@@ -56,15 +52,9 @@ def _fingerprints() -> dict[str, object]:
"""Billige Änderungs-Signale je Quelle → React-Query-Key. Fehler einer Quelle
dürfen den Strom nie reißen (dann bleibt ihr Abdruck einfach stehen)."""
fp: dict[str, object] = {}
try: # Briefkasten trägt Chronik UND Kontext-Limit-Warnungen — in-process, spottbillig
from services import announce
fp["chronik"] = announce.list_after(None)["latest"]
except Exception:
pass
try: # Queue: (id,status)-Paare; list_queue cached selbst ~15 s, der Tick kostet nichts
from services import ideen
d = ideen.list_queue()
fp["ideen"] = json.dumps([(i.get("id"), i.get("status")) for i in d.get("items") or []])
try: # Wächter-Stand (mc2-steward schreibt ihn jede Minute): Hinweise → Startseite neu laden
from services import waechter
fp["start"] = _mtime(waechter.STORE_PATH)
except Exception:
pass
try: # Geladene Modelle (Running-Set): Laden/Entladen soll die Modelle-Ansicht anstoßen
@@ -133,14 +123,6 @@ _KOPF = {"Cache-Control": "no-cache", "X-Accel-Buffering": "no"}
@router.get("/stream")
async def stream(request: Request) -> StreamingResponse:
"""Der aktuelle Kanal: Anstöße UND Messpunkte."""
"""Anstöße UND Messpunkte."""
return StreamingResponse(_strom(request, mit_metrik=True),
media_type="text/event-stream", headers=_KOPF)
@router.get("/events")
async def events(request: Request) -> StreamingResponse:
"""Alt-Kanal ohne Messpunkte. Nur für Browser-Tabs, die noch ein Bündel von vor
dem 28.08.2026 halten. Mit der übernächsten Fassung entfernen."""
return StreamingResponse(_strom(request, mit_metrik=False),
media_type="text/event-stream", headers=_KOPF)