feat: Max-Aufnahmedauer konfigurierbar + Barge-In gibt aria-core Kontext

Max-Aufnahme:
Default rauf von 2 auf 5 Minuten, in den App-Settings konfigurierbar
zwischen 1 und 30 Minuten (loadMaxRecordingMs aus AsyncStorage,
Storage-Key aria_max_recording_sec). Notbremse-Verhalten bleibt:
nach Ablauf wird die Aufnahme automatisch beendet und gesendet.

Barge-In Kontext:
Wenn der User waehrend ARIA noch redet/arbeitet eine neue Sprach-
oder Text-Nachricht sendet, geht jetzt ein 'interrupted: true' Flag
mit. Bridge praefixed den Text fuer aria-core dann mit:

  "[Hinweis: Stefan hat dich gerade unterbrochen waehrend du noch
  gesprochen oder gearbeitet hast. Folgendes ist eine Korrektur,
  Ergaenzung oder ein Themenwechsel zu deiner letzten Antwort.]"

So weiss ARIA dass die neue Message KEINE eigenstaendige Folgefrage
ist sondern auf den abgebrochenen Run bezogen. Der User sieht in
seinem Chat nur den reinen Text — der Hint geht nur an aria-core.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-06 21:58:11 +02:00
parent 406f4cb3cc
commit 31ff20c846
4 changed files with 111 additions and 18 deletions
+33 -8
View File
@@ -1235,6 +1235,7 @@ class ARIABridge:
except (TypeError, ValueError):
self._next_speed_override = None
if text:
interrupted = bool(payload.get("interrupted", False))
# Wenn Files gerade gepuffert sind (Bild + Text gleichzeitig
# gesendet), mergen wir sie zu einer einzigen Anfrage statt
# zwei separater send_to_core-Calls.
@@ -1242,8 +1243,16 @@ class ARIABridge:
if merged:
logger.info("[rvs] App-Chat (mit Anhaengen): '%s'", text[:80])
else:
logger.info("[rvs] App-Chat: '%s'", text[:80])
await self.send_to_core(text, source="app")
core_text = (
f"[Hinweis: Stefan hat dich gerade unterbrochen waehrend du noch "
f"gesprochen oder gearbeitet hast. Folgendes ist eine Korrektur, "
f"Ergaenzung oder ein Themenwechsel zu deiner letzten Antwort.] "
f"{text}"
if interrupted else text
)
logger.info("[rvs] App-Chat%s: '%s'",
" [BARGE-IN]" if interrupted else "", text[:80])
await self.send_to_core(core_text, source="app" + (" [barge-in]" if interrupted else ""))
return
if msg_type == "cancel_request":
@@ -1500,9 +1509,11 @@ class ARIABridge:
self._next_speed_override = speed if 0.1 <= speed <= 5.0 else None
except (TypeError, ValueError):
self._next_speed_override = None
logger.info("[rvs] Audio empfangen: %s, %dms, %dKB",
mime_type, duration_ms, len(audio_b64) // 1365)
asyncio.create_task(self._process_app_audio(audio_b64, mime_type))
interrupted = bool(payload.get("interrupted", False))
logger.info("[rvs] Audio empfangen: %s, %dms, %dKB%s",
mime_type, duration_ms, len(audio_b64) // 1365,
" [BARGE-IN]" if interrupted else "")
asyncio.create_task(self._process_app_audio(audio_b64, mime_type, interrupted))
elif msg_type == "stt_response":
# Antwort der whisper-bridge auf unseren stt_request
@@ -1558,8 +1569,13 @@ class ARIABridge:
_STT_REMOTE_TIMEOUT_READY_S = 45.0
_STT_REMOTE_TIMEOUT_LOADING_S = 300.0
async def _process_app_audio(self, audio_b64: str, mime_type: str) -> None:
"""App-Audio → STT → aria-core. Primaer via whisper-bridge (RVS), Fallback lokal."""
async def _process_app_audio(self, audio_b64: str, mime_type: str, interrupted: bool = False) -> None:
"""App-Audio → STT → aria-core. Primaer via whisper-bridge (RVS), Fallback lokal.
interrupted=True wenn der User waehrend ARIA noch sprach/dachte aufgenommen hat
(Barge-In). Wird als Hinweis-Praefix an aria-core mitgegeben damit ARIA die
Korrektur/Unterbrechung in den Kontext einordnen kann statt als reine
Folgefrage zu behandeln."""
# Erst Remote versuchen
text = await self._stt_remote(audio_b64, mime_type)
if text is None:
@@ -1571,8 +1587,17 @@ class ARIABridge:
if text.strip():
logger.info("[rvs] STT Ergebnis: '%s'", text[:80])
# Barge-In-Hinweis: gibt ARIA den Kontext dass sie unterbrochen wurde
# und dies eine Korrektur/Aenderung der vorherigen Anweisung sein kann.
core_text = (
f"[Hinweis: Stefan hat dich gerade unterbrochen waehrend du noch "
f"gesprochen oder gearbeitet hast. Folgendes ist eine Korrektur, "
f"Ergaenzung oder ein Themenwechsel zu deiner letzten Antwort.] "
f"{text}"
if interrupted else text
)
# ERST an aria-core senden (wichtigster Schritt)
await self.send_to_core(text, source="app-voice")
await self.send_to_core(core_text, source="app-voice" + (" [barge-in]" if interrupted else ""))
# STT-Text an RVS senden (fuer Anzeige in App + Diagnostic)
# sender="stt" damit Bridge es ignoriert (kein Loop)
try: