diff --git a/CHANGELOG.md b/CHANGELOG.md index ae3315c..23be7ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -221,8 +221,26 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). `localStorage`) : l'envoi bascule vers `/api/ai/bookslm/agent`, affiche la trace des appels d'outils et les cartes de confirmation (Apply + aperçu diff) ; `/chat` reste le défaut. i18n FR/EN. +### Modifié + +- **#82 Assistant IA — barre latérale épurée & suivi visuel des requêtes** — la section + « Fournisseur & modèle » perd ses intitulés (titre de section et libellé « Fournisseur : ») + pour rester discrète ; la description du contexte Général n'est plus affichée (bandeau de + statut masqué, description accessible au **survol** de l'en-tête) ; le placeholder + « Posez une question sur ces documents… » est retiré ; le bouton « Envoyer » devient un **emoji + compact** (✈️). Un **indicateur d'activité** apparaît pendant le traitement et détaille le + workflow : envoi, réception de la réponse, appels d'outils (`Outil : X…`), attente de + confirmation, succès ou échec. i18n FR/EN (`ai.activity_*`, `ai.composer_label`). Tests JSDOM + (`tests/frontend/ai.test.mjs` +1). + ### Corrigé +- **BUG-012 — Assistant IA : la commande `@` n'affichait aucun menu en mode Général** — sans vault + résolu, la détection `@` ne listait rien (menu masqué) et le backend ignorait ensuite le + contexte. Le menu est désormais **toujours rendu** et `_mentionVault()` retombe sur le vault de + contexte de la barre latérale, puis sur le premier vault disponible, avant de basculer sur + `vault=all` pour les recherches. Tests JSDOM (`tests/frontend/ai.test.mjs` +1). + - **BUG-011 — Assistant IA : noms de modèles illisibles dans la liste déroulante** — la liste déroulante des modèles s'ouvrait alignée à gauche (`left: 0`) et pouvait dépasser le bord droit de la barre latérale (ancrée à droite), rendant les noms tronqués/illisibles ; elle est diff --git a/docs/ISSUES_TODOLIST.md b/docs/ISSUES_TODOLIST.md index c73e29f..cda4873 100644 --- a/docs/ISSUES_TODOLIST.md +++ b/docs/ISSUES_TODOLIST.md @@ -121,6 +121,7 @@ Avant de corriger quoi que ce soit, un agent IA doit : | *BUG-009* | Assistant IA : liste de modèles corrompue (art ASCII) et clés i18n brutes (`ai.model_search`) sous OpenRouter | 🟢 corrigé | P1 | 📱 frontend | IA | `frontend/js/ai.js`, `frontend/js/i18n.js`, `frontend/sw.js`, `frontend/style.css` | Ouvrir le menu modèle sous « openrouter » | Locale non content-hashée en cache HTTP → `cache:'no-store'` + bump `SW_VERSION` v4 ; styles critiques du picker appliqués **en ligne** (popover absolu, liste en colonne, options `display:block`) ; rendu plafonné à 200 modèles + indicateur « … N autres » | OpenRouter expose plusieurs centaines de modèles ; si `style.css` est en cache, la liste s'affichait en bloc inline (art ASCII) et les clés i18n brutes provenaient d'un `fr.json` obsolète. Tests : `tests/frontend/ai.test.mjs` (+1) | | *BUG-010* | Assistant IA : la commande `@` n'ajoute pas le contexte à la requête en mode Général | 🟢 corrigé | P1 | 📱 frontend | IA | `frontend/js/bookslm.js` | Assistant en mode Général, taper `@fichier`, sélectionner, envoyer | Capture du `vault` renvoyé par `/api/tree-search` dans la sélection `@` ; `_contextVault()` propage ce vault aux requêtes `/context` et `/chat` ; recherches `@` suivantes limitées à ce vault | En mode Général, `_vault` est nul : la requête partait sans vault et le backend ignorait `extra_files`. Tests : `tests/frontend/ai.test.mjs` (+1) | | *BUG-011* | Assistant IA : noms de modèles illisibles dans la liste déroulante | 🟢 corrigé | P2 | 📱 frontend | IA | `frontend/js/ai.js`, `frontend/style.css` | Ouvrir le menu modèle dans la barre latérale de l'assistant | Popover aligné à droite du déclencheur (`right:0`), largeur 340 px bornée à `100vw - 24px`, noms sur plusieurs lignes (`overflow-wrap:anywhere`, police 0,78 rem) + `title` | La liste s'ouvrait vers la droite et dépassait le bord de la sidebar ancrée à droite ; noms tronqués. Tests : `tests/frontend/ai.test.mjs` | +| *BUG-012* | Assistant IA : la commande `@` n'affiche aucun menu de sélection en mode Général | 🟢 corrigé | P1 | 📱 frontend | IA | `frontend/js/bookslm.js` | Assistant en mode Général (aucun vault), taper `@` | `_showMentionMenu` rend **toujours** le menu (même vide) et `_mentionVault()` retombe sur `state.selectedContextVault` puis le premier `state.allVaults`, avant `vault=all` pour les requêtes | Sans vault résolu, l'ancien code masquait le menu et le backend ignorait le contexte. Tests : `tests/frontend/ai.test.mjs` (+1) | ### TODOs techniques (améliorations / nouvelles tâches) @@ -147,6 +148,7 @@ Avant de corriger quoi que ce soit, un agent IA doit : | 2026-09-12 | BUG-007, BUG-008, #82 | Correction + refonte UI | `frontend/js/bookslm.js`, `frontend/js/ai.js`, `frontend/style.css`, `frontend/locales/{fr,en}.json`, `backend/bookslm_routes.py`, `tests/frontend/ai.test.mjs`, `tests/test_bookslm.py` | BUG-007 : motifs Unicode + recherche NFD insensible aux accents + navigation ↑/↓ fiabilisée (jeton de séquence, scrollIntoView). BUG-008 : contexte ad-hoc `@` pris en compte en mode Général (backend) + repli `vault=all`. #82 : section « Fournisseur & modèle » compacte (recherche modèle + bulle capacités ℹ️ au survol/clic/appui long). Vérifié : tests frontend 41/41, `tests/test_bookslm.py` 47 passed. | 🟢 corrigé (en attente vérif utilisateur) | | 2026-09-12 | BUG-009 | Correction | `frontend/js/ai.js`, `frontend/js/i18n.js`, `frontend/sw.js`, `frontend/style.css`, `frontend/locales/{fr,en}.json`, `tests/frontend/ai.test.mjs` | BUG-009 : locale non content-hashée servie depuis le cache HTTP → clés i18n brutes ; passage en `cache:'no-store'` + `SW_VERSION` v4. Liste de modèles corrompue (OpenRouter, styles en cache) → styles critiques en ligne, options `display:block`, plafond 200 + indicateur. Vérifié : tests frontend 42/42. | 🟢 corrigé (en attente vérif utilisateur) | | 2026-09-12 | BUG-010, BUG-011 | Correction | `frontend/js/bookslm.js`, `frontend/js/ai.js`, `frontend/style.css`, `tests/frontend/ai.test.mjs` | BUG-010 : capture du `vault` des résultats `@` + `_contextVault()` propagé aux requêtes `/context`/`/chat` (mode Général). BUG-011 : popover modèle aligné à droite, largeur 340 px, noms multi-lignes + `title`. Vérifié en navigateur (Playwright) et tests frontend 43/43. | 🟢 corrigé (en attente vérif utilisateur) | +| 2026-09-12 | BUG-012, #82 | Correction + UX | `frontend/js/bookslm.js`, `frontend/js/ai.js`, `frontend/style.css`, `frontend/sw.js`, `frontend/locales/{fr,en}.json`, `tests/frontend/ai.test.mjs` | BUG-012 : le menu `@` est toujours rendu et `_mentionVault()` retombe sur le vault de contexte puis le premier vault disponible. #82 : suppression des intitulés « Fournisseur & modèle » / « Fournisseur : », description du contexte Général déplacée en info-bulle, placeholder retiré, bouton Envoyer en emoji ✈️, indicateur d'activité (envoi/réception/outils/confirmation/succès/échec), `SW_VERSION` v5. Vérifié Playwright + tests frontend 45/45. | 🟢 corrigé (en attente vérif utilisateur) | --- diff --git a/docs/features/ai-provider-picker.md b/docs/features/ai-provider-picker.md index 112da50..78ac31b 100644 --- a/docs/features/ai-provider-picker.md +++ b/docs/features/ai-provider-picker.md @@ -52,7 +52,18 @@ propage ce vault aux requêtes `/context` et `/chat` et les recherches suivantes restent dans ce vault (BUG-010, mode Général). -## F. Points d'attention +## F. Barre latérale épurée & suivi visuel (BUG-012, #82) — ✅ livré +- [x] Section « Fournisseur & modèle » sans intitulés (ni titre de section, ni « Fournisseur : »). +- [x] Description du contexte Général retirée de l'affichage (bandeau de statut masqué) et + exposée via `title` au survol de l'en-tête. +- [x] Placeholder « Posez une question sur ces documents… » retiré ; bouton « Envoyer » remplacé + par l'emoji compact ✈️. +- [x] **Indicateur d'activité** (`.bookslm-activity`) affichant le workflow : envoi, réception, + outil en cours, attente de confirmation, terminé, échec (`ai.activity_*`). +- [x] `@` : le menu est toujours rendu et `_mentionVault()` retombe sur le vault de contexte puis + le premier vault disponible (BUG-012). + +## G. Points d'attention - La table de capacités reste **statique** (`backend/model_capabilities.py`) : un modèle inconnu retombe sur le défaut du fournisseur. - Le select masqué est conservé uniquement pour la rétro-compatibilité ; ne pas le supprimer sans diff --git a/frontend/js/ai.js b/frontend/js/ai.js index 25391cf..66c395c 100644 --- a/frontend/js/ai.js +++ b/frontend/js/ai.js @@ -139,13 +139,10 @@ async function _buildPickerUI() { const wrap = document.createElement('div'); wrap.className = 'ai-picker'; - // ── Provider select (compact) ── - const providerLabel = document.createElement('span'); - providerLabel.className = 'ai-picker-label'; - providerLabel.textContent = t('ai.provider') + ':'; - + // ── Provider select (compact, no label to keep the toolbar discreet) ── const providerSelect = document.createElement('select'); providerSelect.className = 'ai-picker-select'; + providerSelect.setAttribute('aria-label', t('ai.provider')); const defaultOpt = document.createElement('option'); defaultOpt.value = ''; defaultOpt.textContent = t('ai.provider_default'); @@ -445,7 +442,6 @@ async function _buildPickerUI() { _renderList(); } - wrap.appendChild(providerLabel); wrap.appendChild(providerSelect); wrap.appendChild(modelSelect); wrap.appendChild(combo); diff --git a/frontend/js/bookslm.js b/frontend/js/bookslm.js index e587196..c2c98c5 100644 --- a/frontend/js/bookslm.js +++ b/frontend/js/bookslm.js @@ -107,6 +107,8 @@ class BooksLM { this._menuKind = null; // Monotonic token used to drop stale async menu renders (fast typing). this._menuSeq = 0; + // Timer that hides the "done" activity indicator after a short delay. + this._activityHideTimer = null; } _readAgentMode() { @@ -333,6 +335,20 @@ class BooksLM { return this._resolveVault(); } + /** + * Concrete vault used to browse files in the `@` mention menu. Falls back to + * the sidebar's selected context vault (then the first vault) so the menu can + * list files even in General mode where no vault is otherwise resolved. + */ + _mentionVault() { + const resolved = this._contextVault(); + if (resolved) return resolved; + const selected = state.selectedContextVault; + if (selected && selected !== 'all') return selected; + const first = Array.isArray(state.allVaults) ? state.allVaults[0] : null; + return (first && (first.name || first)) || null; + } + /** Open a file mentioned in an assistant answer in the main viewer. */ async _openFileLink(path) { const vault = this._resolveVault(); @@ -433,7 +449,9 @@ class BooksLM { return { icon: 'sparkles', title: t('ai.context_general'), - subtitle: t('ai.context_general_desc'), + // The description is kept for the tooltip only, to keep the header clean. + subtitle: '', + tooltip: t('ai.context_general_desc'), }; } @@ -468,12 +486,15 @@ class BooksLM {
+