fix(brain): Proxy-Timeout 20min -> 24h Read, split httpx-Timeouts, Cleanup-Pfade
Brain timed bei langen Pentests nach exakt 20:00 min raus, obwohl ARIAs
Subprozess fleissig weiterarbeitete und der Live-View alles zeigte.
Root-Cause: proxy_client.py hatte einen 1200s httpx.Client-Timeout —
genau der Wert, den wir vor 5 Tagen am Proxy auf 24h hochgezogen hatten.
Schicht uebersehen.
- docker-compose.yml: PROXY_TIMEOUT_SEC=86400 als brain-env.
- proxy_client.py: httpx.Timeout split (connect=10, read=86400, write=30,
pool=10). Toter Proxy wird in 10s erkannt, lange ARIA-Sessions duerfen
24h laufen.
- routes.js handleNonStreamingResponse: res.on("close") + isComplete-Flag.
Brain-Disconnect killt jetzt den Subprozess statt ihn verwaisen zu lassen.
- agent.py chat(): try/except — bei Exception nach dem User-Turn wird ein
Assistant-Error-Marker geschrieben, damit Conversation user->assistant
konsistent bleibt (kein Tool-Call-Loop-Fail in Folge-Calls).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+28
-7
@@ -367,21 +367,42 @@ async function handleStreamingResponse(req, res, subprocess, cliInput, requestId
|
||||
async function handleNonStreamingResponse(res, subprocess, cliInput, requestId) {
|
||||
return new Promise((resolve) => {
|
||||
let finalResult = null;
|
||||
let isComplete = false;
|
||||
// Client-Disconnect-Handler — wenn Brain die HTTP-Verbindung kappt
|
||||
// (z.B. nach Read-Timeout), den noch laufenden Subprocess killen.
|
||||
// Im Streaming-Branch existiert das schon; non-streaming hatte's
|
||||
// bisher nicht → Subprozess lief verwaist weiter, Ressourcen-Leak.
|
||||
res.on("close", () => {
|
||||
if (!isComplete) {
|
||||
console.warn("[NonStreaming] Client disconnected before result — killing subprocess", requestId);
|
||||
try { subprocess.kill(); } catch (_) {}
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
subprocess.on("result", (result) => {
|
||||
finalResult = result;
|
||||
});
|
||||
subprocess.on("error", (error) => {
|
||||
console.error("[NonStreaming] Error:", error.message);
|
||||
res.status(500).json({
|
||||
error: {
|
||||
message: error.message,
|
||||
type: "server_error",
|
||||
code: null,
|
||||
},
|
||||
});
|
||||
isComplete = true;
|
||||
if (!res.headersSent) {
|
||||
res.status(500).json({
|
||||
error: {
|
||||
message: error.message,
|
||||
type: "server_error",
|
||||
code: null,
|
||||
},
|
||||
});
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
subprocess.on("close", (code) => {
|
||||
isComplete = true;
|
||||
if (res.writableEnded) {
|
||||
// Client ist eh schon weg — nichts mehr zu senden.
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
if (finalResult) {
|
||||
res.json(cliResultToOpenai(finalResult, requestId));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user