Deux features mergées n'avaient pas atteint main (effet de bord des PR empilées :
#37 a été mergé dans sa branche de base supprimée, jamais propagé). Recollées proprement
sur main à jour, en fusionnant engine._respond / app.py avec le travail contextes (#39).
Intents vocaux (lecture seule, court-circuitent le LLM) :
- portal/intents.py + ghostfolio.py (récupérés) + exports __init__.
- engine.py : intent_router AVANT le LLM ; cohabite avec context_provider
(pas de contexte émis sur un intent local).
- app.py : construit le routeur (services, ouverture, santé, Ghostfolio).
- config : section [ghostfolio] + doc example.toml.
Affichage version :
- app.py : meta_msg poussé à la connexion.
- hud : case 'meta' + setVersion + ligne « Version installée » (section Service).
- bump 0.11.0 → 0.12.0.
Validé : compile, routage intents, coexistence intent/visualiseur dans _respond
(intent → mode portail sans contexte ; LLM → contexte émis), HUD (meta/version).
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Moitié client de la fonctionnalité contextes (le serveur #38 est déployé). Tu choisis
un contexte pour Asa et tu vois exactement ce qu'on lui envoie.
- Sélecteur (Réglages → « Contexte d'Asa ») : liste peuplée depuis GET /v1/contexts ;
le choix est envoyé en settings{context}, persisté en localStorage, et réappliqué au
backend à la connexion. Masqué si le serveur ne supporte pas (dégradation).
- Visualiseur (icône ▤ de la barre) : drawer affichant le contexte assemblé renvoyé
après chaque tour — consigne (system prompt), données live injectées, doc RAG, mémoire.
- api.py : ServerClient envoie `context`, expose last_context + contexts().
- engine.py : context_provider → émet {type:context} après chaque réponse.
- app.py : récupère /v1/contexts au démarrage, diffuse à la connexion, applique le
changement de contexte (client.context).
- bump 0.10.0 → 0.11.0.
Validé via Playwright : sélecteur (5 contextes), changement → settings{context},
visualiseur (consigne + bloc live Ghostfolio + mémoire), drawer partagé. Rendu conforme.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute la gestion du service STT directement depuis l'interface (Réglages →
section « Service ») et deux commandes CLI.
- CLI : `stt --start` (démarre le service) et `stt --restart` (recharge la config :
modèle ASR, wake word…). Garde-fou si le unit n'est pas installé.
- HUD : boutons Redémarrer / Mettre à jour / Arrêter. Le HUD tournant DANS le
service, les actions sont lancées en process détaché (start_new_session) → le
redémarrage va à son terme même quand le process courant est tué (systemd
possède le job). « Mettre à jour » = `stt --update` puis `stt --restart`.
- bump 0.8.0 → 0.9.0.
Validé : py_compile, --start/--restart dans l'aide, et HUD via Playwright
(3 boutons émettent service-restart/-update/-stop, toast, aucune erreur JS,
rendu conforme).
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute un panneau « Services » au HUD du client STT : une tuile par service du
homelab (Ghostfolio, Grafana, ArgoCD, n8n, Open WebUI, Prometheus, Alertmanager,
Traefik), un clic ouvre l'URL dans le navigateur habituel.
- stt/portal/ : registre piloté par [[services]] de stt.toml (id, name, url, icon,
aliases) + résolution floue (registry.match_service) prête pour la voix.
Ajouter un service = quelques lignes de config, zéro code.
- config.py : défauts homelab + doc dans stt.example.toml.
- ui/app.py : pousse la liste au HUD à la connexion, action de contrôle
open-service → _open_url_external (xdg-open, session navigateur normale) + toast.
- hud/index.html : bouton header, drawer Services (voile partagé avec Réglages),
grille de tuiles, toast de confirmation.
- bump 0.7.0 → 0.8.0.
Validé : registre (fuzzy-match FR/fautes/négatif), wiring backend, et HUD via
Playwright (rendu tuiles + clic émet open-service + toast, aucune erreur JS).
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
`_running_stt_pids` ne regardait que argv[0], or pipx lance
`python -E /…/bin/stt --window app` → argv[0] est l'interpréteur, pas `stt`
(et le `-E` décale encore le chemin). Du coup `stt --stop` ne trouvait jamais
l'instance vocale (« Aucun service ni instance en cours ») alors qu'elle
tournait — confirmé en conditions réelles.
Désormais on cherche un token qui est un *chemin* vers `stt` (slash + basename
`stt`) dans toute la ligne de commande, ce qui écarte aussi le `stt` nu d'un
`journalctl -u stt` (faux positif), et on ignore toujours les sous-commandes
utilitaires.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* fix(rag): exclure hermes/builtin de l'index funk-docs
Les rapports auto-générés par hermes-auto-improve (admin/hermes/builtin/,
"ne pas éditer") représentaient ~84% des points de la collection et noyaient
la vraie doc → rag-query remontait du bruit. On les élague à l'ingestion
(os.walk), surchargeable via RAG_EXCLUDE. Collection re-bâtie : 403 points
propres (0 builtin), rag-query remonte de nouveau les bons documents.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* feat(stt-client): boutons stop réponse + mute micro (HUD) + `stt --stop`
HUD : deux contrôles dans la barre du haut.
- « stop » coupe la réponse en cours — interrompt la lecture TTS (kill aplay)
et saute la synthèse si pressé pendant la génération (Event _interrupt).
- « micro » coupe/réactive l'entrée audio (la boucle VAD ignore les trames) ;
l'état fait foi côté backend, renvoyé au HUD via {"type":"mic"} (ré-émis à
la connexion d'un nouveau client).
Protocole WS : nouveau message {"type":"control","action":"stop|mute|unmute"}.
CLI : `stt --stop` éteint le service — systemd --user (stt.service) si actif,
sinon SIGTERM aux process vocaux trouvés via /proc (s'exclut + ignore les
sous-commandes utilitaires).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* feat(stt): auto-start via `stt --install-service` (phase 6)
Ajoute `stt --install-service` / `--uninstall-service` : génère et active un
service systemd --user (lié à graphical-session.target) qui lance le HUD + voix
à l'ouverture de session. Le kiosk existant (ui.kiosk) fournit l'« écran Jarvis ».
- cli : _service_unit (génération du unit, fonction pure testable),
_cmd_install_service (écrit le unit + import-environment DISPLAY/WAYLAND +
daemon-reload/enable/start), _cmd_uninstall_service.
- Docs : admin/ia/stt.md (phase 6 → ✅, section Auto-start + caveat DISPLAY),
stt/README.
- Bump client 0.2.1 → 0.3.0.
Phase 6 de la roadmap STT. Reste : test sur poste, outils Hermes (7).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa
* feat(stt): app de bureau (fenêtre type Discord) + auto-update
Rend STT lançable comme une application de bureau et ajoute la mise à jour intégrée.
- Mode fenêtre « app » : _open_browser ouvre le HUD en fenêtre chromeless
(--app=, type Discord) en plus du kiosk plein écran ; support Brave ajouté.
Sélection via --window {app,kiosk,none} ou [ui].window_mode.
- stt --install-desktop / --uninstall-desktop : entrée .desktop + icône
(stt/hud/icon.svg, aussi favicon du HUD) → STT dans le menu/dock, lance --window app.
- stt --update : pipx reinstall depuis la source git (via clé SSH), affiche
« ancienne → nouvelle » ; stt --version.
- Docs (admin/ia/stt.md, stt/README) + config (window_mode) + bump 0.3.0 → 0.4.0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa
* fix(stt): détection navigateur cross-distro (AlmaLinux/Fedora + Debian/Ubuntu)
_open_browser tente les binaires natifs (rpm + deb : brave-browser / chromium /
chromium-browser / google-chrome…) puis Flatpak (com.brave.Browser,
org.chromium.Chromium, com.google.Chrome…), sinon repli sur le navigateur par
défaut. systemd --user, lanceurs .desktop et pipx sont déjà identiques sur les
deux familles.
Doc : note de compatibilité distros. Bump 0.4.0 → 0.4.1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa
* docs(stt): journal 2026-06-18 + PROGRESS + ligne STT du CLAUDE.md
- progress/2026-06-18.md : HUD avancé, auto-start, app de bureau, auto-update, cross-distro
- PROGRESS.md : entrée du jour
- CLAUDE.md : ligne STT enrichie (HUD, auto-start, app de bureau, auto-update)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa
* feat(stt): fenêtre app autonome (profil + WM class dédiés, hors session Brave)
Le mode app s'attachait à la session Brave de l'utilisateur (même profil/icône) →
« ça sent le Brave ». On lance désormais une instance séparée : --class=STT-Funk
+ --user-data-dir dédié (~/.local/share/stt/app-profile), et le .desktop déclare
StartupWMClass=STT-Funk → fenêtre autonome avec sa propre icône de barre des tâches.
(Flatpak : --class seul, sandbox.) Une vraie fenêtre native (pywebview) reste une
option ultérieure. Bump 0.4.1 → 0.4.2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa
---------
Co-authored-by: Claude <noreply@anthropic.com>
* feat(stt): HUD avancé — design Claude Design câblé au backend
Remplace le HUD minimal (cercle CSS) par le design Claude Design : avatar
portrait réactif (anneau + ping d'écoute + spinner de réflexion), transcript
à bulles (tag modèle), indicateur de connexion + reconnexion auto, et un
drawer Réglages.
- HUD (stt/hud/index.html) : HTML/CSS/JS sans dépendance externe, DEMO=false
branché sur le websocket existant (états idle/listening/thinking/speaking,
user/assistant/error). Portraits chargés depuis hud/avatars/ (repli « あ »
si absent — voir avatars/README.md).
- Backend (ui/app.py) : le HUD renvoie {"type":"settings",...} ; le serveur
applique à chaud reset / mode cerveau (modèle LiteLLM) / mot de réveil via
_apply_settings (best-effort, non bloquant).
- engine/cli : tag du modèle courant ajouté aux réponses (events assistant).
- Docs : hud/README + avatars/README + admin/ia/stt.md (phase 4 ✅) + config.
Phase 4 de la roadmap STT. Reste : test sur poste + portraits réels.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa
* fix(stt): HUD servi sans cache navigateur (anti ancienne version)
Le HUD est un dashboard live servi en statique : sans en-tête anti-cache, le
navigateur garde l'ancien index.html après mise à jour (« je vois encore la
version bleue »). Ajoute Cache-Control: no-store + Pragma: no-cache via un
handler dédié, et silence le log HTTP par requête.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa
* chore(stt): bump client 0.1.0 → 0.2.0 (HUD avancé)
La version inchangée faisait que pipx/uv réutilisait l'ancien build en cache
lors d'un réinstall (HUD bleu persistant malgré le nouveau code). Le bump force
une résolution propre vers la nouvelle version (HUD design Claude Design).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa
* fix(stt): cache-bust de l'URL HUD en kiosk + bump 0.2.1
Ouvre le HUD avec ?v=<timestamp> (URL unique par lancement) pour que le
navigateur ne puisse jamais servir une version cachée de l'ancien HUD.
Complète Cache-Control: no-store côté serveur.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Qjq5jHiqNepnobJpHYpCa
---------
Co-authored-by: Claude <noreply@anthropic.com>
Serveur : SessionStore (historique borné + TTL, en mémoire), /v1/ask accepte session_id
et injecte l'historique dans l'appel LLM, /v1/reset l'efface. Dockerfile en 1 worker
(cohérence mémoire process).
Client : session_id généré par run (uuid), envoyé à chaque requête ; commande /reset
en mode texte.
Testé en process (TestClient) : historique croît 0→2→4, reset→0, sessions isolées,
sans session_id = sans état.
Mémoire long-terme Qdrant (5b) + réparation Qdrant (5c) à suivre.
Claude-Session: https://claude.ai/code/session_013FmcxGsyXZXogiAHQLjnZT
Co-authored-by: Claude <noreply@anthropic.com>
Serveur : /v1/ask accepte un model optionnel (validé contre STT_ALLOWED_MODELS),
nouvel endpoint GET /v1/models (défaut + alias autorisés). Pas de switch global.
Client : 'stt --text' (chat texte simple sans micro/HUD), '--model hermes|claude|qwen|opus'
(noms courts → alias LiteLLM), commandes /model et /models en mode texte. Le modèle
choisi est envoyé au serveur à chaque requête (voix comme texte).
Claude-Session: https://claude.ai/code/session_013FmcxGsyXZXogiAHQLjnZT
Co-authored-by: Claude <noreply@anthropic.com>