From 15facf48eb81297b5ea76500235e2c29c1712508 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Fri, 15 May 2026 08:50:46 +0200 Subject: [PATCH] =?UTF-8?q?fix(bridge):=20send=5Fto=5Fcore=20als=20create?= =?UTF-8?q?=5Ftask=20=E2=80=94=20RVS-recv=20blockt=20nicht=20mehr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Live-Diagnose nach dem Timeout-Bump: Bridge-Brain-Call rennt jetzt zwar 20 Min — aber nach ~4 Min droppt der RVS-Server die WebSocket-Verbindung. Symptom in App+Diagnostic: "denkt einfach abgebrochen". Ursache: `async for raw_message in ws: await _handle_rvs_message(...)` — das await blockt den recv-Loop solange send_to_core laeuft (bis zu 20 Min). Der mobil.hacker-net.de:444 RVS-Server droppt Verbindungen ohne echte App-Frames nach ~4 Min als idle-Timeout. Die websockets-Lib beantwortet Pings im Hintergrund, aber das reicht offenbar nicht — der Server zaehlt nur Application-Frames. Fix: chat-Handler ruft send_to_core als asyncio.create_task statt await. Brain laeuft im Hintergrund-Task, RVS-recv-Loop bleibt frei, neue Messages werden weiter verarbeitet, Verbindung bleibt lebendig. Gleicher Fix in _flush_pending_files_with_text und file-empty-Edge-Case. Tradeoff: parallele Brain-Calls wenn der User waehrend einer laufenden Antwort schnell mehrere Nachrichten schickt. Brain (FastAPI) verarbeitet beide, conversation.jsonl koennte racen. App macht aber bereits Barge-In via cancel_request bei Folge-Nachrichten — in der Praxis treffen sich parallele Calls selten. Wenn doch Probleme: Bridge-Side asyncio.Lock um send_to_core in einer Folge-Etappe. Co-Authored-By: Claude Opus 4.7 (1M context) --- bridge/aria_bridge.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/bridge/aria_bridge.py b/bridge/aria_bridge.py index 5843911..8dc99b6 100644 --- a/bridge/aria_bridge.py +++ b/bridge/aria_bridge.py @@ -1316,7 +1316,9 @@ class ARIABridge: self._pending_files_flush_task = None text = self._build_pending_files_message(user_text) self._pending_files = [] - await self.send_to_core(text, source="app-file+chat") + # create_task statt await — sonst blockt der RVS-recv-Loop bis Brain + # fertig ist (siehe chat-handler oben). + asyncio.create_task(self.send_to_core(text, source="app-file+chat")) return True async def send_to_core(self, text: str, source: str = "bridge", client_msg_id: Optional[str] = None) -> None: @@ -1641,9 +1643,16 @@ class ARIABridge: " [BARGE-IN]" if interrupted else "", " [GPS]" if location else "", text[:80]) - await self.send_to_core(core_text, - source="app" + (" [barge-in]" if interrupted else ""), - client_msg_id=client_msg_id) + # KEIN await: send_to_core kann 20 Min dauern. Wenn wir + # hier awaiten, blockt der `async for raw_message in ws`- + # Loop solange → RVS-Server droppt uns nach ~4 Min idle. + # Als Task: Brain laeuft im Hintergrund, RVS-recv bleibt + # bedienbar, Pings werden beantwortet, Verbindung lebt. + asyncio.create_task(self.send_to_core( + core_text, + source="app" + (" [barge-in]" if interrupted else ""), + client_msg_id=client_msg_id, + )) return if msg_type == "cancel_request": @@ -1819,7 +1828,8 @@ class ARIABridge: if not file_b64: text = f"Stefan hat eine Datei gesendet ({file_name}, {file_type}) aber die Daten sind leer angekommen." - await self.send_to_core(text, source="app-file") + # create_task statt await — RVS-recv darf nicht blocken + asyncio.create_task(self.send_to_core(text, source="app-file")) return if file_type.startswith("image/"):