From fe804fa40ed2024495a827cb62edb81f4ff877c4 Mon Sep 17 00:00:00 2001 From: duffyduck Date: Sat, 8 Aug 2026 16:29:16 +0200 Subject: [PATCH] fix(chat): Nachrichten brechen nicht mehr ab (Bridge-Timeout) + Diagnostic-Selbstheilung MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ursache: Bridge-/chat-Aufruf hatte 1200s (20min) Timeout, der Proxy aber 24h. Lange Software-Dev-Turns dauern >20min → Bridge gab auf ('/chat fehlgeschlagen: timed out'), der Brain lieferte die Antwort Minuten spaeter (nur im Log, keine Bubble), und der Diagnostic-Kontext blieb auf 'running' haengen (Folgenachrichten in die Queue trotz idler ARIA; nur Ctrl+R half, verlor aber die Queue-Nachricht). - Bridge: /chat-Timeout 1200s → 24h (env BRAIN_CHAT_TIMEOUT_SEC), passend zum Proxy. - Diagnostic: reconcileDiagStates() gleicht lokalen 'running'-Zustand gegen die Brain-queue-status ab (2 Polls Karenz). Haengt ein Kontext, obwohl der Brain nicht busy ist → Queue weiterschalten: angestellte Nachricht geht automatisch raus statt verloren. Co-Authored-By: Claude Opus 4.8 --- bridge/aria_bridge.py | 11 +++++++---- diagnostic/index.html | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/bridge/aria_bridge.py b/bridge/aria_bridge.py index 31f78e3..153c82b 100644 --- a/bridge/aria_bridge.py +++ b/bridge/aria_bridge.py @@ -1963,10 +1963,13 @@ class ARIABridge: url, data=payload, method="POST", headers={"Content-Type": "application/json"}, ) - # 20 Min Timeout — lange Multi-Tool-Workflows (Karten, - # PDFs, viele curl-Calls) brauchen das. 5 Min waren chronisch - # zu knapp und haben ARIA mitten in der Arbeit gekappt. - with urllib.request.urlopen(req, timeout=1200) as resp: + # Timeout MUSS zum Proxy passen (der laesst ARIA bis 24h + # rechnen). 1200s (20 Min) war zu knapp: lange Software-Dev- + # Turns dauern laenger → die Bridge gab auf, die Antwort ging + # verloren (kein Bubble), der Kontext blieb auf 'running' + # haengen. Jetzt 24h (env BRAIN_CHAT_TIMEOUT_SEC). + _chat_timeout = float(os.environ.get("BRAIN_CHAT_TIMEOUT_SEC", "86400")) + with urllib.request.urlopen(req, timeout=_chat_timeout) as resp: return resp.status, resp.read().decode("utf-8", errors="ignore") except Exception as exc: return None, str(exc) diff --git a/diagnostic/index.html b/diagnostic/index.html index 2cc4aa3..feb983f 100644 --- a/diagnostic/index.html +++ b/diagnostic/index.html @@ -1588,9 +1588,34 @@ const d = await r.json(); diagQueueStatus = d?.contexts || {}; renderContextStrip(); + reconcileDiagStates(); } catch {} } + // Selbstheilung: haengt ein Kontext lokal auf 'running', obwohl der Brain + // ihn NICHT als busy meldet, ist der Turn (z.B. durch einen Bridge-Timeout) + // ohne Antwort-Bubble abgebrochen — der Automat blieb sonst ewig 'running' + // (Folge-Nachrichten wandern in die Queue, obwohl ARIA idle ist; frueher + // half nur Ctrl+R, was die Queue-Nachricht verlor). Nach 2 aufeinander- + // folgenden not-busy-Polls (~4s Karenz gegen das Sende-Fenster) schalten + // wir die Queue weiter: angestellte Nachricht geht automatisch raus, sonst + // idle. + const diagStuckCounts = {}; + function reconcileDiagStates() { + const ctxs = diagQueueStatus || {}; + for (const pid of Object.keys(diagCtxStates)) { + if (diagCtxStates[pid] !== 'running') { diagStuckCounts[pid] = 0; continue; } + const busy = !!(ctxs[pid || '__main__'] && ctxs[pid || '__main__'].busy); + if (busy) { diagStuckCounts[pid] = 0; continue; } + diagStuckCounts[pid] = (diagStuckCounts[pid] || 0) + 1; + if (diagStuckCounts[pid] >= 2) { + diagStuckCounts[pid] = 0; + console.warn('[diag] Kontext', pid || '(main)', 'haengt auf running, Brain idle → Queue weiterschalten'); + advanceDiagQueue(pid); + } + } + } + async function refreshDiagProjectsCache() { try { const r = await fetch('/api/brain/projects/list?include_archived=false');