feat(aibox): 子代理实时输出可见化(转发 line/chunk 到主对话侧栏)
此前子代理(create_subagent / run_full_subagent)的输出回调只转发 reasoning_* 三类思考消息, 导致子代理真正的回答文本(chunk)与工具执行过程(line,含命令输出/工具调用)被丢弃,用户看不到。 改动: 1. run_full_subagent 的 sub_think_callback 白名单放开,新增转发 line / chunk; 2. SubAgentTool._subagent_output 处理 line(🔹 [子代理] 前缀)与 chunk; 3. chunk 文本先累积于 _subagent_chunk_buf,遇非 chunk 消息或 execute 结束时由 _flush_subagent_answer 统一冲刷(🤖 [子代理回答]),避免侧栏逐字断行。 仅主对话侧可见,worker 执行子代理本身不受影响。
This commit is contained in:
1 parent
23a10c37c7
commit
c9eaf988b3
1 file changed
+31
-7
+31
-7
@@ -5459,8 +5459,11 @@ def run_full_subagent(role, task, config, logger=None, model=None,
|
||||
# 直到 AI 返回纯文本无工具调用,或达到轮次限制
|
||||
# 将子代理的思考过程(reasoning)通过 output_callback 转发给父代理
|
||||
def sub_think_callback(msg_type, content):
|
||||
if output_callback is not None and \
|
||||
msg_type in ("reasoning_start", "reasoning", "reasoning_end"):
|
||||
# 转发子代理的实时输出:思考过程(reasoning)、工具执行过程(line)、回答文本(chunk)
|
||||
if output_callback is not None and msg_type in (
|
||||
"reasoning_start", "reasoning", "reasoning_end",
|
||||
"line", "chunk",
|
||||
):
|
||||
output_callback(msg_type, content)
|
||||
|
||||
sub_chat.think_and_respond(task, output_callback=sub_think_callback)
|
||||
@@ -5585,23 +5588,44 @@ class SubAgentTool(Tool):
|
||||
}
|
||||
|
||||
def _subagent_output(self, msg_type: str, content: str):
|
||||
"""子代理思考过程转发:把子代理的实时推理文字输出到主对话侧栏"""
|
||||
"""子代理实时输出转发:把子代理的思考、工具执行过程与回答文本流式输出到主对话侧栏。"""
|
||||
# 回答文本(chunk)先累积,避免在侧栏里逐字断行;遇非 chunk 消息或结束时统一冲刷
|
||||
if msg_type == "chunk":
|
||||
buf = getattr(self, "_subagent_chunk_buf", "")
|
||||
buf += content
|
||||
self._subagent_chunk_buf = buf
|
||||
return
|
||||
# 非 chunk 消息:先冲刷已累积的回答文本,再输出当前消息
|
||||
self._flush_subagent_answer()
|
||||
if msg_type == "reasoning_start":
|
||||
self.send_line("\n💭 [子代理思考] ")
|
||||
elif msg_type == "reasoning":
|
||||
self.send_line(content)
|
||||
elif msg_type == "reasoning_end":
|
||||
self.send_line("\n")
|
||||
elif msg_type == "line":
|
||||
# 工具调用、命令输出等过程行
|
||||
self.send_line(f"🔹 [子代理] {content}")
|
||||
|
||||
def _flush_subagent_answer(self):
|
||||
"""冲刷子代理回答缓冲(最后一段 chunk 在结束时统一发出,避免逐字断行)。"""
|
||||
buf = getattr(self, "_subagent_chunk_buf", "")
|
||||
if buf:
|
||||
self.send_line(f"🤖 [子代理回答] {buf}")
|
||||
self._subagent_chunk_buf = ""
|
||||
|
||||
def execute(self, role: str = None, task: str = None, model: str = None,
|
||||
temperature: float = None, max_tokens: int = 2048,
|
||||
max_turns: int = 10, **kwargs) -> str:
|
||||
if error := self.validate_params(["role", "task"], role=role, task=task):
|
||||
return error
|
||||
return run_full_subagent(role, task, self.config, logger=self.logger,
|
||||
model=model, temperature=temperature,
|
||||
max_tokens=max_tokens, max_turns=max_turns,
|
||||
output_callback=self._subagent_output)
|
||||
result = run_full_subagent(role, task, self.config, logger=self.logger,
|
||||
model=model, temperature=temperature,
|
||||
max_tokens=max_tokens, max_turns=max_turns,
|
||||
output_callback=self._subagent_output)
|
||||
# 冲刷子代理回答缓冲(最后一段 chunk 可能尚未发出)
|
||||
self._flush_subagent_answer()
|
||||
return result
|
||||
|
||||
|
||||
class SetProxyTool(Tool):
|
||||
|
||||
Reference in new issue
Block a user