diff --git a/core/main_terminal.py b/core/main_terminal.py index 2e9d46a..2e30875 100644 --- a/core/main_terminal.py +++ b/core/main_terminal.py @@ -1369,6 +1369,20 @@ class MainTerminal: } } }, + { + "type": "function", + "function": { + "name": "close_sub_agent", + "description": "强制关闭指定子智能体,适用于长时间无响应、超时或卡死的任务。使用前请确认必要的日志/文件已保留,操作会立即终止该任务。", + "parameters": { + "type": "object", + "properties": { + "task_id": {"type": "string", "description": "子智能体任务ID"}, + "agent_id": {"type": "integer", "description": "子智能体编号(1~5),若缺少 task_id 可用"} + } + } + } + }, { "type": "function", "function": { @@ -1990,6 +2004,12 @@ class MainTerminal: timeout_seconds=wait_timeout ) self._record_sub_agent_message(result.get("system_message"), result.get("task_id"), inline=False) + + elif tool_name == "close_sub_agent": + result = self.sub_agent_manager.terminate_sub_agent( + task_id=arguments.get("task_id"), + agent_id=arguments.get("agent_id") + ) else: result = {"success": False, "error": f"未知工具: {tool_name}"} diff --git a/modules/sub_agent_manager.py b/modules/sub_agent_manager.py index e805d5f..00a2083 100644 --- a/modules/sub_agent_manager.py +++ b/modules/sub_agent_manager.py @@ -206,6 +206,31 @@ class SubAgentManager: self._save_state() return finalize_result + def terminate_sub_agent( + self, + *, + task_id: Optional[str] = None, + agent_id: Optional[int] = None, + ) -> Dict: + """强制关闭指定子智能体。""" + task = self._select_task(task_id, agent_id) + if not task: + return {"success": False, "error": "未找到对应的子智能体任务"} + + task_id = task["task_id"] + response = self._call_service("POST", f"/tasks/{task_id}/terminate", timeout=10) + if response.get("success"): + task["status"] = "terminated" + task["final_result"] = { + "success": False, + "status": "terminated", + "task_id": task_id, + "agent_id": task.get("agent_id"), + "message": response.get("message") or "子智能体已被强制关闭。", + } + self._save_state() + return response + # ------------------------------------------------------------------ # 内部工具方法 # ------------------------------------------------------------------ diff --git a/sub_agent/web_server.py b/sub_agent/web_server.py index 57b22d8..3728e97 100644 --- a/sub_agent/web_server.py +++ b/sub_agent/web_server.py @@ -2132,6 +2132,32 @@ def stop_sub_agent_task(task_id: str) -> Dict[str, Any]: return {"success": True, "message": "已发送停止指令"} +def force_terminate_sub_agent(task_id: str) -> Dict[str, Any]: + cleanup_inactive_sub_agent_tasks() + task = sub_agent_tasks.get(task_id) + if not task: + return {"success": False, "error": "任务不存在"} + + client_sid = task.get("last_client_sid") + if client_sid and client_sid in stop_flags: + stop_flags[client_sid]["stop"] = True + + terminal = sub_agent_terminals.get(task_id) + if terminal: + try: + reset_system_state(terminal) + except Exception: + pass + + update_sub_agent_task(task_id, status="terminated") + broadcast_sub_agent_event(task_id, "sub_agent_status", { + "status": "terminated", + "message": "子智能体已强制关闭" + }) + _purge_sub_agent_task(task_id) + return {"success": True, "message": "子智能体已强制关闭"} + + # ========================================== # 子智能体任务API(主智能体调用,免登录) # ========================================== @@ -2189,6 +2215,13 @@ def api_stop_sub_agent(task_id: str): return jsonify(result), status_code +@app.route('/tasks//terminate', methods=['POST']) +def api_terminate_sub_agent(task_id: str): + result = force_terminate_sub_agent(task_id) + status_code = 200 if result.get("success") else 400 + return jsonify(result), status_code + + @app.route('/tasks//conversation', methods=['GET']) def api_get_sub_agent_conversation(task_id: str): info = get_task_record(task_id)