fix(webui): merge length recovery stream segments
This commit is contained in:
+26
-5
@@ -4,6 +4,7 @@ from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import dataclasses
|
||||
import inspect
|
||||
import os
|
||||
import time
|
||||
from collections.abc import Mapping
|
||||
@@ -860,9 +861,9 @@ class AgentLoop:
|
||||
"""Run the agent iteration loop.
|
||||
|
||||
*on_stream*: called with each content delta during streaming.
|
||||
*on_stream_end(resuming)*: called when a streaming session finishes.
|
||||
``resuming=True`` means tool calls follow (spinner should restart);
|
||||
``resuming=False`` means this is the final response.
|
||||
*on_stream_end(resuming, merge_next)*: called when a streaming session finishes.
|
||||
``resuming=True`` means the active turn continues. ``merge_next=True`` means
|
||||
the next text segment belongs to the same user-visible assistant message.
|
||||
|
||||
Returns (final_content, tools_used, messages, stop_reason, had_injections).
|
||||
"""
|
||||
@@ -1385,6 +1386,19 @@ class AgentLoop:
|
||||
if ctx.on_stream is not None:
|
||||
stream_callback = ctx.on_stream
|
||||
stream_end_callback = ctx.on_stream_end
|
||||
stream_end_accepts_merge_next = False
|
||||
if stream_end_callback is not None:
|
||||
try:
|
||||
stream_end_signature = inspect.signature(stream_end_callback)
|
||||
stream_end_accepts_merge_next = (
|
||||
"merge_next" in stream_end_signature.parameters
|
||||
or any(
|
||||
parameter.kind is inspect.Parameter.VAR_KEYWORD
|
||||
for parameter in stream_end_signature.parameters.values()
|
||||
)
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
pass
|
||||
segment_streamed_content = False
|
||||
|
||||
async def _tracked_stream(delta: str) -> None:
|
||||
@@ -1393,12 +1407,19 @@ class AgentLoop:
|
||||
segment_streamed_content = True
|
||||
await stream_callback(delta)
|
||||
|
||||
async def _tracked_stream_end(*, resuming: bool = False) -> None:
|
||||
async def _tracked_stream_end(
|
||||
*,
|
||||
resuming: bool = False,
|
||||
merge_next: bool = False,
|
||||
) -> None:
|
||||
nonlocal segment_streamed_content
|
||||
ctx.streamed_content = segment_streamed_content
|
||||
segment_streamed_content = False
|
||||
if stream_end_callback is not None:
|
||||
await stream_end_callback(resuming=resuming)
|
||||
if merge_next and stream_end_accepts_merge_next:
|
||||
await stream_end_callback(resuming=resuming, merge_next=True)
|
||||
else:
|
||||
await stream_end_callback(resuming=resuming)
|
||||
|
||||
ctx.on_stream = _tracked_stream
|
||||
ctx.on_stream_end = _tracked_stream_end
|
||||
|
||||
Reference in New Issue
Block a user