fix(stack): Mem0 restlos ausgebaut + vier stille Defekte behoben

Systemaudit vom 27.08.2026. Alle Befunde gemessen, nicht vermutet.

VIER STILLE DEFEKTE

1. mc2-steward startete seit Wochen nicht (live: 207.609 Neustarts).
   steward.py importierte services.memory, das beim Mem0-Ausbau geloescht
   wurde -> ImportError bei jedem Start. Re-Warm- und Health-Waechter
   waren damit tot.

2. Jedes Hermes-Update wurde automatisch zurueckgerollt.
   hermes-postcheck.sh prueft vier Dinge, die es seit dem 07.08. nicht mehr
   gibt (Sidecar :8765, /api/memory, memory.provider, mc2-memory-Plugin).
   Die Checks konnten nicht gruen werden -> autoupdate.sh wertete jedes
   Update als rot und rollte es zurueck. Checks ersatzlos entfernt; der
   Tool-Smoke laeuft ohnehin durch den echten Agenten.

3. 7 von 12 Skills waren per Knopfdruck nicht startbar.
   deploy.sh kopiert Skills mit tr '-' '_' nach ~/.hermes/skills/,
   routers/skills.py gab Hermes aber den Ordnernamen MIT Bindestrich.
   Der Knopf meldete Erfolg, ausgefuehrt wurde nichts. Neu: _hermes_name().

4. deploy.sh warf bei jedem Deploy die Live-Modellkonfiguration weg.
   MC2 schreibt /etc/llama-swap/config.yaml selbst; die Repo-Datei ist nur
   ein Abzug (ihm fehlt u.a. kritiker/Devstral). Jetzt: erst sichern, Diff
   zeigen, dann kopieren. MC_DEPLOY_SKIP_SWAP_CONFIG=1 ueberspringt.

MEM0-AUSBAU VOLLENDET (Kriterium 3: 17 -> 0 Dateien)
- mem0_service/, mcp/mcp_memory.py und hermes/plugins/mc2-memory entfernt;
  das Plugin schickte bei JEDEM Turn zwei 404-Requests an tote Routen.
- MEMORY_DB/MEM0_SERVICE_URL, _mem0_reachable(), MC_MEMORY_DB und
  MC_MEM_DEDUPE_ENABLED aus Config/Router/Unit entfernt.
- mem0_ms war strukturell tot (park("retrieve") wird nirgends mehr
  aufgerufen) -> aus Backend, API-Typ und Latenzkarte entfernt.
- Verbinden-Tab: tote Gedaechtnis-MCP-Leitung raus, Status-Kachel bleibt.
- AGENTS.md beschrieb Mem0 noch als aktiv - korrigiert.

GATEWAY-ROBUSTHEIT
- _proxy gab bei ungueltigen Payloads HTTP 500 (gemessen 5/5: Rohtext,
  leerer Body, JSON-Liste, JSON-String, null) -> jetzt 5/5 HTTP 400.
- Bild-Weiche ohne Deckel: 10 Bilder x 2 Versuche x 240 s hielten den
  Client bis zu 80 min. Neu: MC_CODER_IMAGE_MAX (4), Rueckfall auf die
  Vision-Umleitung.
- /v1/models: nicht-JSON von der Engine gab 500 -> jetzt 502.

UNITS UND DEPLOY
- mc2-steward.service, dessen warmset-Drop-in und voice-service.service
  fehlten im Repo, obwohl maintenance.py und stack-postcheck.sh sie
  voraussetzen. 1:1 von der laufenden Box uebernommen.
- deploy.sh startete mc2-steward nie neu; restore.sh liess mc2-gateway und
  mc2-steward mit alter Config weiterlaufen. Beide ergaenzt.

FRONTEND
- useEigenleben rief /api/eigenleben - existiert im Backend nicht und wurde
  nirgends genutzt. Samt Typen entfernt.
- Anleitung beschrieb einen Gedaechtnis-Tab, den es nicht gibt.
- Abgeglichen: alle uebrigen 63 Frontend-Aufrufe treffen echte Routen, alle
  5 SSE-Invalidation-Keys sind gemappt, keine ungefangenen Promises.

Gates: compileall gruen - ruff "All checks passed" - tsc gruen - vite build
gruen (dist aktualisiert) - Importe app/steward/gateway_app gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-08-27 14:58:42 +02:00
co-authored by Claude Opus 5
parent 34a9862591
commit 84dc34c0a3
65 changed files with 394 additions and 1440 deletions
+10 -62
View File
@@ -1,6 +1,6 @@
import { useState } from "react"
import {
Check, Copy, Cpu, Brain, Globe, FolderOpen, Laptop, ArrowRight,
Check, Copy, Cpu, Brain, Globe, Laptop, ArrowRight,
Info, CircleCheck, CircleX, Loader2, ChevronDown, ChevronRight,
} from "lucide-react"
import { useConnect, useConnectHealth } from "@/lib/queries"
@@ -82,14 +82,12 @@ function defaultHost(): string {
export function ConnectView() {
const [host, setHost] = useState(localStorage.getItem("mc_host") || defaultHost())
const [mcpPath, setMcpPath] = useState(localStorage.getItem("mc_mcp_path") || "")
// Legacy-Tools (roher /v1-Zugang) leben im Ausklapper — Hermes Desktop ist der Hauptweg.
const [active, setActive] = useState("kilo")
const [sonstigeOffen, setSonstigeOffen] = useState(false)
const [copied, setCopied] = useState<"desktop" | "model" | "memory" | null>(null)
const [copied, setCopied] = useState<"desktop" | "model" | null>(null)
const params = new URLSearchParams({ host })
if (mcpPath) params.set("mcp_path", mcpPath)
const { data, error: dataErr } = useConnect(params.toString())
const { data: health, isLoading: healthLoading } = useConnectHealth()
const error = dataErr ? String(dataErr) : ""
@@ -99,15 +97,10 @@ export function ConnectView() {
if (v) localStorage.setItem("mc_host", v)
}
function saveMcpPath(v: string) {
setMcpPath(v)
localStorage.setItem("mc_mcp_path", v)
}
const desktop = data?.tools["hermes_desktop"]
const tool = data?.tools[active]
async function copy(which: "desktop" | "model" | "memory", snippet?: string) {
async function copy(which: "desktop" | "model", snippet?: string) {
if (!snippet) return
await navigator.clipboard.writeText(snippet)
setCopied(which)
@@ -123,7 +116,7 @@ export function ConnectView() {
</h1>
<p className="text-sm text-muted-foreground">
<span className="text-foreground">Hermes Desktop</span> ist die Tür zur Box einmal verbinden, fertig.
Für Spezialfälle gibt es darunter die rohen Leitungen (Gateway&nbsp;/v1 + Gedächtnis-MCP) für sonstige Tools.
Für Spezialfälle gibt es darunter den rohen Gateway-Zugang (&nbsp;/v1) für sonstige Tools.
</p>
</div>
@@ -165,7 +158,7 @@ export function ConnectView() {
<StatusBadge line={health?.memory} loading={healthLoading} />
</div>
<div className="mt-1 text-[11px] font-mono text-violet-300/80">
MCP · mcp_memory.py · separat
Hermes-nativ · im Agenten · nichts einzurichten
</div>
</div>
</div>
@@ -187,9 +180,9 @@ export function ConnectView() {
</div>
</div>
<p className="mt-3.5 text-[11px] text-muted-foreground leading-relaxed">
Der Gateway liefert <span className="text-foreground">nur das LLM</span>. Das geteilte Gedächtnis läuft über einen
<span className="text-foreground"> eigenen MCP-Server</span> und das Desktop-Gateway bietet die Agenten-Schnittstelle
alle drei Leitungen werden unabhängig eingerichtet. IDEs wählen die <span className="text-foreground">echten Modelle</span>
Der Gateway liefert <span className="text-foreground">nur das LLM</span>. Das Gedächtnis führt
<span className="text-foreground"> Hermes selbst</span> (nichts einzurichten die Kachel zeigt nur, ob es lebt), und das
Desktop-Gateway bietet die Agenten-Schnittstelle. IDEs wählen die <span className="text-foreground">echten Modelle</span>
{" "}(coder · heavy · vision); daneben gibt es die virtuellen Lanes <span className="text-foreground">chat</span> und
{" "}<span className="text-foreground">coding</span>, die je Anfrage selbst das passende Modell wählen (Alltags-Chat, simple Tools).
</p>
@@ -260,12 +253,12 @@ export function ConnectView() {
className="flex w-full items-center gap-2 p-4 text-sm font-space font-bold text-foreground cursor-pointer hover:text-primary transition-colors"
>
{sonstigeOffen ? <ChevronDown className="h-4 w-4" /> : <ChevronRight className="h-4 w-4" />}
Sonstige Tools (roher /v1-Zugang + Gedächtnis-MCP)
Sonstige Tools (roher /v1-Zugang)
<span className="text-[10px] font-medium text-muted-foreground normal-case">Kilo Code · Claude Code · Eigenbau</span>
</button>
{sonstigeOffen && (
<div className="grid gap-5 lg:grid-cols-2 p-4 pt-0">
<div className="grid gap-5 p-4 pt-0">
{/* Leitung 1 — Modell anbinden */}
<div className="space-y-3 rounded-2xl border border-border/60 border-t-2 border-t-primary/70 bg-card/30 p-4">
<div>
@@ -312,51 +305,6 @@ export function ConnectView() {
</>
)}
</div>
{/* Leitung 2 — Gedächtnis anbinden */}
<div className="space-y-3 rounded-2xl border border-border/60 border-t-2 border-t-violet-500/70 bg-card/30 p-4">
<div>
<div className="flex items-center gap-2 text-sm font-space font-bold text-foreground">
<span className="flex h-5 w-5 items-center justify-center rounded-md bg-violet-500/15 text-violet-300 text-[11px]">2</span>
Gedächtnis anbinden
<span className="text-[10px] font-medium text-muted-foreground normal-case">optional</span>
</div>
<p className="text-[11px] text-muted-foreground mt-0.5">Ein MCP-Block gilt zusätzlich für <em>jedes</em> Tool aus Schritt 1.</p>
</div>
<div className="flex items-start gap-2.5 p-3 rounded-xl bg-violet-500/5 border border-violet-500/20 text-[11px] text-muted-foreground leading-relaxed">
<Info className="h-4 w-4 text-violet-400 shrink-0 mt-0.5" />
<span>{data.memory.note}</span>
</div>
{/* Der Pfad wirkt NUR auf dieses Snippet — deshalb wohnt das Feld hier,
nicht mehr prominent in der Kopfzeile („Wann brauche ich das?"). */}
<div className="space-y-1.5">
<label className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground flex items-center gap-1.5">
<FolderOpen className="h-3.5 w-3.5 text-violet-400" /> Wo liegt mcp_memory.py auf DIESEM PC?
</label>
<input
value={mcpPath}
onChange={(e) => saveMcpPath(e.target.value)}
aria-label="Lokaler MCP-Scriptpfad"
spellCheck={false}
placeholder="z.B. F:\Coding Stuff\mission-control-2\mcp\mcp_memory.py"
className="w-full h-9 rounded-lg border border-border/60 bg-background/40 px-3 font-mono text-xs outline-none focus:ring-1 focus:ring-violet-500/50 text-foreground"
/>
<p className="text-[10px] text-muted-foreground/70">
Nur nötig, wenn du das Gedächtnis in einem PC-Tool anschließt das Script läuft lokal
und spricht mit der Box. Der Pfad landet direkt im Snippet unten.
</p>
</div>
<CodeWindow
tool={data.memory}
fileName="mcp.json"
accent="violet"
copied={copied === "memory"}
onCopy={() => copy("memory", data.memory.snippet)}
/>
</div>
</div>
)}
</div>
+6 -4
View File
@@ -345,10 +345,12 @@ description: Treibt Entwicklung mit strikter TDD-Praxis
</div>
</div>
<Stack>
Dein Gedächtnis (Tab <strong>Gedächtnis</strong>) ist <strong>Mem0</strong>-basiert: auto-lernend &amp;
semantisch, <strong>graph-first</strong> dargestellt, mit 4-Typen-Taxonomie
(<Pill>Identität</Pill> · <Pill>Wissen</Pill> · <Pill>Regeln</Pill> · <Pill>Ereignisse</Pill>). Der Agent
lernt im Hintergrund nach jedem Turn — egal ob du per Desktop, Konsole, Telegram oder Lucy mit ihm sprichst.
Dein Gedächtnis führt <strong>Hermes</strong> selbst — auto-lernend und semantisch. Der Agent lernt im
Hintergrund nach jedem Turn, egal ob du per Desktop, Konsole, Telegram oder Lucy mit ihm sprichst.
<br />Deshalb hat das Steuerpult <strong>keinen eigenen Gedächtnis-Tab</strong>: bis August 2026 lag das
Gedächtnis in einem MC2-Sidecar, seit dessen Ablösung ist Hermes die einzige Quelle — angesehen und
gepflegt wird es dort, nicht hier. Unter <strong>Wissen</strong> findest du weiterhin die Graph-Sicht
auf Lucys Wissens-Vault.
<br /><strong>Gotcha:</strong> ein gelöschter Fakt kann wieder auftauchen, solange die Original-Nachricht noch im Verlauf steht (additive Extraktion).
</Stack>
</Card>