diff --git a/infrastructure/OPENMEMORY.md b/infrastructure/OPENMEMORY.md new file mode 100644 index 000000000..6b3afe1eb --- /dev/null +++ b/infrastructure/OPENMEMORY.md @@ -0,0 +1,48 @@ +# OpenMemory (mem0) + +Selbst-gehosteter Memory-Store mit MCP-Schnittstelle. Wird u. a. von Cursor und Jervais/Hermes als persistentes Gedaechtnis genutzt. + +## Deployment +- **Host:** CT122 auf pve-hetzner (Tailscale-Gateway `root@100.88.230.59`), interne IP `10.10.10.122`. +- **Container:** Docker Compose unter `/root/mem0/openmemory/` (`docker-compose.yml`): + - `openmemory-openmemory-mcp-1` (`mem0/openmemory-mcp`) — API/MCP auf Port `8765`, `uvicorn main:app --reload --workers 4`. + - `openmemory-mem0_store-1` (`qdrant/qdrant`) — Vektor-Store, Collection `openmemory`. + - `openmemory-openmemory-ui-1` (`mem0/openmemory-ui`) — Dashboard auf Port `3000`. +- **App-Quellcode (bind-mount):** Host `/root/mem0/openmemory/api` → Container `/usr/src/openmemory`. +- **Aktive Konfiguration:** NICHT `config.json`, sondern DB-Tabelle `configs` (key `main`) in `/usr/src/openmemory/openmemory.db`. LLM = `gpt-4o-mini` via OpenRouter (`OPENAI_BASE_URL=https://openrouter.ai/api/v1`), Embedder `text-embedding-3-small`. +- **Zugang vom Cursor-Host:** SSH-Tunnel `openmemory-tunnel.service` (autossh) leitet `localhost:8765` → `10.10.10.122:8765`. MCP-URL in `mcp.json`: `http://localhost:8765/mcp/cursor/sse/orbitalo`. +- **Logs:** `docker logs openmemory-openmemory-mcp-1` (json-file, keine Rotation konfiguriert). + +--- + +# Hotfix — 2026-05-31 + +Behob zwei Fehlfunktionen. + +## Symptome +1. `list_memories` lieferte hart: `Error getting memories: fromisoformat: argument must be str`. +2. `add_memories` mit laengeren Texten gab still `{"results": []}` zurueck (nicht gespeichert), ohne sichtbaren Client-Fehler. + +## Root Causes +1. **Gemischte Timestamp-Typen in qdrant.** 274 von 663 Punkten hatten `hash` und `created_at` als **Integer** (alte Records einer frueheren mem0-Version), neuere als String/ISO. + - `mem0.memory.main._normalize_iso_timestamp_to_utc()` fing nur `ValueError`; bei int wirft `datetime.fromisoformat()` ein `TypeError` → `get_all`/`list_memories` crasht komplett. + - Zusaetzlich verlangt das Pydantic-Modell `MemoryItem` Strings fuer `hash`/`created_at` → `ValidationError` bei int. +2. **Truncation des Extraktor-LLM-JSON.** `max_tokens: 2000` zu klein; beim Update-Memory-Schritt (Prompt enthaelt alle bestehenden Memories) wurde das JSON abgeschnitten → `Invalid JSON response` → leeres `results`. + - Hinweis: Leeres `results` kann AUCH legitim sein (LLM-Dedup → `event: NONE`/`NOOP`). Nur das abgeschnittene JSON ist der Bug. + +## Fixes (angewendet + verifiziert) +1. **qdrant-Daten normalisiert:** 274 Records, `hash` int→`str`, `created_at`/`updated_at` epoch-int→ISO-UTC. Backup: `api/qdrant_intfix_backup-20260531.json`. +2. **mem0-Library tolerant:** `site-packages/mem0/memory/main.py` `except ValueError:` → `except (ValueError, TypeError):`. Backup `.bak-tsfix-20260531` (NICHT rebuild-fest). +3. **Durabler Monkeypatch (rebuild-fest):** in `api/main.py` nach den Imports — ueberschreibt `_normalize_iso_timestamp_to_utc` so, dass Nicht-String-Werte unveraendert durchgereicht werden. Backup `api/main.py.bak-tsfix-20260531`. +4. **max_tokens erhoeht:** DB-Config `configs.main` → `mem0.llm.config.max_tokens` `2000` → `8000`. Backup `api/config_main.bak-20260531.json`. + +## Verifikation +- `_normalize_iso_timestamp_to_utc(1774205916)` gibt int zurueck statt Crash; ISO weiterhin korrekt. +- `list_memories()` liefert JSON-Array (100), 0 verbleibende int-Records. +- Langer `add_memories` → gueltiges JSON, `event: ADD` (Dedup korrekt `NONE`/`NOOP`). +- Live ueber Cursor-MCP (nach Client-Reload) beide Tools ok. + +## Nach Container-Rebuild beachten +- Persistent: Fix 1 (qdrant-Daten), Fix 3 (Monkeypatch in `main.py`), Fix 4 (DB-Config). +- Verloren bei Image-Rebuild: Fix 2 (site-packages) — durch Fix 3 abgedeckt. +- Container-Neustart invalidiert MCP-Sessions → Clients muessen neu initialisieren (`-32602` = request before initialization). In Cursor: MCP `openmemory` toggeln oder Fenster neu laden.