diff --git a/core/main_terminal_parts/tools_execution.py b/core/main_terminal_parts/tools_execution.py index 0b503f5..0c914ed 100644 --- a/core/main_terminal_parts/tools_execution.py +++ b/core/main_terminal_parts/tools_execution.py @@ -1135,9 +1135,16 @@ class MainTerminalToolsExecutionMixin: "message": msg, } except asyncio.TimeoutError: - result = {"success": False, "error": f"等待子智能体 {agent_id} 输出超时(5分钟)"} + result = {"success": False, "error": f"等待子智能体 {agent_id} 输出超时(5分钟)。可用 send_message_to_sub_agent 重新激活。"} + except asyncio.CancelledError: + result = {"success": False, "error": f"等待子智能体 {agent_id} 被取消。该子智能体现在不可用,可用 send_message_to_sub_agent 重新激活。"} + except RuntimeError as exc: + error_msg = str(exc) + if "send_message_to_sub_agent" not in error_msg: + error_msg += " 可用 send_message_to_sub_agent 重新激活。" + result = {"success": False, "error": error_msg} except Exception as exc: - result = {"success": False, "error": f"等待子智能体 {agent_id} 输出失败: {exc}"} + result = {"success": False, "error": f"等待子智能体 {agent_id} 输出失败: {exc}。可用 send_message_to_sub_agent 重新激活。"} elif wait_sub_agent_ids: if getattr(self, "multi_agent_mode", False): result = { @@ -1923,7 +1930,7 @@ class MainTerminalToolsExecutionMixin: agent_ids=arguments.get("agent_ids", []) ) - # 多智能体模式专属工具:send_message_to_sub_agent / ask_sub_agent / answer_sub_agent_question / create_custom_agent / list_agents / list_active_sub_agents + # 多智能体模式专属工具:send_message_to_sub_agent / stop_sub_agent / answer_sub_agent_question / create_custom_agent / list_agents / list_active_sub_agents elif tool_name == "send_message_to_sub_agent": if not getattr(self, "multi_agent_mode", False): result = {"success": False, "error": "该工具仅在多智能体模式下可用"} @@ -1962,51 +1969,15 @@ class MainTerminalToolsExecutionMixin: logger.exception("[multi_agent] send_message_to_sub_agent failed") result = {"success": False, "error": str(exc)} - elif tool_name == "ask_sub_agent": + elif tool_name == "stop_sub_agent": if not getattr(self, "multi_agent_mode", False): result = {"success": False, "error": "该工具仅在多智能体模式下可用"} else: try: - from modules.multi_agent.state import format_multi_agent_message, TYPE_ASK agent_id = int(arguments.get("agent_id", 0)) - question = arguments.get("question", "") - timeout = int(arguments.get("timeout_seconds", 600)) - conv_id = self.context_manager.current_conversation_id - state = self.sub_agent_manager.get_multi_agent_state(conv_id) - if not state: - result = {"success": False, "error": "多智能体状态未就绪"} - else: - question_id = f"ask_sub_agent_{int(time.time() * 1000)}_{uuid.uuid4().hex[:6]}" - # 构造提问并插入子对话(子智能体下一轮 assistant 输出作为回答返回到工具结果) - text = format_multi_agent_message( - display_name="Team Leader", - msg_type=TYPE_ASK, - content=question, - msg_id=question_id, - target=state.get_instance(agent_id).display_name if state.get_instance(agent_id) else f"Agent_{agent_id}", - ) - ma_debug( - "tool_ask_sub_agent", - agent_id=agent_id, - question=str(question)[:500], - question_id=question_id, - wrapped_message_preview=text[:500], - conversation_id=conv_id, - ) - ok = self.sub_agent_manager.inject_message_to_sub_agent(agent_id, text) - if not ok: - result = {"success": False, "error": f"子智能体 {agent_id} 不存在"} - else: - # 阻塞等待子智能体下一轮输出作为回答 - answer = await state.wait_for_answer( - question_id=question_id, - agent_id=agent_id, - timeout=timeout, - ) - result = {"success": True, "answer": answer} - except asyncio.TimeoutError: - result = {"success": False, "error": "等待子智能体回答超时"} + result = self.sub_agent_manager.stop_sub_agent(agent_id=agent_id) except Exception as exc: + logger.exception("[multi_agent] stop_sub_agent failed") result = {"success": False, "error": str(exc)} elif tool_name == "answer_sub_agent_question": diff --git a/modules/multi_agent/state.py b/modules/multi_agent/state.py index ed6932d..72c743c 100644 --- a/modules/multi_agent/state.py +++ b/modules/multi_agent/state.py @@ -316,17 +316,45 @@ class MultiAgentState: return self.agents.get(aid) def list_active(self) -> List[AgentInstance]: - return [a for a in self.agents.values() if a.status == "running" or a.status == "idle"] + # failed 视为可复活状态,仍算活跃 + return [a for a in self.agents.values() if a.status in ("running", "idle", "failed")] def list_all(self) -> List[AgentInstance]: return list(self.agents.values()) def mark_status(self, agent_id: int, status: str, last_output: str = "") -> None: a = self.agents.get(agent_id) - if a: - a.status = status - if last_output: - a.last_output = last_output + if not a: + return + a.status = status + if last_output: + a.last_output = last_output + # 当子智能体进入终态/idle 时,立即取消 sleep(wait_sub_agent_output_ids) 的等待 + if status in ("failed", "terminated", "idle"): + self._cancel_output_wait(agent_id, status) + + def _cancel_output_wait(self, agent_id: int, status: str) -> None: + """取消指定 agent 的 sleep 输出等待,并提示可用 send_message_to_sub_agent 重新激活。""" + fut = self.output_waits.pop(agent_id, None) + if not fut or fut.done(): + return + if status == "terminated": + msg = f"子智能体 {agent_id} 已终止,无法继续等待输出。" + elif status == "failed": + msg = f"子智能体 {agent_id} 已失败,无法继续等待输出。该子智能体可被复活,可用 send_message_to_sub_agent 重新激活。" + else: + msg = f"子智能体 {agent_id} 已进入空闲状态,无法继续等待输出。可用 send_message_to_sub_agent 重新激活。" + try: + loop = fut.get_loop() + if loop and not loop.is_closed(): + loop.call_soon_threadsafe(fut.set_exception, RuntimeError(msg)) + return + except Exception: + pass + try: + fut.set_exception(RuntimeError(msg)) + except Exception: + pass # ----- 主对话注入 ----- def push_master_message(self, message_text: str) -> None: diff --git a/modules/multi_agent/tools.py b/modules/multi_agent/tools.py index 5f5d345..30d938e 100644 --- a/modules/multi_agent/tools.py +++ b/modules/multi_agent/tools.py @@ -65,6 +65,23 @@ def _master_tool_create_sub_agent() -> Dict[str, Any]: } +def _master_tool_stop_sub_agent() -> Dict[str, Any]: + return { + "type": "function", + "function": { + "name": "stop_sub_agent", + "description": "暂停指定子智能体实例,使其进入 idle 状态而不终结。暂停后可用 send_message_to_sub_agent 重新激活继续工作。", + "parameters": { + "type": "object", + "properties": _inject_intent({ + "agent_id": {"type": "integer", "description": "要暂停的子智能体编号。"}, + }), + "required": ["agent_id"], + }, + }, + } + + def _master_tool_terminate_sub_agent() -> Dict[str, Any]: return { "type": "function", @@ -104,29 +121,6 @@ def _master_tool_send_message_to_sub_agent() -> Dict[str, Any]: } -def _master_tool_ask_sub_agent() -> Dict[str, Any]: - return { - "type": "function", - "function": { - "name": "ask_sub_agent", - "description": ( - "向指定子智能体提出一个明确问题并阻塞等待一轮回答(不是发起任务,是问问题)。" - "问题会以 `来自 Team Leader 的提问` 格式插入子对话,子智能体下一轮 assistant 输出" - "作为回答返回到此工具结果中。" - ), - "parameters": { - "type": "object", - "properties": _inject_intent({ - "agent_id": {"type": "integer", "description": "目标子智能体编号。"}, - "question": {"type": "string", "description": "要询问的问题,应简短明确。"}, - "timeout_seconds": {"type": "integer", "description": "等待回答超时秒数,默认 600。"}, - }), - "required": ["agent_id", "question"], - }, - }, - } - - def _master_tool_answer_sub_agent_question() -> Dict[str, Any]: return { "type": "function", @@ -210,9 +204,9 @@ def _master_tool_get_sub_agent_status() -> Dict[str, Any]: MULTI_AGENT_MASTER_TOOLS: List[Dict[str, Any]] = [ _master_tool_create_sub_agent(), + _master_tool_stop_sub_agent(), _master_tool_terminate_sub_agent(), _master_tool_send_message_to_sub_agent(), - _master_tool_ask_sub_agent(), _master_tool_answer_sub_agent_question(), _master_tool_create_custom_agent(), _master_tool_list_agents(), diff --git a/server/conversation.py b/server/conversation.py index 5d678ad..c734aa8 100644 --- a/server/conversation.py +++ b/server/conversation.py @@ -644,13 +644,20 @@ def create_conversation(terminal: WebTerminal, workspace: UserWorkspace, usernam metadata_overrides={ "permission_mode": default_permission_mode or getattr(terminal, "get_permission_mode", lambda: "unrestricted")(), "execution_mode": getattr(terminal, "get_execution_mode", lambda: "sandbox")(), - "multi_agent_mode": multi_agent_mode, + "multi_agent_mode": bool(multi_agent_mode), }, ) try: cm.current_conversation_id = previous_cm_current except Exception: pass + # 同步 terminal 级别的多智能体开关,避免新对话继承旧状态 + terminal.multi_agent_mode = bool(multi_agent_mode) + try: + if hasattr(terminal, "sub_agent_manager"): + terminal.sub_agent_manager.multi_agent_mode = bool(multi_agent_mode) + except Exception: + pass result = { "success": True, "conversation_id": conversation_id, @@ -661,8 +668,15 @@ def create_conversation(terminal: WebTerminal, workspace: UserWorkspace, usernam result = terminal.create_new_conversation( thinking_mode=thinking_mode, run_mode=run_mode, - metadata_overrides={"multi_agent_mode": multi_agent_mode} if multi_agent_mode else None, + metadata_overrides={"multi_agent_mode": bool(multi_agent_mode)}, ) + # 同步 terminal 级别的多智能体开关,避免新对话继承旧状态 + terminal.multi_agent_mode = bool(multi_agent_mode) + try: + if hasattr(terminal, "sub_agent_manager"): + terminal.sub_agent_manager.multi_agent_mode = bool(multi_agent_mode) + except Exception: + pass if result["success"]: # 仅在当前工作区创建时更新 session 模式;指定其他工作区时由前端切换后自动同步。 diff --git a/server/multi_agent.py b/server/multi_agent.py index 1697f49..0d963b1 100644 --- a/server/multi_agent.py +++ b/server/multi_agent.py @@ -329,6 +329,13 @@ def create_multi_agent_conversation(): ctx_manager.current_conversation_id = previous_cm_current except Exception: pass + # 同步 terminal 级别的多智能体开关 + terminal.multi_agent_mode = True + try: + if hasattr(terminal, "sub_agent_manager"): + terminal.sub_agent_manager.multi_agent_mode = True + except Exception: + pass # 触发对话列表更新事件 try: diff --git a/static/src/components/chat/actions/ToolAction.vue b/static/src/components/chat/actions/ToolAction.vue index 98a0e32..eae9c4f 100644 --- a/static/src/components/chat/actions/ToolAction.vue +++ b/static/src/components/chat/actions/ToolAction.vue @@ -204,8 +204,6 @@ function renderToolResult(): string { return renderTerminateSubAgent(result, args); } else if (name === 'send_message_to_sub_agent') { return renderSendMessageToSubAgent(result, args); - } else if (name === 'ask_sub_agent') { - return renderAskSubAgent(result, args); } else if (name === 'answer_sub_agent_question') { return renderAnswerSubAgentQuestion(result, args); } else if (name === 'create_custom_agent') { @@ -832,14 +830,123 @@ function renderTerminalSnapshot(result: any, args: any): string { } function renderSleep(result: any, args: any): string { - const seconds = args.seconds || args.duration || 0; const status = formatToolStatusLabel(result, '✓ 完成'); - + const mode = result?.mode || 'seconds'; let html = '
'; - html += `
等待时间:${seconds}秒
`; html += `
状态:${status}
`; + html += `
模式:${escapeHtml(mode)}
`; + + if (mode === 'seconds' || mode === '' || mode === null) { + const seconds = args.seconds || args.duration || 0; + html += `
等待时间:${seconds}秒
`; + if (args.reason) { + html += `
原因:${escapeHtml(String(args.reason))}
`; + } + } else if (mode === 'wait_sub_agent_output') { + const agentId = result?.agent_id ?? args?.wait_sub_agent_output_ids ?? ''; + if (agentId !== '') { + html += `
等待子智能体:#${escapeHtml(String(agentId))}
`; + } + } else if (mode === 'wait_sub_agent_ids') { + const agentIds = Array.isArray(result?.agent_ids) ? result.agent_ids : []; + if (agentIds.length > 0) { + html += `
等待子智能体:${agentIds.map(String).join(', ')}
`; + } + const taskIds = Array.isArray(result?.waited_task_ids) ? result.waited_task_ids : []; + if (taskIds.length > 0) { + html += `
任务 ID:${taskIds.map(String).join(', ')}
`; + } + } else if (mode === 'wait_runcommand_id') { + const commandId = result?.command_id ?? args?.wait_runcommand_id ?? ''; + if (commandId !== '') { + html += `
后台命令 ID:${escapeHtml(String(commandId))}
`; + } + } + + if (!result?.success && result?.error) { + html += `
错误:${escapeHtml(String(result.error))}
`; + } html += '
'; + // content + if (mode === 'seconds' || mode === '' || mode === null) { + const message = result?.message || ''; + if (message) { + html += '
'; + html += `
结果:
`; + html += `
${escapeHtml(String(message))}
`; + html += '
'; + } + } else if (mode === 'wait_sub_agent_output') { + const message = result?.message || ''; + if (message) { + html += '
'; + html += '
子智能体输出:
'; + html += `
${escapeHtml(String(message))}
`; + html += '
'; + } + } else if (mode === 'wait_sub_agent_ids') { + const results = Array.isArray(result?.results) ? result.results : []; + if (results.length > 0) { + html += '
'; + html += `
已等待 ${results.length} 个子智能体:
`; + results.forEach((item: any) => { + if (!item || typeof item !== 'object') return; + const agentId = item.agent_id ?? '?'; + const taskId = item.task_id ?? '?'; + const itemStatus = item.status ?? 'unknown'; + const success = item.success === true; + html += '
'; + html += `
子智能体 #${escapeHtml(String(agentId))}(任务 ${escapeHtml(String(taskId))})· ${escapeHtml(String(itemStatus))} · ${success ? '✓ 成功' : '✗ 失败'}
`; + const itemMessage = item.message || item.error || ''; + if (itemMessage) { + const runtime = item.runtime_seconds ?? item.elapsed_seconds ?? null; + const runtimeNote = runtime !== null ? `运行 ${Math.round(Number(runtime))} 秒` : ''; + const stats = item.stats; + if (runtimeNote || stats) { + html += '
'; + if (runtimeNote) { + html += `${escapeHtml(runtimeNote)}`; + } + if (stats && typeof stats === 'object') { + const statParts = []; + if (stats.api_calls != null) statParts.push(`调用 ${stats.api_calls} 次`); + if (stats.files_read != null) statParts.push(`阅读 ${stats.files_read} 次`); + if (stats.edit_files != null) statParts.push(`编辑 ${stats.edit_files} 次`); + if (stats.searches != null) statParts.push(`搜索 ${stats.searches} 次`); + if (stats.web_pages != null) statParts.push(`网页 ${stats.web_pages} 个`); + if (stats.commands != null) statParts.push(`命令 ${stats.commands} 个`); + if (statParts.length > 0) { + html += `${escapeHtml(statParts.join(' | '))}`; + } + } + html += '
'; + } + html += `
${escapeHtml(String(itemMessage))}
`; + } + html += '
'; + }); + html += '
'; + } + } else if (mode === 'wait_runcommand_id') { + const nested = result?.result; + if (nested && typeof nested === 'object') { + const output = nested.output || nested.stdout || ''; + const exitCode = nested.exit_code !== undefined ? nested.exit_code : nested.returncode; + html += '
'; + html += '
后台命令输出:
'; + if (exitCode !== undefined) { + html += `
退出码:${escapeHtml(String(exitCode))}
`; + } + if (output) { + html += `
${escapeHtml(String(output))}
`; + } else { + html += '
[无输出]
'; + } + html += '
'; + } + } + return html; } @@ -1378,42 +1485,6 @@ function renderSendMessageToSubAgent(result: any, args: any): string { return html; } -function renderAskSubAgent(result: any, args: any): string { - const status = formatToolStatusLabel(result, '✓ 已回答', '✗ 获取失败'); - const agentId = args.agent_id ?? ''; - const question = args.question ?? ''; - const answer = - result?.answer ?? result?.content ?? result?.message ?? result?.output ?? result?.result ?? ''; - - let html = '
'; - html += `
状态:${status}
`; - if (agentId !== '') { - html += `
子智能体 ID:${escapeHtml(String(agentId))}
`; - } - if (question) { - const preview = String(question).slice(0, 200); - const suffix = String(question).length > 200 ? '…' : ''; - html += `
问题:${escapeHtml(preview + suffix)}
`; - } - if (!result?.success && result?.error) { - html += `
错误:${escapeHtml(String(result.error))}
`; - } - html += '
'; - - if (answer && typeof answer === 'string') { - html += '
'; - html += '
回答
'; - html += `
${escapeHtml(answer)}
`; - html += '
'; - } else if (result?.success) { - html += '
'; - html += '
子智能体未返回答复内容。
'; - html += '
'; - } - - return html; -} - function renderAnswerSubAgentQuestion(result: any, args: any): string { const status = formatToolStatusLabel(result, '✓ 已回复', '✗ 回复失败'); const questionId = args.question_id ?? result.question_id ?? ''; diff --git a/static/src/components/chat/actions/toolRenderers.ts b/static/src/components/chat/actions/toolRenderers.ts index a34da3f..f7ccd5f 100644 --- a/static/src/components/chat/actions/toolRenderers.ts +++ b/static/src/components/chat/actions/toolRenderers.ts @@ -159,8 +159,6 @@ export function renderEnhancedToolResult( return renderTerminateSubAgent(result, args); } else if (name === 'send_message_to_sub_agent') { return renderSendMessageToSubAgent(result, args); - } else if (name === 'ask_sub_agent') { - return renderAskSubAgent(result, args); } else if (name === 'answer_sub_agent_question') { return renderAnswerSubAgentQuestion(result, args); } else if (name === 'create_custom_agent') { @@ -804,14 +802,123 @@ function renderTerminalSnapshot(result: any, args: any): string { } function renderSleep(result: any, args: any): string { - const seconds = args.seconds || args.duration || 0; const status = formatToolStatusLabel(result, '✓ 完成'); - + const mode = result?.mode || 'seconds'; let html = '
'; - html += `
等待时间:${seconds}秒
`; html += `
状态:${status}
`; + html += `
模式:${escapeHtml(mode)}
`; + + if (mode === 'seconds' || mode === '' || mode === null) { + const seconds = args.seconds || args.duration || 0; + html += `
等待时间:${seconds}秒
`; + if (args.reason) { + html += `
原因:${escapeHtml(String(args.reason))}
`; + } + } else if (mode === 'wait_sub_agent_output') { + const agentId = result?.agent_id ?? args?.wait_sub_agent_output_ids ?? ''; + if (agentId !== '') { + html += `
等待子智能体:#${escapeHtml(String(agentId))}
`; + } + } else if (mode === 'wait_sub_agent_ids') { + const agentIds = Array.isArray(result?.agent_ids) ? result.agent_ids : []; + if (agentIds.length > 0) { + html += `
等待子智能体:${agentIds.map(String).join(', ')}
`; + } + const taskIds = Array.isArray(result?.waited_task_ids) ? result.waited_task_ids : []; + if (taskIds.length > 0) { + html += `
任务 ID:${taskIds.map(String).join(', ')}
`; + } + } else if (mode === 'wait_runcommand_id') { + const commandId = result?.command_id ?? args?.wait_runcommand_id ?? ''; + if (commandId !== '') { + html += `
后台命令 ID:${escapeHtml(String(commandId))}
`; + } + } + + if (!result?.success && result?.error) { + html += `
错误:${escapeHtml(String(result.error))}
`; + } html += '
'; + // content + if (mode === 'seconds' || mode === '' || mode === null) { + const message = result?.message || ''; + if (message) { + html += '
'; + html += `
结果:
`; + html += `
${escapeHtml(String(message))}
`; + html += '
'; + } + } else if (mode === 'wait_sub_agent_output') { + const message = result?.message || ''; + if (message) { + html += '
'; + html += '
子智能体输出:
'; + html += `
${escapeHtml(String(message))}
`; + html += '
'; + } + } else if (mode === 'wait_sub_agent_ids') { + const results = Array.isArray(result?.results) ? result.results : []; + if (results.length > 0) { + html += '
'; + html += `
已等待 ${results.length} 个子智能体:
`; + results.forEach((item: any) => { + if (!item || typeof item !== 'object') return; + const agentId = item.agent_id ?? '?'; + const taskId = item.task_id ?? '?'; + const itemStatus = item.status ?? 'unknown'; + const success = item.success === true; + html += '
'; + html += `
子智能体 #${escapeHtml(String(agentId))}(任务 ${escapeHtml(String(taskId))})· ${escapeHtml(String(itemStatus))} · ${success ? '✓ 成功' : '✗ 失败'}
`; + const itemMessage = item.message || item.error || ''; + if (itemMessage) { + const runtime = item.runtime_seconds ?? item.elapsed_seconds ?? null; + const runtimeNote = runtime !== null ? `运行 ${Math.round(Number(runtime))} 秒` : ''; + const stats = item.stats; + if (runtimeNote || stats) { + html += '
'; + if (runtimeNote) { + html += `${escapeHtml(runtimeNote)}`; + } + if (stats && typeof stats === 'object') { + const statParts = []; + if (stats.api_calls != null) statParts.push(`调用 ${stats.api_calls} 次`); + if (stats.files_read != null) statParts.push(`阅读 ${stats.files_read} 次`); + if (stats.edit_files != null) statParts.push(`编辑 ${stats.edit_files} 次`); + if (stats.searches != null) statParts.push(`搜索 ${stats.searches} 次`); + if (stats.web_pages != null) statParts.push(`网页 ${stats.web_pages} 个`); + if (stats.commands != null) statParts.push(`命令 ${stats.commands} 个`); + if (statParts.length > 0) { + html += `${escapeHtml(statParts.join(' | '))}`; + } + } + html += '
'; + } + html += `
${escapeHtml(String(itemMessage))}
`; + } + html += '
'; + }); + html += '
'; + } + } else if (mode === 'wait_runcommand_id') { + const nested = result?.result; + if (nested && typeof nested === 'object') { + const output = nested.output || nested.stdout || ''; + const exitCode = nested.exit_code !== undefined ? nested.exit_code : nested.returncode; + html += '
'; + html += '
后台命令输出:
'; + if (exitCode !== undefined) { + html += `
退出码:${escapeHtml(String(exitCode))}
`; + } + if (output) { + html += `
${escapeHtml(String(output))}
`; + } else { + html += '
[无输出]
'; + } + html += '
'; + } + } + return html; } @@ -1371,42 +1478,6 @@ function renderSendMessageToSubAgent(result: any, args: any): string { return html; } -function renderAskSubAgent(result: any, args: any): string { - const status = formatToolStatusLabel(result, '✓ 已回答', '✗ 获取失败'); - const agentId = args.agent_id ?? ''; - const question = args.question ?? ''; - const answer = - result?.answer ?? result?.content ?? result?.message ?? result?.output ?? result?.result ?? ''; - - let html = '
'; - html += `
状态:${status}
`; - if (agentId !== '') { - html += `
子智能体 ID:${escapeHtml(String(agentId))}
`; - } - if (question) { - const preview = String(question).slice(0, 200); - const suffix = String(question).length > 200 ? '…' : ''; - html += `
问题:${escapeHtml(preview + suffix)}
`; - } - if (!result?.success && result?.error) { - html += `
错误:${escapeHtml(String(result.error))}
`; - } - html += '
'; - - if (answer && typeof answer === 'string') { - html += '
'; - html += '
回答
'; - html += `
${escapeHtml(answer)}
`; - html += '
'; - } else if (result?.success) { - html += '
'; - html += '
子智能体未返回答复内容。
'; - html += '
'; - } - - return html; -} - function renderAnswerSubAgentQuestion(result: any, args: any): string { const status = formatToolStatusLabel(result, '✓ 已回复', '✗ 回复失败'); const questionId = args.question_id ?? result.question_id ?? ''; diff --git a/utils/tool_result_formatter/agent_context.py b/utils/tool_result_formatter/agent_context.py index e220519..5ad92a2 100644 --- a/utils/tool_result_formatter/agent_context.py +++ b/utils/tool_result_formatter/agent_context.py @@ -267,13 +267,14 @@ def _format_send_message_to_sub_agent(result_data: Dict[str, Any]) -> str: return "消息已发送。" -def _format_ask_sub_agent(result_data: Dict[str, Any]) -> str: +def _format_stop_sub_agent(result_data: Dict[str, Any]) -> str: if not result_data.get("success"): - return _format_failure("ask_sub_agent", result_data) - answer = result_data.get("answer") - if answer is None: - return "子智能体未返回答复。" - return f"子智能体的回答:\n{answer}" + return _format_failure("stop_sub_agent", result_data) + agent_id = result_data.get("agent_id") + message = result_data.get("message") or "子智能体已暂停。" + if agent_id is not None: + return f"已暂停子智能体 #{agent_id}。{message}" + return message def _format_answer_sub_agent_question(result_data: Dict[str, Any]) -> str: diff --git a/utils/tool_result_formatter/dispatch.py b/utils/tool_result_formatter/dispatch.py index b12988c..ae63e4e 100644 --- a/utils/tool_result_formatter/dispatch.py +++ b/utils/tool_result_formatter/dispatch.py @@ -38,7 +38,7 @@ from utils.tool_result_formatter.agent_context import ( _format_get_sub_agent_status, _format_terminate_sub_agent, _format_send_message_to_sub_agent, - _format_ask_sub_agent, + _format_stop_sub_agent, _format_answer_sub_agent_question, _format_create_custom_agent, _format_list_agents, @@ -131,7 +131,7 @@ TOOL_FORMATTERS = { "close_sub_agent": _format_close_sub_agent, "terminate_sub_agent": _format_terminate_sub_agent, "send_message_to_sub_agent": _format_send_message_to_sub_agent, - "ask_sub_agent": _format_ask_sub_agent, + "stop_sub_agent": _format_stop_sub_agent, "answer_sub_agent_question": _format_answer_sub_agent_question, "create_custom_agent": _format_create_custom_agent, "list_agents": _format_list_agents,