# hermes-mail-browser -- Liste virtualisee OWA : limite a 5-7 mails + recherche precise dans la boite **Date** : 2026-07-24 **Sphere** : hermes-tt **Composant** : `hermes-mail-browser` (port 3110) ## Symptome Nabil avait laisse 10 mails "Dr. Nexum Veille" successifs dans l'inbox pour test. hermes-tt n'en voyait que 5, rien avant vendredi 24/07 12:07, meme en demandant `limit=20`. ## Cause racine OWA (New Outlook) utilise une liste de messages **virtualisee** : seuls les elements visibles a l'ecran (~5-7 lignes) sont reellement montes dans le DOM. `/inbox` lisait ce DOM en un seul coup (`eval_on_selector_all` sans scroll) -- peu importe le `limit` demande, il ne pouvait renvoyer que ce qui etait deja monte. Plusieurs methodes de scroll testees : - `element.scrollTop = scrollHeight` (programmatique) : **ne declenche rien** sur cette UI (scrollHeight == clientHeight en permanence, pas d'evenement de chargement). - Molette (`mouse.wheel`) : charge un peu plus mais de facon peu fiable. - **Navigation clavier (`ArrowDown` sur l'option focus)** : methode fiable -- force le composant virtualise a monter les elements suivants au fur et a mesure que le focus avance. Validee : 40 pressions ArrowDown avec accumulation/dedoublonnage ont retrouve 54 mails uniques sur une recherche qui n'en montrait que 6 au premier chargement. ## Fix Nouvelle fonction `read_listbox_items(page, target_count)` : accumule les messages par `ArrowDown` progressif (350ms entre chaque), dedoublonne par `aria-label` (cle stable), s'arrete des que `target_count` atteint ou apres 8 tours sans nouveaute (liste epuisee). Remplace la lecture ponctuelle dans `/inbox`. Consequence sur l'indexation : une liste virtualisee **demonte** les elements du haut au fur et a mesure du scroll -- un `.nth(index)` positionnel n'est donc plus stable dans le temps. Nouvelle fonction `click_option_by_position(page, index)` : accumule jusqu'a `index+1` via `read_listbox_items`, puis relocalise l'element cible par son `aria-label` (cle stable) plutot que par position DOM, avant de cliquer. Utilisee par `/message/{index}`, `/message/{index}/attachments`, `/message/{index}/attachments/{filename}/text`. ## Nouvelle capacite : recherche precise dans toute la boite Nabil avait aussi besoin de chercher un mail precis sans parcourir tout l'inbox page par page. La searchbox OWA existe (`role=searchbox`, `aria-label="Rechercher"`) et fonctionne exactement comme la liste d'inbox (meme structure `role=listbox`/`role=option`) -- memes fonctions d'accumulation reutilisees. Nouveaux endpoints : - `GET /search?q=&limit=N` -- resultats au meme format que /inbox - `GET /search/message?q=...&match=` -- ouvre le premier resultat dont le texte contient `match`, retourne le corps complet - `GET /search/message/attachments?q=...&match=...` - `GET /search/message/attachments/{filename}/text?q=...&match=...` `match` plutot qu'un index positionnel : plus robuste dans un contexte de recherche ou le volume de resultats n'est pas connu a l'avance et ou l'index d'un resultat particulier n'a pas de sens stable. ## Validation - `GET /inbox?limit=20` : 20 mails renvoyes correctement, jusqu'au 20/07 (contre 5 avant le fix, rien avant le 24/07 12:07). ~36s pour 20 items (acceptable, usage agent ponctuel). - `GET /search?q=Dr. Nexum Veille&limit=8` : 8 resultats corrects en ~24s. - Test de non-regression : `/inbox` sans parametre reste identique a avant (retro-compatible avec l'usage existant de hermes-tt). ## Incident collateral Pendant le rebuild/redeploiement du conteneur, hermes-tt (via Nabil) a teste l'ancienne hypothese de parametre `search=` (au lieu de `q=`) sur `/search`, echouant avec une reponse vide -- rapporte comme "l'application ne fonctionne pas". Cause reelle : le skill `mail-o365-tt.md` n'avait pas encore ete mis a jour avec le bon contrat d'API au moment du test. Le skill a ete complete (sections "Naviguer dans les dossiers" et "Rechercher un mail avec precision") et hermes-agent-tt redemarre pour recharger le fichier -- healthy et skill a jour depuis. ## Fichiers modifies `/volume1/docker/hermes-mail-browser/app/main.py` (backup : `main.py.bak_20260724_search_scroll` et `main.py.bak_20260724_folders`). `/volume1/docker/hermes-platform/hermes-tt/data/skills/mail-o365-tt.md` (backup : `mail-o365-tt.md.bak_20260724_final`).