102 lines
12 KiB
Markdown
102 lines
12 KiB
Markdown
# #76 — BooksLM — Console AI contextuelle par répertoire (style NotebookLM)
|
|
|
|
> **Statut :** ✅ Terminé
|
|
> **Effort :** 5-6 jours (réalisé) | **Impact :** 🟡
|
|
> **Références :** [Roadmap](../ROADMAP.md) · [Changelog — 2.2.0](../../CHANGELOG.md)
|
|
|
|
> **Extension (#80, 2026-09-11) :** rendu Markdown complet des réponses, liens cliquables
|
|
> fichiers/chemins et gestion multi-sessions — voir [ai-assistant-ux.md](./ai-assistant-ux.md).
|
|
>
|
|
> **Extension (2026-09-11) :** l'assistant AI est désormais **multi-contexte** — Répertoire
|
|
> (mode historique), Documents (documents ouverts, via le bouton flottant) et Général (aucun
|
|
> document ouvert : aide sur l'app + création de fichiers/dossiers par cartes d'action). Header
|
|
> refondu (sélecteur fournisseur/modèle sur une ligne dédiée), `Entrée` envoie / `Ctrl+Entrée`
|
|
> insère un saut de ligne. Voir CHANGELOG.
|
|
|
|
- **Description :** Console de chat AI contextuelle accessible via le menu contextuel des répertoires dans l'arborescence. Au clic sur « BooksLM », un panneau de chat s'ouvre à droite du viewer et indexe automatiquement toutes les ressources markdown (et PDF via #74) du répertoire courant et de ses sous-répertoires récursivement comme contexte pour un assistant AI. L'assistant peut répondre à des questions, résumer, synthétiser, et croiser l'information à travers tous les documents du scope — exactement comme NotebookLM de Google, mais pour n'importe quel répertoire de votre vault Obsidian.
|
|
|
|
- **Fonctionnement général :**
|
|
- L'utilisateur fait un clic-droit sur un répertoire dans l'arborescence → option « BooksLM »
|
|
- Un panneau latéral (450-500px) s'ouvre à droite, poussant le viewer existant
|
|
- Le backend collecte tous les fichiers `.md` (et `.pdf` si #74 est complété) récursivement
|
|
- Le contenu est assemblé en un contexte système pour le LLM (fenêtre de contexte optimisée)
|
|
- L'utilisateur peut chatter avec l'AI qui a une connaissance complète du répertoire
|
|
- L'historique de chat est optionnellement sauvegardé (localStorage ou fichier `.books-lm.json` dans le répertoire)
|
|
|
|
- **Sous-tâches :**
|
|
|
|
## A. Backend — Collecte et préparation du contexte (1.5-2 jours) — ✅ livré (backend/bookslm.py, bookslm_routes.py)
|
|
- [x] **A1. Nouvel endpoint `POST /api/ai/bookslm/context`** : Reçoit `{vault, directory}` → parcourt récursivement le répertoire → lit tous les fichiers supportés → retourne un objet `{files: [{path, title, content, type: "md"|"pdf"}], total_chars, file_count, directory_tree}`
|
|
- [x] **A2. Limites configurables** : `BOOKSLM_MAX_FILES` (défaut 200), `BOOKSLM_MAX_TOTAL_CHARS` (défaut 200 000), `BOOKSLM_MAX_FILE_CHARS` (défaut 30 000 par fichier). Les fichiers au-delà sont tronqués avec un message `[... continue dans le fichier]`.
|
|
- [x] **A3. Filtrage intelligent** : Ignorer les fichiers cachés (`.` préfixe), les dossiers `_attachments/`, les fichiers binaires non-supportés. Respecter `.gitignore` ou `.obsigate-ignore` si présent.
|
|
- [ ] **A4. Streaming du contexte (non retenu — collecte rapide, indicateur simple côté UI)** : Pour les très gros répertoires, l'endpoint supporte le streaming SSE pour informer l'UI de la progression (« Indexation de 45/127 fichiers... »).
|
|
|
|
## B. Backend — Endpoint chat BooksLM (1 jour) — ✅ livré
|
|
- [x] **B1. Endpoint `POST /api/ai/bookslm/chat`** : Reçoit `{vault, directory, message, conversation_history: [{role, content}]}` → construit le contexte système à partir des fichiers du répertoire → appelle le provider AI configuré → stream la réponse via SSE.
|
|
- [x] **B2. Prompt système** : Template par défaut optimisé : « Tu es un assistant de recherche qui aide à comprendre et analyser les documents d'un répertoire. Voici le contenu de tous les documents disponibles. Réponds en te basant UNIQUEMENT sur ces documents. Cite tes sources avec le nom du fichier. Si l'information n'est pas dans les documents, dis-le clairement. »
|
|
- [x] **B3. Mode « Sources »** : Chaque réponse inclut les fichiers référencés (détectés via mention de titre ou contenu). L'UI affiche des badges de source cliquables.
|
|
- [x] **B4. Mise en cache du contexte** : Le contexte du répertoire est caché en mémoire (hash du contenu) pour éviter de re-parser tous les fichiers à chaque message. Invalidé si un fichier est modifié (watcher).
|
|
- [x] **B5. Provider** : Utilise la même abstraction provider que l'AI Editor (#27) — DeepSeek, OpenRouter, Gemini. Ajouter `BOOKSLM_DEFAULT_MODEL` dans `.env` (défaut : `DEEPSEEK_MODEL`).
|
|
|
|
## C. Frontend — Panneau de chat BooksLM (2 jours) — ✅ livré (frontend/js/bookslm.js)
|
|
- [x] **C1. Module `frontend/js/bookslm.js`** : Nouveau module ES avec la classe `BooksLM` :
|
|
- Gère l'état : `_isOpen`, `_currentDirectory`, `_messages[]`, `_contextFiles[]`, `_isLoading`
|
|
- Crée le DOM du panneau : conteneur latéral `.bookslm-panel` (450px, redimensionnable via poignée)
|
|
- Header : titre « BooksLM », nom du répertoire courant, bouton fermer, bouton « Nouvelle conversation »
|
|
- Zone de messages : scrollable, bulles utilisateur (droite) et assistant (gauche) avec Markdown rendu
|
|
- Zone d'entrée : `textarea` avec Ctrl+Enter pour envoyer, bouton envoyer
|
|
- Barre d'état : nombre de fichiers indexés, nombre total de caractères
|
|
- [x] **C2. Intégration au menu contextuel** : Dans `frontend/js/context-menu.js`, ajouter l'option « 🧠 BooksLM » pour les nœuds de type `directory` dans l'arborescence. Visible seulement si le vault est accessible.
|
|
- [x] **C3. Rendu Markdown dans le chat** : Utiliser le renderer Markdown existant (ou un sous-ensemble simplifié) pour afficher les réponses de l'AI avec support du **gras**, *italique*, `code`, listes, et tableaux.
|
|
- [x] **C4. Streaming des réponses** : Connexion SSE pour afficher la réponse de l'AI token par token (effet « typing » naturel).
|
|
- [x] **C5. Badges de sources** : Après chaque réponse, afficher les fichiers sources mentionnés sous forme de badges cliquables qui ouvrent le fichier dans le viewer principal.
|
|
- [x] **C6. Mode plein écran** : Bouton pour basculer en mode plein écran (cache la sidebar, le panneau prend tout l'espace). Utile pour les sessions de recherche intense.
|
|
|
|
## D. Frontend — Actions et UX (0.5-1 jour) — ✅ livré (D5 partiel)
|
|
- [x] **D1. Copier la réponse** : Bouton copie sur chaque message assistant.
|
|
- [x] **D2. Régénérer** : Bouton pour régénérer la dernière réponse (utile si la réponse est hors-sujet).
|
|
- [x] **D3. Exporter la conversation** : Bouton pour exporter l'historique en Markdown → sauvegarder comme note dans le répertoire courant.
|
|
- [x] **D4. Historique des conversations** : Stockage dans `localStorage` par clé `bookslm-history-{vault}-{directory}`. Liste déroulante dans le header pour charger une conversation précédente.
|
|
> **Évolué (#95, 2026-09-16) :** l'historique est désormais **persisté côté backend**
|
|
> (`data/ai_history/{user}.json`), le localStorage ne sert plus que de cache,
|
|
> et les anciennes clés `bookslm-sessions-*` / `bookslm-history-*` sont migrées.
|
|
> Voir [ai-assistant-history.md](./ai-assistant-history.md).
|
|
- [x] **D5. Indicateur de contexte (barre de progression %) — non retenu, compteur fichiers/caractères affiché)** : Barre de progression montrant l'utilisation du contexte (% de la limite `BOOKSLM_MAX_TOTAL_CHARS`). Si le répertoire est trop gros, suggérer de réduire le scope.
|
|
- [x] **D6. Suggestions de questions** : Après l'indexation, afficher 3 questions suggérées basées sur les titres et métadonnées des fichiers (« Résume ce répertoire », « Quels sont les thèmes principaux ? », « Y a-t-il des contradictions entre ces documents ? »).
|
|
|
|
## E. CSS & Design (0.5 jour) — ✅ livré
|
|
- [x] **E1. Panneau latéral** : Animation slide-in depuis la droite (300ms ease-out). Ombre portée pour séparation visuelle.
|
|
- [x] **E2. Poignée de redimensionnement** : Similaire à `.sidebar-resize-handle`, curseur `col-resize`, largeur min 350px, max 800px. Persistance dans localStorage.
|
|
- [x] **E3. Bulles de chat** : Style cohérent avec le thème actuel. Messages utilisateur avec accent-color, messages assistant avec fond `var(--surface2)`.
|
|
- [x] **E4. Responsive** : Sur mobile (<768px), le panneau passe en plein écran (pas de split view). Navigation par swipe pour revenir au viewer.
|
|
- [x] **E5. Thème sombre/clair** : Toutes les variables CSS utilisent les customs properties existantes → compatibilité automatique.
|
|
|
|
## F. Intégration et compatibilité (0.5 jour) — ✅ livré (F1 adapté : panneau dédié, pas un pane du PaneManager)
|
|
- [ ] **F1. Compatibilité Split View (#75) (adapté : panneau latéral indépendant, cohabite avec le split view)** : Si le split view est actif, BooksLM s'ouvre en remplacement du panneau le plus à droite (ou en 3e colonne). Le panneau BooksLM est traité comme un type spécial de pane dans le PaneManager.
|
|
- [x] **F2. Compatibilité AI Editor (#26-29)** : BooksLM utilise le même système de provider AI. Les clés API configurées pour l'AI Editor fonctionnent pour BooksLM.
|
|
- [x] **F3. Compatibilité PDF (#74)** : Si le support PDF est implémenté, les PDFs dans le répertoire sont inclus dans le contexte (texte extrait).
|
|
- [x] **F4. Palette de commandes (#31)** : Ajouter les commandes « BooksLM: Ouvrir pour le répertoire courant » et « BooksLM: Nouvelle conversation ».
|
|
|
|
## G. Tests (1 jour) — ✅ G1 livré (28 tests), G2/G3 non retenus
|
|
- [x] **G1. Tests unitaires backend** :
|
|
- `test_bookslm_context.py` : collecte récursive, respect des limites, filtrage fichiers cachés, streaming SSE
|
|
- `test_bookslm_chat.py` : construction du prompt, caching du contexte, invalidation après modification
|
|
- [ ] **G2. Tests d'intégration frontend (non retenus)** :
|
|
- Ouverture du panneau BooksLM depuis le menu contextuel
|
|
- Envoi d'un message et affichage de la réponse
|
|
- Badges de sources cliquables
|
|
- Export de conversation
|
|
- Redimensionnement du panneau
|
|
- [ ] **G3. Tests E2E (Playwright) (non retenus à ce jour)** :
|
|
- Test : clic-droit sur répertoire → BooksLM → panneau visible
|
|
- Test : chat fonctionnel → message envoyé → réponse reçue
|
|
- Test : fermeture et réouverture → historique restauré
|
|
|
|
## H. Points d'attention / Risques
|
|
- **Taille du contexte** : Un répertoire avec 500 fichiers markdown peut facilement dépasser 1M de caractères → essentiel de tronquer intelligemment (préférer les fichiers modifiés récemment, ou prioriser selon la structure : README.md, index.md en premier).
|
|
- **Coût API** : Chaque message envoie le contexte complet au LLM → potentiellement coûteux en tokens. Ajouter un avertissement si le contexte dépasse 100K tokens estimés.
|
|
- **Performance** : La collecte récursive de 200+ fichiers peut prendre plusieurs secondes → l'UI doit montrer la progression (streaming SSE) et le backend doit être non-bloquant (background task).
|
|
- **Sécurité** : Ne pas envoyer les fichiers ignorés (`.env`, `.git/`, `.hermes/`, tokens, secrets) dans le contexte. Le `secret_redactor.py` existant (#16) doit être appliqué au contenu avant envoi au LLM.
|
|
- **Privacy** : Si le provider AI est externe (OpenRouter, DeepSeek, Gemini), le contenu des fichiers est envoyé à un tiers → warning dans l'UI avec option d'activer/désactiver par vault.
|
|
- **Scope répertoire** : Ne PAS inclure les fichiers hors du répertoire (pas de remontée au parent ou de traversée de vault). Le scope est strictement le répertoire + sous-répertoires.
|