Skip to content

Commit 64a2e09

Browse files
committed
fix: send SSE heartbeat to prevent WebChat disconnect during compression
When context compression triggers with slow reasoning models (e.g. deepseek-reasoner), the backend can go 30+ seconds without pushing any SSE data. The client-side EventSource / browser then assumes the connection is dead and disconnects, causing the WebUI to hang indefinitely since it never receives the eventual response. Fix: yield an SSE comment (`: heartbeat`) on every empty poll cycle. Comment lines are defined in the SSE spec as keep-alive signals -- the EventSource API ignores them but the HTTP connection stays open. Fixes #6938
1 parent b241b46 commit 64a2e09

1 file changed

Lines changed: 8 additions & 0 deletions

File tree

astrbot/dashboard/routes/chat.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ async def _poll_webchat_stream_result(back_queue, username: str):
4040
try:
4141
result = await asyncio.wait_for(back_queue.get(), timeout=1)
4242
except asyncio.TimeoutError:
43+
# Return a sentinel so the caller can send an SSE heartbeat to
44+
# keep the connection alive during long-running operations (e.g.
45+
# context compression with reasoning models). See #6938.
4346
return None, False
4447
except asyncio.CancelledError:
4548
logger.debug(f"[WebChat] 用户 {username} 断开聊天长连接。")
@@ -364,6 +367,11 @@ async def stream():
364367
client_disconnected = True
365368
break
366369
if not result:
370+
# Send an SSE comment as keep-alive so the client
371+
# doesn't time out during slow backend ops like
372+
# context compression with reasoning models (#6938).
373+
if not client_disconnected:
374+
yield ": heartbeat\n\n"
367375
continue
368376

369377
if (

0 commit comments

Comments
 (0)