diff --git a/admin/ia/stt.md b/admin/ia/stt.md index cf1d506..a1b08ec 100644 --- a/admin/ia/stt.md +++ b/admin/ia/stt.md @@ -14,9 +14,9 @@ Objectif ultérieur : « agir sur le homelab » via les outils de Hermes (phase > (5e). > ✅ **2026-06-18** — HUD avancé (4) + auto-start (6). HUD : design **Claude Design** (avatar > portrait réactif, transcript à bulles, drawer Réglages **câblé au backend** : reset / mode -> cerveau / mot de réveil à chaud). Auto-start : `stt --install-service` (systemd --user, -> `graphical-session.target`). Reste : test audio bout-en-bout (phase 1), portraits réels + -> test sur cible, outils Hermes (7). +> cerveau / mot de réveil à chaud). Auto-start : `stt --install-service` (systemd --user). +> App de bureau : `stt --install-desktop` (fenêtre type Discord) ; auto-update : `stt --update`. +> Reste : test audio bout-en-bout (phase 1), portraits réels + test sur cible, outils Hermes (7). --- @@ -182,6 +182,36 @@ la session graphique démarre au boot et tire le service. --- +## Application de bureau & mise à jour + +**Lancer STT comme une appli** (fenêtre dédiée type Discord, pas un onglet) : + +```bash +stt --install-desktop # entrée de menu (.desktop) + icône → épinglable au dock +stt --uninstall-desktop # la retirer +``` + +Le lanceur exécute `stt --window app` : le HUD s'ouvre en fenêtre *chromeless* (`--app=` de +Chromium/Brave). Modes via `--window` ou `[ui].window_mode` : `app` (fenêtre), `kiosk` (plein +écran, défaut du service), `none` (n'ouvre rien). L'icône est `stt/hud/icon.svg` (aussi favicon). + +> ⚠️ Le lanceur de bureau et le service systemd (kiosk) utilisent les **mêmes ports** (9300/9301) : +> n'en faire tourner qu'un à la fois. Borne dédiée → service kiosk ; usage à la demande → lanceur +> de bureau (et `stt --uninstall-service`). + +**Mettre à jour** (sans désinstaller/réinstaller à la main) : + +```bash +stt --update # pipx reinstall depuis la source git (via ta clé SSH) — affiche ancienne → nouvelle +stt --version # version installée +``` + +`--update` re-récupère la dernière version depuis la branche/source d'installation. Pré-requis : +avoir installé via `pipx` depuis git. Astuce : toujours bumper la version du paquet à chaque +release, sinon le cache de build pipx/uv peut resservir l'ancienne (cf. `pyproject.toml`). + +--- + ## Roadmap | Phase | Objectif | État | diff --git a/stt/README.md b/stt/README.md index 5de1e58..849b2a5 100644 --- a/stt/README.md +++ b/stt/README.md @@ -31,6 +31,9 @@ stt --text # chat texte simple (sans micro ni HUD) — idéal pour t stt # voix + HUD ; dis "Ok Hermès …" stt --model claude # choisir le modèle : hermes (défaut) | claude | qwen | opus stt --install-service # auto-start au login (systemd --user, kiosk « écran Jarvis ») +stt --install-desktop # ajoute STT au menu des applis → fenêtre dédiée (type Discord) +stt --window app # ouvre le HUD en fenêtre app (sinon : kiosk plein écran) +stt --update # met à jour depuis git (plus de désinstall/réinstall manuel) ``` En mode texte : commandes `/model `, `/models`, `/quit`. Prérequis voix : micro, Piper + voix dans `~/.local/share/piper/`, `aplay` (alsa-utils). diff --git a/stt/client/config/stt.example.toml b/stt/client/config/stt.example.toml index f93b116..9d2e0d5 100644 --- a/stt/client/config/stt.example.toml +++ b/stt/client/config/stt.example.toml @@ -23,7 +23,8 @@ chat_timeout_sec = 60 [ui] theme = "arc-reactor" avatar = "default" -kiosk = true # ouvre le HUD en plein écran (kiosk) au lancement +kiosk = true # (compat) plein écran si window_mode absent +window_mode = "kiosk" # "app" (fenêtre, type Discord) | "kiosk" (plein écran) | "none" ws_host = "127.0.0.1" ws_port = 9300 # websocket états ↔ HUD (doit matcher hud/index.html) http_port = 9301 # HTTP statique qui sert le HUD diff --git a/stt/client/pyproject.toml b/stt/client/pyproject.toml index 1622990..46b9ae0 100644 --- a/stt/client/pyproject.toml +++ b/stt/client/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "stt" -version = "0.3.0" +version = "0.4.0" description = "STT — client vocal Jarvis du homelab Funk (voix + HUD, parle au STT-server)" requires-python = ">=3.11" readme = "README.md" diff --git a/stt/client/stt/cli.py b/stt/client/stt/cli.py index 8e3f945..694f57c 100644 --- a/stt/client/stt/cli.py +++ b/stt/client/stt/cli.py @@ -109,6 +109,106 @@ def _cmd_uninstall_service() -> int: return 0 +def _desktop_entry(stt_bin: str, icon_path: str) -> str: + """Contenu du lanceur .desktop : STT comme application de bureau (fenêtre app).""" + return f"""[Desktop Entry] +Type=Application +Name=STT — Assistant vocal +GenericName=Assistant vocal +Comment=Assistant vocal Jarvis du homelab Funk +Exec={stt_bin} --window app +Icon={icon_path} +Terminal=false +Categories=Utility;AudioVideo; +Keywords=jarvis;assistant;voix;hermes; +StartupNotify=true +""" + + +def _cmd_install_desktop() -> int: + """Crée l'entrée de menu (.desktop) + icône → STT lançable comme une appli (type Discord).""" + import shutil + import subprocess + from pathlib import Path + + stt_bin = shutil.which("stt") or os.path.realpath(sys.argv[0]) + icon_path = Path(__file__).resolve().parent / "hud" / "icon.svg" + apps_dir = Path.home() / ".local" / "share" / "applications" + apps_dir.mkdir(parents=True, exist_ok=True) + entry = apps_dir / "stt.desktop" + entry.write_text(_desktop_entry(stt_bin, str(icon_path))) + entry.chmod(0o755) + subprocess.run(["update-desktop-database", str(apps_dir)], check=False) + + print(f"✓ Lanceur : {entry}") + print(f" Icône : {icon_path}") + print(f" Exec : {stt_bin} --window app") + print("\nSTT apparaît dans le menu des applications (épinglable au dock).") + print("Il s'ouvre en fenêtre « app » (sans onglets), comme Discord.") + print("Retirer : stt --uninstall-desktop") + return 0 + + +def _cmd_uninstall_desktop() -> int: + """Supprime le lanceur de bureau.""" + import subprocess + from pathlib import Path + + entry = Path.home() / ".local" / "share" / "applications" / "stt.desktop" + if entry.exists(): + entry.unlink() + print(f"✓ Lanceur supprimé : {entry}") + else: + print("(lanceur déjà absent)") + subprocess.run(["update-desktop-database", str(entry.parent)], check=False) + return 0 + + +def _installed_version() -> str | None: + from importlib.metadata import PackageNotFoundError, version + + try: + return version("stt") + except PackageNotFoundError: + return None + + +def _cmd_version() -> int: + print(_installed_version() or "version inconnue (pas installé via pip/pipx)") + return 0 + + +def _cmd_update() -> int: + """Met à jour STT depuis sa source git (pipx reinstall) — sans désinstall/réinstall manuel.""" + import re + import shutil + import subprocess + + pipx = shutil.which("pipx") + if not pipx: + print("pipx introuvable — mise à jour automatique impossible.") + print("Réinstalle manuellement depuis la source git.") + return 1 + before = _installed_version() + if before: + print(f"Version installée : {before}") + print("Récupération de la dernière version depuis git (pipx reinstall)…\n") + res = subprocess.run([pipx, "reinstall", "stt"], capture_output=True, text=True) + out = ((res.stdout or "") + (res.stderr or "")).strip() + if out: + print(out) + m = re.search(r"installed package stt ([0-9][^\s,]*)", out) + after = m.group(1) if m else None + print() + if after and before and after != before: + print(f"✓ Mis à jour : {before} → {after}") + elif after: + print(f"✓ Déjà à jour ({after}).") + else: + print("✓ Réinstallation terminée — vérifie avec : stt --version") + return res.returncode + + def _make_client(args): from stt.api import ServerClient from stt.config import load_config, resolve_model @@ -172,6 +272,11 @@ def _cmd_voice(args) -> int: from stt.voice import VoiceEngine cfg, client = _make_client(args) + # mode d'ouverture du HUD : --window > config window_mode > kiosk (compat) > none + ui = cfg["ui"] + ui["window_mode"] = ( + args.window or ui.get("window_mode") or ("kiosk" if ui.get("kiosk") else "none") + ) print(f"STT-server : {client.url} — modèle '{client.model}'") if not client.healthy(): print(" ⚠️ serveur injoignable — vérifie [server] url et le réseau") @@ -203,18 +308,35 @@ def main(argv: list[str] | None = None) -> int: p.add_argument("--model", help="Modèle : hermes, claude, qwen, opus (ou alias LiteLLM)") p.add_argument("--server", help="Force l'URL du STT-server (sinon config)") p.add_argument("--no-tts", action="store_true", help="Réponses texte seulement (voix)") + p.add_argument("--window", choices=["app", "kiosk", "none"], + help="Ouverture du HUD : app (fenêtre, type Discord) | kiosk (plein écran) | none") p.add_argument("--install-service", action="store_true", help="Installe le service systemd --user (auto-start au login + kiosk)") p.add_argument("--uninstall-service", action="store_true", help="Désinstalle le service systemd --user") + p.add_argument("--install-desktop", action="store_true", + help="Crée le lanceur de bureau (.desktop + icône) — appli type Discord") + p.add_argument("--uninstall-desktop", action="store_true", + help="Supprime le lanceur de bureau") + p.add_argument("--update", action="store_true", + help="Met à jour STT depuis git (pipx reinstall)") + p.add_argument("--version", action="store_true", help="Affiche la version installée") args = p.parse_args(argv) + if args.version: + return _cmd_version() if args.setup: return _cmd_setup() + if args.update: + return _cmd_update() if args.install_service: return _cmd_install_service() if args.uninstall_service: return _cmd_uninstall_service() + if args.install_desktop: + return _cmd_install_desktop() + if args.uninstall_desktop: + return _cmd_uninstall_desktop() if args.text: return _cmd_text(args) return _cmd_voice(args) diff --git a/stt/client/stt/config.py b/stt/client/stt/config.py index 2d79f8e..dfde4e5 100644 --- a/stt/client/stt/config.py +++ b/stt/client/stt/config.py @@ -52,6 +52,9 @@ DEFAULT_CONFIG: dict[str, Any] = { "theme": "arc-reactor", "avatar": "default", "kiosk": True, + # window_mode : "app" (fenêtre type Discord) | "kiosk" (plein écran) | "none". + # Si absent, repli sur kiosk ci-dessus (compat). + "window_mode": "kiosk", "ws_host": "127.0.0.1", "ws_port": 9300, "http_port": 9301, diff --git a/stt/client/stt/hud/icon.svg b/stt/client/stt/hud/icon.svg new file mode 100644 index 0000000..cc47662 --- /dev/null +++ b/stt/client/stt/hud/icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/stt/client/stt/hud/index.html b/stt/client/stt/hud/index.html index 177da6a..b8f2820 100644 --- a/stt/client/stt/hud/index.html +++ b/stt/client/stt/hud/index.html @@ -4,6 +4,7 @@ STT — Assistant vocal +