0da5e2aba1
Store SQLite conversations/messages (propriété par actor, fenêtre 20), historique rejoué au LLM (runAgentTurn history), ChatService persiste et renvoie conversationId. API GET/DELETE /conversations + chat avec conversationId. UI Chat: sidebar conversations (drawer mobile), nouvelle, reprise, suppression. docs/conversations.md. 83 tests verts, build web vert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016w5jRe87MGdd6AMvXQcHNi
55 lines
2.4 KiB
Markdown
55 lines
2.4 KiB
Markdown
# Conversations persistantes (mémoire multi-tour)
|
|
|
|
CHLOVA stocke chaque conversation et **rejoue l'historique récent** au LLM, pour
|
|
qu'il garde le contexte d'un message à l'autre et que l'utilisateur puisse
|
|
**reprendre** une conversation plus tard.
|
|
|
|
## Modèle
|
|
|
|
SQLite (`node:sqlite`, même fichier que la table assets — `CHLOVA_DB_PATH`).
|
|
|
|
| Table | Colonnes |
|
|
|---|---|
|
|
| `conversations` | `id` (uuid), `actor`, `title`, `created_at`, `updated_at` |
|
|
| `messages` | `id`, `conversation_id`, `role` (`user`/`assistant`), `content`, `ts` |
|
|
|
|
- **Propriété** : une conversation appartient à un `actor` (API = `api:owner`,
|
|
Telegram = `telegram:<userId>`). Accès à une conversation d'un autre acteur
|
|
refusé (`ForbiddenConversationError` → HTTP 403 / 404 selon l'endpoint).
|
|
- **Titre** : dérivé du 1er message (tronqué à 60 car.).
|
|
- **Fenêtre de contexte** : les `HISTORY_WINDOW` (= 20) derniers messages sont
|
|
rejoués au LLM (`ChatService` → `runAgentTurn({ history })`). Au-delà, l'ancien
|
|
n'est pas envoyé (pas de résumé/troncature par tokens en v1 — amélioration
|
|
possible si les conversations deviennent longues).
|
|
|
|
## Flux
|
|
|
|
1. `POST /api/chat { message, conversationId? }` :
|
|
- sans `conversationId` → nouvelle conversation créée, son id renvoyé ;
|
|
- avec `conversationId` → historique chargé + rejoué, message ajouté.
|
|
- réponse : `{ reply, conversationId }`.
|
|
2. `GET /api/conversations` → liste (id, titre, dates) de l'acteur, par récence.
|
|
3. `GET /api/conversations/:id` → messages complets (reprise).
|
|
4. `DELETE /api/conversations/:id` → suppression (messages + conversation).
|
|
|
|
## UI
|
|
|
|
Onglet **Chat** : barre latérale des conversations (drawer sur mobile, fixe en
|
|
`md+`), bouton **Nouvelle**, sélection pour reprendre, suppression. L'envoi
|
|
transmet le `conversationId` courant ; une nouvelle conversation rafraîchit la
|
|
liste.
|
|
|
|
## Surfaces
|
|
|
|
- **API/UI** : pleinement câblé (création, reprise, suppression).
|
|
- **Telegram** (si activé) : `conversationId` stable = `telegram:<userId>` →
|
|
mémoire continue par utilisateur.
|
|
- **Mobile (Expo)** : chat encore sans état — branchement des conversations à
|
|
faire (réutilise les mêmes endpoints).
|
|
|
|
## Sécurité / vie privée
|
|
|
|
Les messages sont stockés en clair dans la base (volume `chlova-data`). Pas de
|
|
secret n'y transite normalement (l'agent manipule des références). La base n'est
|
|
jamais exposée ; seul le backend y accède.
|