diff --git a/BEDIENUNGSANLEITUNG.md b/BEDIENUNGSANLEITUNG.md index 14c70eb..3942272 100644 --- a/BEDIENUNGSANLEITUNG.md +++ b/BEDIENUNGSANLEITUNG.md @@ -1,4 +1,4 @@ -# Voice Assistant Gateway — Handbuch +# Alexis — Handbuch > **Zielgruppen:** 👤 Endnutzer · 🔧 Admin/Betreiber · 💻 Entwickler > @@ -68,7 +68,7 @@ funktioniert trotzdem, die Ausgabe ist dann unformatiert. ### 1.1 Überblick -Der **Voice Assistant Gateway** ist ein modulares Sprachassistenten-System. Er nimmt +**Alexis** ist ein modulares Sprachassistenten-System. Es nimmt gesprochene oder getippte Eingaben entgegen, lässt sie von einer KI beantworten und liest die Antwort vor. Die drei KI-Stufen — **Spracherkennung (STT)**, **Sprachmodell (LLM)** und **Sprachsynthese (TTS)** — sind einzeln austauschbar: lokal oder in der Cloud, diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..d7aca91 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,33 @@ +# Changelog + +Alle nennenswerten Änderungen an **Alexis**. Format lose nach [Keep a Changelog](https://keepachangelog.com/de/); +Versionierung nach [SemVer](https://semver.org/lang/de/) (prä-1.0: `0.x`). + +## [0.2.0] — 2026-06-27 + +### Geändert +- **Marke:** Produkt heißt jetzt **Alexis** (Anzeigename); technische Identifier + (Dienst, Pfade, Paketname, Konfig-/DB-Dateinamen) bleiben unverändert. +- Version wird im UI (Kopfzeile) und unter `/api/config` (`version`) angezeigt; eine + Quelle der Wahrheit ist `pyproject.toml`. + +### Hinzugefügt +- **Aufgeräumtes Vorlese-Menü:** nicht nutzbare TTS-Provider werden ausgeblendet + (statt ausgegraut). Backend liefert die fertige Sichtbarkeit (`tts_menu`), + „Im Gerät" nur auf Mobilgeräten. `/api/config` wird serverseitig gecacht + (spart die zuvor pro Seitenladen ausgelöste, kostenpflichtige OpenRouter-Probe). +- **GPU-Erkennung:** Setting `GPUS` (`auto|none|"0,1,2"`), an `CUDA_VISIBLE_DEVICES` + gekoppelt; zentrale Erkennung in `app/capabilities.py`. + +### Behoben +- **Stimm-Geschlechtswahl wirkt wieder:** `voice_gender` fehlte im `UserPrefs`-Schema + und wurde still verworfen → es kam immer die weibliche Stimme. Feld ergänzt + (+ Regressions-Test). +- **Geräte-TTS** folgt der Geschlechtswahl (Heuristik über Stimmname/voiceURI), sonst + Server-Fallback. + +## [0.1.0] + +- Erste interne Version: modulares Gateway (STT/LLM/TTS austauschbar), Profile, + Provider-Registries, Notruf-Eskalation, Auto-Erinnerungen, Admin-Panel, + Auth/SSO + Passwort-Login. diff --git a/README.md b/README.md index d28ed79..d397c09 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Voice Assistant Gateway +# Alexis — modulares Sprachassistenten-Gateway Modulares FastAPI-Gateway für einen **seniorengerechten Sprachassistenten** — cloud-first, aber hybrid/lokal betreibbar, mit austauschbaren STT-/LLM-/TTS-Providern. diff --git a/app/__init__.py b/app/__init__.py index e69de29..b0cb773 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -0,0 +1,32 @@ +"""Alexis — modulares Sprachassistenten-Gateway. + +`__version__` ist die **eine** Versionsquelle für UI/OpenAPI/`/api/config`. Sie wird +bevorzugt direkt aus `pyproject.toml` gelesen (dieses Repo ist ein editable In-Place- +Deployment unter /opt/voice-assistant, ein `pip install -e .` nach jeder Versionsänderung +entfällt damit); Fallback sind die installierten Paket-Metadaten, dann "0.0.0". +""" + +from __future__ import annotations + + +def _detect_version() -> str: + # 1) pyproject.toml im Quellbaum (maßgeblich für das In-Place-Deployment) + try: + import tomllib + from pathlib import Path + + pyproject = Path(__file__).resolve().parent.parent / "pyproject.toml" + with pyproject.open("rb") as fh: + return tomllib.load(fh)["project"]["version"] + except Exception: + pass + # 2) installierte Paket-Metadaten (gepackte Deployments ohne Quellbaum) + try: + from importlib.metadata import version + + return version("voice-assistant-gateway") + except Exception: + return "0.0.0" + + +__version__ = _detect_version() diff --git a/app/api/config.py b/app/api/config.py index 68f69e7..afa2136 100644 --- a/app/api/config.py +++ b/app/api/config.py @@ -4,6 +4,7 @@ import time import httpx from fastapi import APIRouter +from app import __version__ from app.config import settings, active_profile from app.capabilities import resolve_gpus from app.providers.tts.cartesia import _UNSUPPORTED_LANGS as _CARTESIA_UNSUPPORTED @@ -94,6 +95,7 @@ async def _build_config() -> dict: {"provider": "device", "visible": True, "client_only": True}, ] return { + "version": __version__, "profile": active_profile(), "app_env": settings.app_env, "default_route": route.as_dict(), diff --git a/app/main.py b/app/main.py index 656a04e..8a70fe4 100644 --- a/app/main.py +++ b/app/main.py @@ -7,6 +7,7 @@ from fastapi import FastAPI, Request from fastapi.staticfiles import StaticFiles from starlette.responses import RedirectResponse, JSONResponse, HTMLResponse +from app import __version__ from app.config import settings from urllib.parse import urlencode @@ -51,7 +52,7 @@ async def _lifespan(app: FastAPI): task.cancel() -app = FastAPI(title="Voice Assistant Gateway", lifespan=_lifespan) +app = FastAPI(title="Alexis", version=__version__, lifespan=_lifespan) @app.middleware("http") diff --git a/app/web/app.js b/app/web/app.js index 35800b9..fbdcc96 100644 --- a/app/web/app.js +++ b/app/web/app.js @@ -290,6 +290,8 @@ async function refreshTtsMenu() { const cfg = await fetch("/api/config", { cache: "no-store" }).then((r) => r.json()); _ttsMenu = cfg.tts_menu || null; cartesiaUnsupportedLangs = cfg.available?.cartesia_unsupported_languages || []; + const vEl = document.getElementById("app-version"); + if (vEl && cfg.version) vEl.textContent = "v" + cfg.version; } catch (e) { /* offline -> nichts verstecken */ } applyTtsVisibility(); } diff --git a/app/web/index.html b/app/web/index.html index f5cfdb8..0e9bbfb 100644 --- a/app/web/index.html +++ b/app/web/index.html @@ -3,7 +3,7 @@ - Voice Assistant + Alexis @@ -227,7 +227,7 @@
-

Voice Assistant

+

Alexis