Commit Graph

2 Commits

Author SHA1 Message Date
duffyduck 31a1370050 feat(brain): memory_save mit attach_paths — ARIA haengt Bilder selbst an
Letzter Baustein vor Stefan's End-to-End-Test:

memory_attachments.attach_from_path(memory_id, src_path):
- Kopiert eine bestehende Datei aus /shared/uploads/ oder
  /shared/memory-attachments/ in das Anhang-Verzeichnis der Memory
- Pfadschutz: nur ALLOWED_SOURCE_PREFIXES (/shared/uploads/,
  /shared/memory-attachments/) — kein Zugriff auf Root-FS oder
  SSH-Keys
- Groessen-Limit wie save_attachment (20 MB Default)

agent.py memory_save:
- Neuer optionaler Parameter `attach_paths: List[str]`
- Nach dem upsert: pro Pfad attach_from_path → Payload update mit
  neuen Anhang-Metadaten
- Fehler beim Anhang sind nicht fatal (Memory bleibt gespeichert,
  Hinweis in der Tool-Response)
- Tool-Description deutlich erweitert: expliziter Workflow-Hinweis
  bei Bildern → erst `Read <pfad>` aufrufen (Claude Code Read ist
  multi-modal), Texte/Kennungen/Marken in den content extrahieren,
  dann erst memory_save mit attach_paths. Beispiel-Workflow als
  Pseudocode mit Cessna 172 / Kennung D-EAAA.

End-to-End-Workflow ist jetzt einarmig moeglich:
  User: "Ich hab eine Cessna 172" + Bild im Attachment
  ARIA: Read /shared/uploads/aria_xy.jpg → sieht "Kennung D-EAAA"
  ARIA: memory_save(content="Stefan besitzt eine Cessna 172,
        Kennung D-EAAA, weiss/rot lackiert.",
        attach_paths=["/shared/uploads/aria_xy.jpg"])
  → 🧠-Bubble mit Anhang in der App
  → Spaetere Frage "welche Kennung hat mein Flieger?" liefert via
    Cold-Memory den Eintrag inkl. Kennung aus dem content

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 02:57:02 +02:00
duffyduck c677cfed24 feat(brain): Anhaenge an Memory-Eintraege (Stufe A — Backend)
Pro Memory koennen jetzt Dateien (Bilder, PDFs, Sound, ...) angehaengt
werden. Use-Case: Stefan sagt "ich hab eine Cessna 172" und pinnt
gleich ein Foto dran — ARIA sieht spaeter neben dem Memory auch die
visuelle Referenz (Stufe E = Multi-Modal-Pipeline).

Stufe A baut nur den Backend-Layer; UI kommt in Stufe B (Diagnostic)
und C (App). Anhaenge werden in Stufe A nur via HTTP-API gepflegt
(curl), ARIA selbst kann sie noch nicht hochladen — sinnvoll erst
wenn die Vision-Pipeline (Stufe E) steht.

Komponenten:

- memory_attachments.py: neuer Storage-Helper. Layout
  /shared/memory-attachments/<memory-id>/<safe-filename>.
  Filename-Sanitization (kein Path-Traversal), Limit 20 MB
  konfigurierbar, save/list/delete/read_bytes + delete_all fuer
  Cleanup beim Memory-Delete.

- vector_store.py: MemoryPoint.attachments (List[dict]) — Metadaten
  {name, mime, size, path} im Qdrant-Payload damit Suche/Anzeige
  sie ohne Filesystem-Lookup kennt.

- main.py:
  - MemoryIn akzeptiert attachments-Liste (fuer Restore-Faelle)
  - MemoryOut liefert attachments
  - GET    /memory/{id}/attachments              → Liste vom FS
  - POST   /memory/{id}/attachments              → Base64-Upload,
            schreibt FS + updated Payload-Liste
  - DELETE /memory/{id}/attachments/{filename}   → FS + Payload-Eintrag weg
  - GET    /memory/{id}/attachments/{filename}   → Bytes mit MIME serve
  - /memory/delete cleanup: ruft attachments.delete_all damit kein
    Verzeichnis verwaist

Smoke-Test nach Brain-Rebuild (Stefan auf VM):
  # Memory-ID rauspicken
  ID=$(curl -s "$ARIA_BRAIN_URL/memory/list?type=fact" | python3 -c "import sys,json;print(json.load(sys.stdin)[0]['id'])")
  # Bild als Base64 hochladen
  B64=$(base64 -w0 /pfad/zu/foto.jpg)
  curl -s -X POST "$ARIA_BRAIN_URL/memory/$ID/attachments" \
    -H 'Content-Type: application/json' \
    -d "{\"name\":\"foto.jpg\",\"data_base64\":\"$B64\"}" | jq
  # Liste anzeigen
  curl -s "$ARIA_BRAIN_URL/memory/$ID/attachments" | jq
  # Datei wieder laden
  curl -s "$ARIA_BRAIN_URL/memory/$ID/attachments/foto.jpg" -o /tmp/back.jpg

Stufe B (Diagnostic-UI) folgt sobald A getestet ist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 02:27:02 +02:00