feat(stt-client): portail de services dans le HUD — tuiles cliquables + registre config-driven (#34)

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>
This commit is contained in:
ALI YESILKAYA 2026-06-20 22:20:11 +02:00 committed by GitHub
parent a7b5c44e82
commit 9c335d169b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 438 additions and 21 deletions

View file

@ -70,6 +70,52 @@ DEFAULT_CONFIG: dict[str, Any] = {
"enabled": True,
"local_db": str(DATA_DIR / "memory.sqlite"),
},
# Portail de services — alimente le panneau « Services » du HUD ET la commande
# vocale « ouvre <service> ». Ajouter un service = ajouter une entrée ici (ou
# un bloc [[services]] dans stt.toml, qui remplace alors toute cette liste).
# Champs : id (unique), name, url, icon (emoji), aliases (mots déclencheurs voix).
"services": [
{
"id": "ghostfolio", "name": "Ghostfolio",
"url": "http://ghostfolio.lab.local", "icon": "💰",
"aliases": ["portefeuille", "portfolio", "ghosto", "bourse", "investissements"],
},
{
"id": "grafana", "name": "Grafana",
"url": "http://grafana.lab.local", "icon": "📊",
"aliases": ["graphana", "metriques", "monitoring", "dashboard", "graphiques"],
},
{
"id": "argocd", "name": "ArgoCD",
"url": "http://argocd.lab.local", "icon": "🚢",
"aliases": ["argo", "argo cd", "deploiements", "gitops"],
},
{
"id": "n8n", "name": "n8n",
"url": "http://n8n.lab.local", "icon": "🔀",
"aliases": ["workflows", "automatisation", "nodes", "huit n huit"],
},
{
"id": "openwebui", "name": "Open WebUI",
"url": "http://openwebui.lab.local", "icon": "💬",
"aliases": ["open web ui", "webui", "chat", "llm", "interface ia"],
},
{
"id": "prometheus", "name": "Prometheus",
"url": "http://prometheus.lab.local", "icon": "🔥",
"aliases": ["prometheus", "metriques brutes", "tsdb"],
},
{
"id": "alertmanager", "name": "Alertmanager",
"url": "http://alertmanager.lab.local", "icon": "🚨",
"aliases": ["alertes", "alert manager", "alarmes"],
},
{
"id": "traefik", "name": "Traefik",
"url": "http://traefik.lab.local", "icon": "🛣️",
"aliases": ["reverse proxy", "ingress", "routeur", "proxy"],
},
],
}