fix(aibox/botops): 修复两处重复输出根因
1. 侧栏重复:_handle_tool_calls 中 msg_type in ("line", "complete")
将流式工具末尾的 complete 信号也当作 line 转发,导致所有支持
流式输出的工具(get_current_time、run_command、read_file等20+个)
结果在侧栏显示两次。改为仅转发 "line" 类型。
2. 聊天区Markdown列表重复:Textual 的 Markdown.append() 在 chunk
边界切断 Markdown 语法(如列表项 "- "被拆成两个chunk)时,增量
解析可能导致内容重复渲染。改为累积完整文本后调用 update() 整体
重新解析,避免增量解析的边界问题。
This commit is contained in:
1 parent
66963092a3
commit
f3d06252bb
2 files changed
+11
-4
No files matched your search
@@ -117,7 +117,12 @@ class ChatView(VerticalScroll):
|
|||||||
self._anchor_bottom()
|
self._anchor_bottom()
|
||||||
|
|
||||||
async def append_ai(self, delta: str):
|
async def append_ai(self, delta: str):
|
||||||
"""追加增量片段(服务端 chunk 为增量语义,直接拼接)。"""
|
"""追加增量片段(服务端 chunk 为增量语义,累积文本后 update 整个 Markdown)。
|
||||||
|
|
||||||
|
使用 update() 而非 Markdown.append():Textual 的 Markdown.append() 在
|
||||||
|
chunk 边界切断 Markdown 语法(如列表项、代码块)时可能导致重复解析渲染。
|
||||||
|
累积完整文本后 update() 确保每次都从完整文本重新解析,避免重复。
|
||||||
|
"""
|
||||||
if not delta:
|
if not delta:
|
||||||
return
|
return
|
||||||
if self._ai_finalized:
|
if self._ai_finalized:
|
||||||
@@ -125,9 +130,9 @@ class ChatView(VerticalScroll):
|
|||||||
return
|
return
|
||||||
# 第一次收到chunk时创建widget(此时思考widget如果存在已经在前面了)
|
# 第一次收到chunk时创建widget(此时思考widget如果存在已经在前面了)
|
||||||
await self._ensure_ai_widget()
|
await self._ensure_ai_widget()
|
||||||
self._ai_widget.append(delta)
|
|
||||||
self._ai_text += delta
|
self._ai_text += delta
|
||||||
# anchor 状态下容器会自动吸底;保险起见刷新后再滚一次
|
# 累积文本后整体update,而非增量append,避免Markdown增量解析导致的重复渲染
|
||||||
|
self._ai_widget.update(self._ai_text)
|
||||||
self.call_after_refresh(self.scroll_end, animate=False)
|
self.call_after_refresh(self.scroll_end, animate=False)
|
||||||
|
|
||||||
async def finish_ai(self, full_text: str = ""):
|
async def finish_ai(self, full_text: str = ""):
|
||||||
|
|||||||
+3
-1
@@ -7068,7 +7068,9 @@ class DeepSeekChat:
|
|||||||
while not output_queue.empty():
|
while not output_queue.empty():
|
||||||
try:
|
try:
|
||||||
msg_type, content = output_queue.get_nowait()
|
msg_type, content = output_queue.get_nowait()
|
||||||
if output_callback and msg_type in ("line", "complete"):
|
if output_callback and msg_type == "line":
|
||||||
|
# 只转发"line"类型;"complete"是流式结束信号,不作为行输出
|
||||||
|
# (之前complete也被转发导致工具结果在侧栏显示两次)
|
||||||
output_callback("line", str(content) if content is not None else "")
|
output_callback("line", str(content) if content is not None else "")
|
||||||
has_stream_output = True
|
has_stream_output = True
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
|
|||||||
Reference in new issue
Block a user