bridge liest nur nachrichten vor wo claude sagt: drin vorkommt und merkt sich welche schon vorgelesen wurden beim bridge neustart
This commit is contained in:
parent
aab93958f8
commit
d9b1e1bed4
|
|
@ -40,6 +40,7 @@ try:
|
||||||
except:
|
except:
|
||||||
pass # Kein ALSA - kein Problem
|
pass # Kein ALSA - kein Problem
|
||||||
|
|
||||||
|
import json
|
||||||
import yaml
|
import yaml
|
||||||
import click
|
import click
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
@ -107,6 +108,7 @@ class ClaudesEyesAudioBridge:
|
||||||
|
|
||||||
# State
|
# State
|
||||||
self.last_assistant_message_id: Optional[str] = None
|
self.last_assistant_message_id: Optional[str] = None
|
||||||
|
self._current_chat_id: Optional[str] = None # Aktuelle Chat-ID für TTS-State
|
||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
|
|
||||||
# Ready-Flag: Heartbeat UND TTS warten bis Claude [READY] gesendet hat
|
# Ready-Flag: Heartbeat UND TTS warten bis Claude [READY] gesendet hat
|
||||||
|
|
@ -150,6 +152,9 @@ class ClaudesEyesAudioBridge:
|
||||||
# Merke den tatsächlichen Pfad für späteres Speichern
|
# Merke den tatsächlichen Pfad für späteres Speichern
|
||||||
self._actual_config_path = path
|
self._actual_config_path = path
|
||||||
|
|
||||||
|
# Pfad für TTS-State (vorgelesene Nachrichten)
|
||||||
|
self._tts_state_path = path.parent / ".tts_state.json"
|
||||||
|
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
logger.error(f"Config nicht gefunden: {path}")
|
logger.error(f"Config nicht gefunden: {path}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
@ -157,6 +162,57 @@ class ClaudesEyesAudioBridge:
|
||||||
with open(path, 'r', encoding='utf-8') as f:
|
with open(path, 'r', encoding='utf-8') as f:
|
||||||
return yaml.safe_load(f)
|
return yaml.safe_load(f)
|
||||||
|
|
||||||
|
def _load_tts_state(self, chat_id: str) -> Optional[str]:
|
||||||
|
"""
|
||||||
|
Lädt die zuletzt vorgelesene Nachricht-ID für einen Chat.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id: Die Chat-ID (aus der URL)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Die zuletzt vorgelesene Nachricht-ID oder None
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if self._tts_state_path.exists():
|
||||||
|
with open(self._tts_state_path, 'r', encoding='utf-8') as f:
|
||||||
|
state = json.load(f)
|
||||||
|
last_id = state.get(chat_id)
|
||||||
|
if last_id:
|
||||||
|
logger.info(f"TTS-State geladen für Chat {chat_id[:20]}...: {last_id[:30]}...")
|
||||||
|
return last_id
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Konnte TTS-State nicht laden: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _save_tts_state(self, chat_id: str, message_id: str):
|
||||||
|
"""
|
||||||
|
Speichert die zuletzt vorgelesene Nachricht-ID für einen Chat.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
chat_id: Die Chat-ID (aus der URL)
|
||||||
|
message_id: Die Nachricht-ID die zuletzt vorgelesen wurde
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Existierenden State laden oder leeren dict
|
||||||
|
state = {}
|
||||||
|
if self._tts_state_path.exists():
|
||||||
|
try:
|
||||||
|
with open(self._tts_state_path, 'r', encoding='utf-8') as f:
|
||||||
|
state = json.load(f)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# State aktualisieren
|
||||||
|
state[chat_id] = message_id
|
||||||
|
|
||||||
|
# Speichern
|
||||||
|
with open(self._tts_state_path, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(state, f, indent=2)
|
||||||
|
|
||||||
|
logger.debug(f"TTS-State gespeichert: {chat_id[:20]}... -> {message_id[:30]}...")
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Konnte TTS-State nicht speichern: {e}")
|
||||||
|
|
||||||
def _save_chat_url_to_config(self, new_url: str):
|
def _save_chat_url_to_config(self, new_url: str):
|
||||||
"""
|
"""
|
||||||
Speichert die neue Chat-URL in der config.yaml.
|
Speichert die neue Chat-URL in der config.yaml.
|
||||||
|
|
@ -472,17 +528,36 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
|
||||||
# Heartbeat startet NUR wenn Claude wirklich [READY] sendet
|
# Heartbeat startet NUR wenn Claude wirklich [READY] sendet
|
||||||
if self.chat.wait_for_ready_signal(timeout=300): # 5 Minuten max
|
if self.chat.wait_for_ready_signal(timeout=300): # 5 Minuten max
|
||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
# WICHTIG: Markiere die letzte Nachricht BEVOR TTS aktiviert wird
|
# Chat-ID ermitteln und gespeicherten TTS-State laden
|
||||||
# So werden alle bisherigen Nachrichten (inkl. [READY]) ignoriert
|
|
||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
last_msg = self.chat.get_last_assistant_message()
|
current_url = self.chat.get_current_chat_url()
|
||||||
if last_msg:
|
self._current_chat_id = self.chat.extract_chat_id(current_url)
|
||||||
self.last_assistant_message_id = last_msg.id
|
|
||||||
logger.info(f"TTS startet nach Nachricht: {last_msg.id[:30]}...")
|
if self._current_chat_id:
|
||||||
|
# Versuche gespeicherten State zu laden
|
||||||
|
saved_id = self._load_tts_state(self._current_chat_id)
|
||||||
|
if saved_id:
|
||||||
|
self.last_assistant_message_id = saved_id
|
||||||
|
console.print(f"[green]TTS: Setze fort ab gespeicherter Position[/green]")
|
||||||
|
logger.info(f"TTS setzt fort nach: {saved_id[:30]}...")
|
||||||
|
else:
|
||||||
|
# Kein gespeicherter State - starte nach [READY] Nachricht
|
||||||
|
last_msg = self.chat.get_last_assistant_message()
|
||||||
|
if last_msg:
|
||||||
|
self.last_assistant_message_id = last_msg.id
|
||||||
|
self._save_tts_state(self._current_chat_id, last_msg.id)
|
||||||
|
logger.info(f"TTS startet nach READY-Nachricht: {last_msg.id[:30]}...")
|
||||||
|
else:
|
||||||
|
self.last_assistant_message_id = f"init_{time.time()}"
|
||||||
|
logger.info("Keine letzte Nachricht gefunden, TTS startet frisch")
|
||||||
else:
|
else:
|
||||||
# Fallback: Generiere eine Dummy-ID die niemals matcht
|
# Keine Chat-ID (neuer Chat?) - nutze letzte Nachricht
|
||||||
self.last_assistant_message_id = f"init_{time.time()}"
|
last_msg = self.chat.get_last_assistant_message()
|
||||||
logger.info("Keine letzte Nachricht gefunden, TTS startet frisch")
|
if last_msg:
|
||||||
|
self.last_assistant_message_id = last_msg.id
|
||||||
|
else:
|
||||||
|
self.last_assistant_message_id = f"init_{time.time()}"
|
||||||
|
logger.info("Keine Chat-ID, TTS startet frisch")
|
||||||
|
|
||||||
# Jetzt TTS und Heartbeat aktivieren
|
# Jetzt TTS und Heartbeat aktivieren
|
||||||
self._tts_active.set()
|
self._tts_active.set()
|
||||||
|
|
@ -668,6 +743,10 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
|
||||||
if msg.is_from_assistant:
|
if msg.is_from_assistant:
|
||||||
self.last_assistant_message_id = msg.id
|
self.last_assistant_message_id = msg.id
|
||||||
|
|
||||||
|
# State speichern (persistent)
|
||||||
|
if self._current_chat_id:
|
||||||
|
self._save_tts_state(self._current_chat_id, msg.id)
|
||||||
|
|
||||||
# Text für Sprache aufbereiten
|
# Text für Sprache aufbereiten
|
||||||
speech_text = self._clean_for_speech(msg.text)
|
speech_text = self._clean_for_speech(msg.text)
|
||||||
logger.debug(f"TTS: Nach Bereinigung: {len(speech_text) if speech_text else 0} Zeichen")
|
logger.debug(f"TTS: Nach Bereinigung: {len(speech_text) if speech_text else 0} Zeichen")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue