This repository has been archived on 2026-07-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
mission-control/CLAUDE.md
T
Hitonabi af0e63c9d6 docs(v9): Phase 5 (Dashboard-Adoption) + Phasen 6-8 in ROADMAP
Kurswechsel dokumentiert: eingebettetes Hermes-Web-Dashboard statt Eigenbau-Chat.
CLAUDE.md: hermes_ui-Router, HERMES_DASHBOARD_URL, Dashboard-Gotcha, Projektstatus.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 16:51:52 +02:00

10 KiB
Raw Blame History

Mission Control

Web-Dashboard zur Verwaltung eines lokalen LLM-Stacks (llama-swap) auf dem Bosgame M5. FastAPI-Backend + Svelte 5-Frontend (Vite-Build). Leitprinzip: KISS — SoC ohne Overhead.

Architektur

Backend (Top-Level-Helfer + ein Router je Bereich):

  • app.py — dünner Einstieg: FastAPI, hängt die Router ein, liefert das statische UI aus, Exception-Handler + Cache-Control: no-cache-Middleware.
  • config.py — alle Env-Vars + die gemeinsame ruamel.yaml-Instanz. Auch SOURCE_DIR/PROD_DIR fürs Self-Update.
  • auth.py — optionale Token-Auth: Header X-MC-Token oder Query ?token= (Query ist Pflicht für WebSockets).
  • jobengine.py — In-Memory-Job-System (Threads + Subprocess) mit Live-Log. Secrets gehen über stdin (kein Leak in Log/ps).
  • llamaswap.py — spricht llama-swap an und liest/schreibt dessen config.yaml per ruamel.yaml.
  • hw_math.py — Odysseus-Fit-Mathe: VRAM/RAM-Bedarf, tps-Schätzung, max_ctx_for, extract_params_b.
  • recipes.py — kuratierte Use-Case-Stacks fürs Cookbook 2.0.
  • mcp_memory.py — stdio-MCP-Server: Gedächtnis-Tools für Cline/OpenCode/Claude Code.
  • routers/*.py — ein Router je Bereich:
    • models.py — status/download/register/update_model/unload/chat
    • jobs.py — Jobs-Liste
    • maintenance.py — update/self-update/os-update/service-restart/reboot/logs-WebSocket
    • system.py — status + stream-WebSocket (Live-Metriken psutil/sysfs)
    • cookbook.py — analyze/evaluate/recipes/install-recipe/upgrades
    • integration.py — test (Engine-Verbindungstest)
    • news.py — RSS-Aggregation via stdlib
    • memory.py — Gedächtnis-CRUD (SQLite, WAL-Mode), 5 Kategorien
    • hermes.py — Chat-WS proxyt zum Hermes-Agent-Server (:8642) + transcribe(Whisper)/tts(Piper)/status/pubkey + Cockpit-Reads agent/cron/skills (Phase 4)
    • hermes_ui.pyReverse-Proxy auf das eingebettete Hermes-Web-Dashboard (/hermes-ui/, HTTP + WS-Bridge pty/ws/pub/events, X-Forwarded-Prefix). Der Chat lebt jetzt hier (iframe), nicht mehr im Eigenbau.
  • hermes_control.py — read-only Control-Plane: liest Agent-Status (gateway_state.json + Cron-Heartbeat), Cron-Jobs & Skills via hermes-CLI (COLUMNS=400, Rich-Tabelle geparst). TTL-Cache.

Frontend (frontend/src/, Svelte 5 + Vite, Build → static/dist/):

  • index.html — Gerüst: Sidebar-Nav (10 Tabs), Topbar, Alert-Banner, View-Container je Bereich.
  • frontend/src/main.ts — bootet alle Svelte-Panels, Topbar/Alert, WebSocket Live-Metriken, Polling.
  • frontend/src/panels/ — je ein Panel: Overview, Models, Jobs(Aktivität), Server, Cookbook, Connect(Verbinden), News, Guides, Memory(Gedächtnis), Hermes.
  • frontend/src/stores/ — Svelte 5 Runes: status.svelte.ts, jobs.svelte.ts, system.svelte.ts.
  • Design-System (v3): EINE Akzentfarbe Teal #2dd4bf. Grün/Gelb/Rot nur für Status. Tokens in css/base.css.

Der Stack drumherum

  • Bosgame M5: AMD Strix Halo (gfx1151), Ubuntu 26.04, Kernel 7.0, ~124 GB GTT. LAN-IP 192.168.178.151.
  • Inferenz: llama.cpp-ROCm-Binaries → llama-swap auf *:8080 (LAN-offen, -watch-config).
  • 3 Modelle / 5 Rollen: coder (Qwen3-30B-A3B), scout (Qwen3-8B), vision (Qwen3-VL).
  • Mission Control: Produktiv unter /opt/mission-control, Source unter ~/mission-control.
  • Gedächtnis: SQLite unter /srv/models/mission-control-memory.db (5 Kategorien: user/instruction/stable/versioned/ephemeral).
  • Hermes Agent: aktuell Eigenbau als Teil von Mission Control; ab v9 das Nous Hermes-Agent-Framework als eigener Dienst (hermes-agent.service, OpenAI-API auf :8642, base_url → llama-swap, MCP-Client bindet mcp_memory.py ein). Voice (Whisper STT + Piper TTS) bleibt in Mission Control und wrappt :8642.

Entwickeln & Deployen

Wo entwickelt wird: Windows-PC (F:\Coding Stuff\mission-control), Ziel: Linux-Bosgame. Lokal nur Smoke-Test (rendert/bootet?), echter Funktionstest auf dem Bosgame.

Lokaler Smoke-Test (Windows):

python -m venv .venv && .venv/Scripts/python -m pip install -r requirements.txt
.venv/Scripts/python -m uvicorn app:app --port 9001

Bosgame-Zugang:

ssh -i ~/.ssh/id_ed25519_hermes -o IdentitiesOnly=yes hitonabi@192.168.178.151

User: hitonabi. sudo NOPASSWD-Whitelist für systemctl restart mission-control|llama-swap und journalctl.

Frontend-Build:

cd frontend && npm run build   # vor jedem git push

Output: static/dist/main.js + static/dist/main.css — wird committet (kein Build-Schritt auf dem Server).

Deploy-Kette:

npm run build → git push (Gitea :3000) → Bosgame: git pull → rsync → systemctl restart

Oder über den Self-Update-Button in Mission Control (empfohlen).

Self-Update-Button (POST /api/self-update): git pull → rsync → restart — alles in einem Klick.

Konfiguration (Env-Vars)

Variable Default Zweck
MC_LLAMA_SWAP_URL http://127.0.0.1:8080 llama-swap URL
MC_CONFIG_PATH /etc/llama-swap/config.yaml llama-swap Config
MC_MODELS_DIR /srv/models GGUF-Ablageort
MC_TOKEN leer Auth-Token (optional, LAN-only)
MC_UPDATE_CMD leer Engine-Update-Befehl
MC_DEFAULT_TTL 300 Sekunden bis Auto-Unload
MC_SOURCE_DIR ~/mission-control Self-Update Quelle
MC_MEMORY_DB {MODELS_DIR}/mission-control-memory.db SQLite Gedächtnis
HERMES_API_URL http://127.0.0.1:8642/v1 Hermes-Agent-Server (OpenAI-API)
HERMES_API_KEY aus ~/.hermes/.env API-Key des Hermes-Servers (sonst Env)
HERMES_HOME ~/.hermes Hermes-Agent State-Dir (Cockpit-Reads)
HERMES_BIN ~/.local/bin/hermes Hermes-CLI (Cron/Skills-Reads)
HERMES_DASHBOARD_URL http://127.0.0.1:9119 Hermes-Web-Dashboard (eingebettet via /hermes-ui/)
HERMES_WINDOWS_HOST leer Windows-PC IP für SSH
HERMES_WINDOWS_USER TobisPC Windows SSH-Username
HERMES_SSH_KEY ~/.ssh/id_ed25519_hermes_agent SSH-Key für Hermes
PIPER_BIN /opt/mission-control/piper/piper Piper TTS Binary
PIPER_VOICE .../de_DE-kerstin-low.onnx Piper Stimm-Modell
WHISPER_MODEL medium Whisper Modell-Größe

Konventionen

  • Neuer Bereich: routers/<bereich>.py + frontend/src/panels/<Bereich>Panel.svelte + Nav/View in index.html + Import in main.ts. Danach npm run build.
  • Backend SoC: gemeinsame Logik in config/auth/jobengine/llamaswap/hw_math. Alles unter /api/*.
  • Sicherheit: Shell-Befehle → nur LAN. Secrets via stdin. Token optional.
  • SQLite: WAL-Mode aktiv, check_same_thread=False — ausreichend für Single-User.
  • asyncio.get_running_loop() statt get_event_loop() (Python 3.10+ kompatibel).
  • Memory-Kategorien: user | instruction | stable | versioned | ephemeral — Enum in routers/memory.py.

Gotchas

  • ${PORT} in llama-swap-Config → str.replace statt .format (KeyError sonst).
  • -watch-config bei llama-swap nötig für Auto-Einpflegen.
  • HF_HUB_DISABLE_XET=1 bei HuggingFace-Downloads (Hänger bei ~6 MB).
  • Vision-Modelle: brauchen --mmproj <projektor> und --jinja.
  • Gitea-Push kann transient mit „Failed to authenticate" fehlschlagen → einfach nochmal.
  • Piper TTS: Binary + Stimm-Modell müssen separat installiert werden (nicht via pip).
  • Whisper: lädt beim ersten Aufruf ~1.4 GB Modell herunter (einmalig, dann gecacht).
  • Hermes SSH-Key: muss auf dem Bosgame generiert werden (~/.ssh/id_ed25519_hermes_agent).
  • system_status-Keys: /api/system/status liefert verschachtelt (cpu.percent, ram.used in Bytes) — nicht flach. Konsumenten müssen entsprechend lesen.
  • Hermes-Server-Key: routers/hermes.py proxyt zu :8642 und liest den Key bei Bedarf aus ~/.hermes/.env (API_SERVER_KEY) — MC muss als User hitonabi laufen, sonst kein Lesezugriff.
  • Hermes-Dashboard (Phase 5): braucht Extras uv pip install --python ~/.hermes/hermes-agent/venv/bin/python -e ".[web,pty]" und einen einmaligen UI-Build (erster hermes dashboard-Start ohne --skip-build; Output → hermes_cli/web_dist). Dienst: ~/.config/systemd/user/hermes-dashboard.service (an 127.0.0.1:9119 gebunden, --skip-build). Wird unter /hermes-ui/ per X-Forwarded-Prefix geproxyt — nie ohne diesen Header proxen, sonst absolute Asset-Pfade kaputt. /hermes-ui/* ist bewusst ohne MC-Token (LAN-only; Dashboard self-auth auf Loopback).
  • OpenCode Config: Datei heißt opencode.jsonc (nicht .json), Key ist "providers" (Plural).
  • ConnectPanel hinter NPM-Proxy: location.hostname zeigt Proxy-Domain → LAN-IP Override im Verbinden-Tab setzen (localStorage).

Projektstatus

v7 (Memory Layer): SQLite-Gedächtnis mit 5 Kategorien + MCP-Server für alle Tools live. v8 (Hermes Agent): Chat-Agent mit Voice (Whisper STT + Piper TTS), Tool Calling, WebSocket-Streaming live. v8.1 (Bug-Fix): system_status-Keys, Model-Routing, asyncio, sudo-PW für Engine-Update, Chat-History in sessionStorage. v8.2 (UX): Guide-Tabs + Begriffe oben, Mobile Bottom-Nav (≤520px), Download-Links, ConnectPanel-Fixes. v8.3 (Memory Import): Import aus Cloud-KIs (Claude/Gemini/ChatGPT) — zeilenweiser Batch-POST. v9 (Hermes-Agent-Adoption, Entscheidung 2026-06-23): Eigenbau-Agent → Nous Hermes-Agent-Framework (MIT). MC wird Control-Plane. Eigenes Memory bleibt via MCP erhalten. Phasen 03 live (harter Cutover: hermes_agent.py entfernt) + Phase 4: Agent-Cockpit (Status/Cron/Skills) via hermes_control.py + Phase 5 (Kurswechsel): Eigenbau-Chat ersetzt durch das eingebettete Hermes-Web-Dashboard (hermes-dashboard-Dienst :9119, MC-Reverse-Proxy /hermes-ui/, iframe). Offen: Phase 6 (volle lokale Rechte), Phase 7 (Agent-Modell Hermes 4 14B), Phase 8 (insights/Memory im Cockpit), Self-Update für hermes-gateway+hermes-dashboard. Siehe ROADMAP v9.

Offene v8-Einrichtungsschritte (kein Code, nur Setup):

  • Piper Binary + Kerstin-Stimme installieren (Befehle im Hermes-Tab → ⚙ Setup)
  • Windows OpenSSH Server aktivieren + SSH-Key einrichten

Nordstern: Den Bosgame nie wieder via SSH/Putty anfassen — 100 % Automatisierung / Klicki-Bunti.