# #88 — Assistant IA : contexte applicatif & fiabilité des liens > **Statut :** 🟢 corrigé / livré (en attente de vérification utilisateur) > **Version :** 2.3.0 > **Composants :** `frontend/js/bookslm.js`, `backend/bookslm.py`, `backend/bookslm_routes.py` > **Bugs liés :** BUG-041, BUG-042 ## Contexte Trois troubles d'usage signalés sur l'Assistant IA (BooksLM) : 1. **Répertoire vide bloquant** — ouvrir l'assistant sur un dossier ne contenant aucun fichier markdown renvoyait `⚠ Error: Aucun fichier markdown trouvé dans ce dossier` (HTTP 404) au lieu de répondre à la question de l'utilisateur. 2. **Assistant Général aveugle** — en mode Général, l'assistant ne savait que lister les vaults : il ne connaissait ni les documents ouverts, ni le répertoire courant, ni la page de résultats de recherche, ni les fichiers récemment modifiés. 3. **Liens de fichiers peu fiables** — l'assistant produisait des liens vers des noms de fichiers qui échouaient avec `File not found: …`, sans règle claire (nom simple, dossier, chemin complet). ## Conception ### 1. Dégradation gracieuse du dossier vide (BUG-041) `_resolve_system_prompt` (`backend/bookslm_routes.py`) ne lève plus de 404 quand le contexte d'un dossier est vide. Il construit le prompt Général (aide applicative + actions), enrichi d'un bloc **« Dossier vide »**, et prévient le modèle qu'aucun contexte documentaire n'est disponible — il répond quand même et propose une création de fichier si pertinent. Le prompt Général reçoit en outre les **fichiers récemment modifiés** de l'utilisateur (`backend/services/recent.list_recent`, best-effort). ### 2. Contexte applicatif de l'assistant Général (#88) Le frontend envoie un nouveau champ `app_context` dans les requêtes `/chat` et `/agent` (`_buildAppContext()`), contenant l'état vivant de l'interface : | Champ | Contenu | |---|---| | `open_documents` | Documents ouverts dans les onglets/panneaux (via `collectOpenDocuments()`) | | `current_path` | Document affiché dans le viewer | | `directory` | Répertoire courant de l'assistant | | `vault` | Vault sélectionné | | `search_query` / `search_total` | Dernière recherche et nombre de résultats | | `search_results` | Fichiers affichés sur la page de résultats (max 20) | Côté backend, `build_general_system_prompt(vaults, app_context, recent_files)` rend un bloc **« Contexte applicatif actuel »** ajouté au prompt Général. ### 3. Liens de fichiers déterministes (BUG-042) Classification des liens (`_classifyPath`) : | Forme | `data-kind` | Action au clic | |---|---|---| | Nom de fichier seul (`readme.md`) | `name` | Copie le nom dans le presse-papiers | | Chemin de dossier (`projets/2026`) | `dir` | Révèle le dossier dans l'arborescence | | Chemin de fichier (`notes/a.md`) | `file` | Ouvre le fichier dans le viewer | Avant d'agir, `_activatePath()` **résout** le chemin contre l'index du vault (`_resolveExistingPath`) : correspondance exacte, puis suffixe (segment de tête omis par le modèle), puis basename unique. Les chemins non résolus copient le nom au lieu d'ouvrir un lien mort — plus de `File not found`. ### 4. Espaces, accents et préfixe de vault dans les chemins (BUG-042) Les noms de fichiers/dossiers pouvant contenir des espaces et des accents, la détection et la résolution sont adaptées : - **Liens markdown** : la cible peut contenir des espaces, être encadrée par `<…>` ou porter un `"titre"` ; les URL percent-encodées (`%20`) sont décodées. - **Code inline** : `` `Ma note.md` `` / `` `Recettes/Préparation.md` `` sont reconnus (`_looksLikePath` utilise `PATH_NAME_RE`, une classe Unicode `\p{L}\p{N}\p{M}` — les accents sont acceptés, le jeu de caractères reste strict pour rejeter extraits de code et commandes shell). - **Mentions brutes** : une mention avec espaces n'est liée **que si elle existe réellement dans l'index du vault** (`_linkifySpacePaths` + `_confirmPathInCache`), et l'acceptation se fait sur le **plus long suffixe aligné sur un mot** — ainsi « Ouvre Mon dossier/Ma note.md » ne crée pas de lien englobant « Ouvre » et la prose ordinaire n'est jamais liée à tort. Les chemins sans espace mais accentués sont liés par le motif `PATH_WITH_DIR_RE`, lui aussi Unicode-aware. - **Normalisation Unicode** : `_normKey()` compare en NFC + minuscules, donc une mention décomposée (`e` + accent combinant, comme sur macOS) correspond à une entrée d'index précomposée, et inversement. - **Préfixe de vault** : `_splitVaultPrefix()` retire un premier segment égal au nom d'un vault connu (`TestVault/Recettes/Pizza Maison.md` → `Recettes/Pizza Maison.md`). La résolution interroge l'index **de ce vault** (`_fetchPathsForVault`, fetch ponctuel sans écraser le cache du vault actif), puis `_openFileLink`/`_revealPath` reçoivent le vault cible. Si le préfixe ne correspond à aucun vault connu, `_resolveExistingPath` retente en retirant le premier segment. ## Tests - `tests/frontend/ai.test.mjs` : classification (`name`/`file`/`dir`), routage `_activatePath` (ouvre/révèle/copie), clic d'un lien « nom » → presse-papiers, et prise en charge des espaces (code inline, liens markdown `%20`, mentions brutes liées uniquement si présentes dans l'index, résolution au clic). - `tests/test_bookslm.py` : `build_general_system_prompt` avec `app_context` + `recent_files` ; prompt inchangé sans contexte ; chat sur dossier vide ne renvoie plus 404.