1) Notruf-Sperre (Cooldown) gegen Mehrfach-Alarme verwirrter/verängstigter
Senioren:
- Neue Einstellung emergency_cooldown_minutes (Default 5), zur Laufzeit im
Admin-Bereich änderbar (RUNTIME_SETTABLE), 0 = aus.
- record_manual_emergency unterdrückt innerhalb der Sperre jeden weiteren
Alarm (kein zweiter Versand, kein Log-Eintrag) und liefert status=cooldown
mit minutes_ago/remaining_seconds. Neuer Endpunkt GET /api/emergency/status
für die Anzeige nach einem Seiten-Neuladen. Store: last_manual_emergency_at.
- UI: Nach dem Alarm wird der Button grün, zeigt „✓" und pulsiert für die
Dauer der Sperre. Erneuter Druck öffnet einen grünen Hinweis-Dialog:
„Ich habe Deine Helfer vor <n> Minuten alarmiert. Wahrscheinlich ist Deine
Hilfe schon unterwegs." Der grüne Zustand übersteht ein Neuladen
(Status-Abruf beim Start).
2) „Neues Gespräch" als Symbol (Stift) zurück in die Kopfzeile — zwischen
Sprachauswahl und Menü; löst dieselbe Aktion aus wie der Menüeintrag.
Tests: neue test_emergency_cooldown.py (Status/Suppression/Endpoint); zwei
bestehende Notruf-Tests an die neue Interface-Methode bzw. die Sperre
angepasst. 250 Offline-Tests grün. Frontend via Headless-Chrome verifiziert
(Alarm->grün/pulsierend, Hinweis-Dialog, Reload-Persistenz, Header-Button).
Bump app.js v=50 -> v=51.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Gegen "Blödsinn", v. a. an Handys:
1) Modell-Default base -> small + compute_type int8 (Benchmark auf der VM:
base patzt schon bei sauberem Audio "an Dienstag und 10 Uhr", small korrekt
"am Dienstag um 10 Uhr"; ~4 s/6-s-Clip, gecacht).
2) faster_whisper.transcribe mit vad_filter=True (+min_silence 500ms) und
condition_on_previous_text=False -> weniger Stille-/Kontext-Halluzinationen.
3) stt_force_language (Default True): WS-Pfad gibt die feste Zielsprache vor
statt Auto-Detect -> robust bei kurzen/verrauschten Clips. Auto-Detect +
Fremdsprachen-Übersetzung jetzt opt-in (stt_force_language=False).
Tests: Config-Defaults + VAD/Language-Durchreichung; test_ws-Übersetzung auf
opt-in umgestellt. Suite 253 grün.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Beim Notruf-Knopf wird – sofern SMTP konfiguriert ist – eine E-Mail an die
Kontaktperson(en) des Nutzers geschickt (Default: dieter.schlueter@linix.de).
Der Nutzer-Hinweis spiegelt ehrlich wider, ob wirklich etwas rausging:
"Kontaktperson per E-Mail benachrichtigt" vs. "noch keine Benachrichtigung".
- config.py: EMERGENCY_CONTACT_EMAIL + SMTP_* (ohne SMTP_HOST kein Versand);
veralteten LLM-Klassifikator-Kommentar entfernt.
- emergency.py: SMTP-Versand (best effort, im Thread), lokalisierte Hinweise
für "gesendet"/"nicht gesendet" (10 Sprachen). Pro-Nutzer-Kontakte via
prefs.emergency_contacts vorbereitet, Fallback auf Config-Default.
- Test mit gemocktem smtplib. env.example + DEPLOYMENT.md 2.5 dokumentiert.
SMS/Anruf-Eskalation folgt später (eigene Planung). 210 passed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Die unzuverlässige/intransparente Auto-Erkennung (Stichwörter + LLM) ist
ersatzlos entfernt: emergency.py neu (nur manueller, vom Nutzer bestätigter
Notruf), llm_classifier.py gelöscht, Aufrufe in chat.py/ws.py raus,
emergency_llm_* aus der Config.
Neu: prominenter "🆘 Hilfe rufen"-Knopf (Bestätigung) → POST /api/emergency
→ protokolliert + liefert Hinweis in Nutzersprache. Eskalation (Benachrichtigung
an Angehörige) folgt später; vorerst Platzhalter "ACHTUNG: Es ist noch keine
Benachrichtigung eingebaut." (10 Sprachen). Admin-Tab "Notfälle" → "Notrufe".
Tests: test_emergency_llm.py entfernt, test_quota_safety.py auf Notruf-Endpunkt
umgeschrieben. 208 passed. Live verifiziert.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sprache ist immer fest. Entfernt: language_mode aus Route/Schema/Config/
Runtime-Config, die Flex-Verzweigung in Orchestrator (effective_language =
language) und ws.py (immer normales transcribe), die "🔄 Flex"-Option im
Frontend samt zugehöriger app.js-Logik (langOverrides, loadMe, Turn-Sprache).
Die generische STT-Methode transcribe_detect bleibt als wiederverwendbare
Infrastruktur erhalten (nicht mehr aufgerufen). Test: Route trägt kein
language_mode mehr. 215 passed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Geräte-STT erkennt Sprache lokal und sendet nur Text über den Text-Turn; spart
Audio-Upload + Server-STT. Getrennter Schalter (STT ▾) unabhängig vom TTS.
- Linie C: nur bei nachweislich lokaler Erkennung (iOS / Chrome on-device); Cloud
(z. B. Chrome-Desktop -> Google) nur mit Admin-Flag ALLOW_CLOUD_STT.
-> config.allow_cloud_stt, RUNTIME_SETTABLE, /api/me, Admin-Toggle.
- Fix-only (SpeechRecognition braucht Sprach-Hint); Flex -> Server-STT-Fallback.
Kein/instabiles SpeechRecognition (z. B. Firefox) -> Server-STT. Live-Interim im
Eingabefeld. Terminal/Desktop/Laptop unverändert serverseitig (Option nur sichtbar,
wenn das Gerät lokale Erkennung bietet).
- Tests: /api/me-Flag + runtime-setzbar (169 grün). Doku §5.1.2 + §6.3.1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Loest #7. Der chatterbox-Stub wird durch eine echte Anbindung an den lokalen
Chatterbox-HTTP-Dienst ersetzt (POST /speak -> /status pollen -> GET /audio, WAV).
no_playback=true -> der Dienst spielt nicht lokal ab, liefert nur Bytes. WAV->PCM
(24 kHz, Resampling bei Bedarf). Waehlbar via tts_provider=chatterbox; piper bleibt
der schnelle Default (chatterbox ist ~echtzeit-langsam, dafuer klonbare Stimme).
- config: CHATTERBOX_BASE_URL/_VOICE/_LANG/_SPEED/_TIMEOUT; Registry verdrahtet
- Tests: gemockter httpx (Synthese, WAV/Resample, Job-Fehler, Stimmenwahl)
- Doku: README, Architektur (#7), deploy/README (GPU-Pinning per UUID, no_playback)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Discovery zeigte: YunoHost reicht den Usernamen nicht als Header durch, sondern im
signierten Cookie "yunohost.portal" (JWT, Claim "user"). Die Forward-Auth liest jetzt
die Identitaet aus Header ODER Cookie - nur von der Proxy-Quell-IP akzeptiert.
HS256-Signaturpruefung optional via TRUSTED_AUTH_JWT_SECRET (stdlib hmac, kein Dep).
- config: trusted_auth_cookie / _cookie_claim / _jwt_secret
- nginx-Vorlage + deploy/README: keine Identitaets-Header-Zeile mehr noetig; SSO-Schutz
der Subdomain ist Pflicht (sonst Spoofing)
- Tests: Cookie-Extraktion, Signaturpruefung, Proxy-IP-Trust
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- app/core/memory_extractor.py: LLM destilliert nach je N Turns dauerhafte
Fakten/Vorlieben aus dem Verlauf, dedupliziert gegen vorhandene Erinnerungen
und legt sie ab - best-effort, nicht-blockierend (Hintergrund-Task), eigener
Extraktions-Prompt (JSON, Reasoning aus), Cap-Begrenzung
- Trigger in /api/chat und /ws/voice nach dem Persistieren des Turns
- Konfig: MEMORY_EXTRACTION_ENABLED/_EVERY_N_TURNS/_MAX/_PROVIDER
- Tests: Extraktion, Dedup, kaputtes JSON, Cap, leeres Gespraech, Scheduling
- Doku: README + Architektur-Roadmap (Punkt 3 erledigt)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
PiperTTSProvider ruft das piper-Binary (--output-raw) async auf, liest die native
Sample-Rate aus der .onnx.json und resampelt per ffmpeg auf 24000 Hz (Gateway-Norm).
Nicht passende Stimmen (z. B. Cloud-Stimme 'Zephyr' aus der Route) fallen auf die
konfigurierte Default-Stimme zurueck. Damit ist eine voll-lokale Konstellation
(faster-whisper + Ollama + piper) moeglich -> keine API-Kosten, max. Datenschutz.
- config: PIPER_BIN/PIPER_VOICES_DIR/PIPER_VOICE/TTS_SAMPLE_RATE (+ .env.example)
- dependencies: piper-Factory mit Settings verdrahtet
- tests: tests/test_piper_tts.py (offline, Fake-Binary; Resample-Test skippt ohne ffmpeg);
e2e/auth-Tests nutzen jetzt einen Stub-TTS statt 'piper' als Pseudo-Stub
- docs: README, BEDIENUNGSANLEITUNG (voll-lokal-Beispiel), Architektur-Roadmap
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Store: messages-Tabelle + append_message/get_recent_messages (mit Mandanten-Schutz)
- LLMProvider.complete um history erweitert (openrouter + local bauen system+history+user)
- Orchestrator.chat_text reicht den Verlauf ans LLM weiter
- chat.py: bei session_id letzte HISTORY_MAX_MESSAGES laden, danach User-/Assistant-Turn speichern
- ohne session_id weiterhin zustandslos; ?debug zeigt history_len
- Config HISTORY_MAX_MESSAGES (Default 10)
- Tests: 32 gruen (3 neue Gedaechtnis-Tests)
- Doku aktualisiert (README, BEDIENUNGSANLEITUNG, Architektur)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>