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:
|
||||
pass # Kein ALSA - kein Problem
|
||||
|
||||
import json
|
||||
import yaml
|
||||
import click
|
||||
from rich.console import Console
|
||||
|
|
@ -107,6 +108,7 @@ class ClaudesEyesAudioBridge:
|
|||
|
||||
# State
|
||||
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()
|
||||
|
||||
# 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
|
||||
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():
|
||||
logger.error(f"Config nicht gefunden: {path}")
|
||||
sys.exit(1)
|
||||
|
|
@ -157,6 +162,57 @@ class ClaudesEyesAudioBridge:
|
|||
with open(path, 'r', encoding='utf-8') as 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):
|
||||
"""
|
||||
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
|
||||
if self.chat.wait_for_ready_signal(timeout=300): # 5 Minuten max
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
# WICHTIG: Markiere die letzte Nachricht BEVOR TTS aktiviert wird
|
||||
# So werden alle bisherigen Nachrichten (inkl. [READY]) ignoriert
|
||||
# Chat-ID ermitteln und gespeicherten TTS-State laden
|
||||
# ════════════════════════════════════════════════════════════════
|
||||
last_msg = self.chat.get_last_assistant_message()
|
||||
if last_msg:
|
||||
self.last_assistant_message_id = last_msg.id
|
||||
logger.info(f"TTS startet nach Nachricht: {last_msg.id[:30]}...")
|
||||
current_url = self.chat.get_current_chat_url()
|
||||
self._current_chat_id = self.chat.extract_chat_id(current_url)
|
||||
|
||||
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:
|
||||
# Fallback: Generiere eine Dummy-ID die niemals matcht
|
||||
self.last_assistant_message_id = f"init_{time.time()}"
|
||||
logger.info("Keine letzte Nachricht gefunden, TTS startet frisch")
|
||||
# Keine Chat-ID (neuer Chat?) - nutze letzte Nachricht
|
||||
last_msg = self.chat.get_last_assistant_message()
|
||||
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
|
||||
self._tts_active.set()
|
||||
|
|
@ -668,6 +743,10 @@ Erst dann starten die automatischen TICKs mit Bildern!"""
|
|||
if msg.is_from_assistant:
|
||||
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
|
||||
speech_text = self._clean_for_speech(msg.text)
|
||||
logger.debug(f"TTS: Nach Bereinigung: {len(speech_text) if speech_text else 0} Zeichen")
|
||||
|
|
|
|||
Loading…
Reference in New Issue