fix: prevent silent chat death and reduce streaming overhead

Three-factor compound failure causing chat sessions to silently stall:

1. Silent Exception Death (helpers/defer.py):
   DeferredTask._on_task_done() captures exceptions in Future but
   no code reads it. Chat sessions die with zero UI feedback.
   Fix: Log exceptions and notify AgentContext on task failure.

2. O(n²) Per-Chunk DirtyJson Parsing (agent.py):
   stream_callback runs extract_json_root_string() + json_parse_dirty()
   on EVERY streaming chunk with growing string length.
   Fix: Only parse when full.rstrip() ends with } or ].

3. Indefinite History Compression Wait:
   organize_history_wait has await task.result() with no timeout.
   Fix: Wrap with asyncio.wait_for() 30s timeout.

Amplifier: All chats share one EventLoopThread singleton,
making concurrent sessions particularly affected.
This commit is contained in:
wgnr-ai 2026-04-10 02:17:22 +00:00
parent d357c24d03
commit 663d4b5e79
3 changed files with 50 additions and 4 deletions

View file

@ -1,3 +1,4 @@
import asyncio
from helpers.extension import Extension
from agent import LoopData
from extensions.python.message_loop_end._10_organize_history import DATA_NAME_TASK
@ -19,8 +20,8 @@ class OrganizeHistoryWait(Extension):
if not task.is_ready():
self.agent.context.log.set_progress("Compressing history...")
# Wait for the task to complete
await task.result()
# Wait for the task to complete (with timeout to prevent indefinite blocking)
await asyncio.wait_for(task.result(), timeout=30)
# Clear the coroutine data after it's done
self.agent.set_data(DATA_NAME_TASK, None)