import asyncio
import json
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional, Set

try:
    from config import (
        OUTPUT_FORMATS, DATA_DIR, PROMPTS_DIR, NEED_CONFIRMATION,
        MAX_TERMINALS, TERMINAL_BUFFER_SIZE, TERMINAL_DISPLAY_SIZE,
        MAX_READ_FILE_CHARS, READ_TOOL_DEFAULT_MAX_CHARS,
        READ_TOOL_DEFAULT_CONTEXT_BEFORE, READ_TOOL_DEFAULT_CONTEXT_AFTER,
        READ_TOOL_MAX_CONTEXT_BEFORE, READ_TOOL_MAX_CONTEXT_AFTER,
        READ_TOOL_DEFAULT_MAX_MATCHES, READ_TOOL_MAX_MATCHES,
        READ_TOOL_MAX_FILE_SIZE,
        TERMINAL_SANDBOX_MOUNT_PATH,
        TERMINAL_SANDBOX_MODE,
        TERMINAL_SANDBOX_CPUS,
        TERMINAL_SANDBOX_MEMORY,
        PROJECT_MAX_STORAGE_MB,
        CUSTOM_TOOLS_ENABLED,
    )
except ImportError:
    import sys
    project_root = Path(__file__).resolve().parents[2]
    if str(project_root) not in sys.path:
        sys.path.insert(0, str(project_root))
    from config import (
        OUTPUT_FORMATS, DATA_DIR, PROMPTS_DIR, NEED_CONFIRMATION,
        MAX_TERMINALS, TERMINAL_BUFFER_SIZE, TERMINAL_DISPLAY_SIZE,
        MAX_READ_FILE_CHARS, READ_TOOL_DEFAULT_MAX_CHARS,
        READ_TOOL_DEFAULT_CONTEXT_BEFORE, READ_TOOL_DEFAULT_CONTEXT_AFTER,
        READ_TOOL_MAX_CONTEXT_BEFORE, READ_TOOL_MAX_CONTEXT_AFTER,
        READ_TOOL_DEFAULT_MAX_MATCHES, READ_TOOL_MAX_MATCHES,
        READ_TOOL_MAX_FILE_SIZE,
        TERMINAL_SANDBOX_MOUNT_PATH,
        TERMINAL_SANDBOX_MODE,
        TERMINAL_SANDBOX_CPUS,
        TERMINAL_SANDBOX_MEMORY,
        PROJECT_MAX_STORAGE_MB,
        CUSTOM_TOOLS_ENABLED,
    )

from modules.file_manager import FileManager
from modules.search_engine import SearchEngine
from modules.terminal_ops import TerminalOperator
from modules.memory_manager import MemoryManager
from modules.terminal_manager import TerminalManager
from modules.todo_manager import TodoManager
from modules.sub_agent_manager import SubAgentManager
from modules.webpage_extractor import extract_webpage_content, tavily_extract
from modules.ocr_client import OCRClient
from modules.easter_egg_manager import EasterEggManager
from modules.personalization_manager import (
    load_personalization_config,
    build_personalization_prompt,
)
from modules.skills_manager import (
    get_skills_catalog,
    build_skills_list,
    merge_enabled_skills,
    build_skills_prompt,
)
from modules.custom_tool_registry import CustomToolRegistry, build_default_tool_category
from modules.custom_tool_executor import CustomToolExecutor

try:
    from config.limits import THINKING_FAST_INTERVAL
except ImportError:
    THINKING_FAST_INTERVAL = 10

from modules.container_monitor import collect_stats, inspect_state
from core.tool_config import TOOL_CATEGORIES
from utils.api_client import DeepSeekClient
from utils.context_manager import ContextManager
from utils.tool_result_formatter import format_tool_result_for_context
from utils.logger import setup_logger
from config.model_profiles import (
    get_model_profile,
    get_model_prompt_replacements,
    get_model_context_window,
)

logger = setup_logger(__name__)
DISABLE_LENGTH_CHECK = True

class MainTerminalToolsExecutionMixin:
    def _record_sub_agent_message(self, message: Optional[str], task_id: Optional[str] = None, inline: bool = False):
                """以 system 消息记录子智能体状态。"""
                if not message:
                    return
                if task_id and task_id in self._announced_sub_agent_tasks:
                    return
                if task_id:
                    self._announced_sub_agent_tasks.add(task_id)
                logger.info(
                    "[SubAgent] record message | task=%s | inline=%s | content=%s",
                    task_id,
                    inline,
                    message.replace("\n", "\\n")[:200],
                )
                metadata = {"sub_agent_notice": True, "inline": inline}
                if task_id:
                    metadata["task_id"] = task_id
                self.context_manager.add_conversation("system", message, metadata=metadata)
                print(f"{OUTPUT_FORMATS['info']} {message}")

    async def handle_tool_call(self, tool_name: str, arguments: Dict) -> str:
                """处理工具调用（添加参数预检查和改进错误处理）"""
                # 导入字符限制配置
                from config import (
                    MAX_READ_FILE_CHARS, 
                    MAX_RUN_COMMAND_CHARS, MAX_EXTRACT_WEBPAGE_CHARS
                )

                # 检查是否需要确认
                if tool_name in NEED_CONFIRMATION:
                    if not await self.confirm_action(tool_name, arguments):
                        return json.dumps({"success": False, "error": "用户取消操作"})

                # === 新增：预检查参数大小和格式 ===
                try:
                    # 检查参数总大小
                    arguments_str = json.dumps(arguments, ensure_ascii=False)
                    if len(arguments_str) > 200000:  # 200KB限制
                        return json.dumps({
                            "success": False,
                            "error": f"参数过大({len(arguments_str)}字符)，超过200KB限制",
                            "suggestion": "请分块处理或减少参数内容"
                        }, ensure_ascii=False)

                    # 针对特定工具的内容检查
                    if tool_name == "write_file":
                        content = arguments.get("content", "")
                        length_limit = 200000
                        if not DISABLE_LENGTH_CHECK and len(content) > length_limit:
                            return json.dumps({
                                "success": False,
                                "error": f"文件内容过长({len(content)}字符)，超过{length_limit}字符限制",
                                "suggestion": "请分块写入，或设置 append=true 多次写入"
                            }, ensure_ascii=False)
                        if '\\' in content and content.count('\\') > len(content) / 10:
                            print(f"{OUTPUT_FORMATS['warning']} 检测到大量转义字符，可能存在格式问题")

                except Exception as e:
                    return json.dumps({
                        "success": False,
                        "error": f"参数预检查失败: {str(e)}"
                    }, ensure_ascii=False)

                # 自定义工具预解析（仅管理员）
                custom_tool = None
                if self.custom_tools_enabled and getattr(self, "user_role", "user") == "admin":
                    try:
                        self.custom_tool_registry.reload()
                    except Exception:
                        pass
                    custom_tool = self.custom_tool_registry.get_tool(tool_name)

                try:
                    if custom_tool:
                        result = await self.custom_tool_executor.run(tool_name, arguments)
                    elif tool_name == "read_file":
                        result = self._handle_read_tool(arguments)
                    elif tool_name in {"vlm_analyze", "ocr_image"}:
                        path = arguments.get("path")
                        prompt = arguments.get("prompt")
                        if not path:
                            return json.dumps({"success": False, "error": "缺少 path 参数", "warnings": []}, ensure_ascii=False)
                        result = self.ocr_client.vlm_analyze(path=path, prompt=prompt or "")
                    elif tool_name == "view_image":
                        path = (arguments.get("path") or "").strip()
                        if not path:
                            return json.dumps({"success": False, "error": "path 不能为空"}, ensure_ascii=False)
                        host_unrestricted = self._is_host_mode()
                        if path.startswith("/workspace"):
                            if host_unrestricted:
                                path = path.split("/workspace", 1)[1].lstrip("/")
                            else:
                                return json.dumps({"success": False, "error": "非法路径，超出项目根目录，请使用不带/workspace的相对路径"}, ensure_ascii=False)
                        if host_unrestricted and (Path(path).is_absolute() or (len(path) > 1 and path[1] == ":")):
                            abs_path = Path(path).expanduser().resolve()
                        else:
                            abs_path = (Path(self.context_manager.project_path) / path).resolve()
                            if not host_unrestricted:
                                try:
                                    abs_path.relative_to(Path(self.context_manager.project_path).resolve())
                                except Exception:
                                    return json.dumps({"success": False, "error": "非法路径，超出项目根目录，请使用不带/workspace的相对路径"}, ensure_ascii=False)
                        if not abs_path.exists() or not abs_path.is_file():
                            return json.dumps({"success": False, "error": f"图片不存在: {path}"}, ensure_ascii=False)
                        if abs_path.stat().st_size > 10 * 1024 * 1024:
                            return json.dumps({"success": False, "error": "图片过大，需 <= 10MB"}, ensure_ascii=False)
                        allowed_ext = {".png", ".jpg", ".jpeg", ".webp", ".gif", ".bmp", ".svg"}
                        if abs_path.suffix.lower() not in allowed_ext:
                            return json.dumps({"success": False, "error": f"不支持的图片格式: {abs_path.suffix}"}, ensure_ascii=False)
                        # 记录待附加图片，供上层将图片附加到工具结果
                        self.pending_image_view = {
                            "path": str(path)
                        }
                        result = {"success": True, "message": "图片已附加到工具结果中，将随 tool 返回。", "path": path}
                    elif tool_name == "view_video":
                        path = (arguments.get("path") or "").strip()
                        if not path:
                            return json.dumps({"success": False, "error": "path 不能为空"}, ensure_ascii=False)
                        host_unrestricted = self._is_host_mode()
                        if path.startswith("/workspace"):
                            if host_unrestricted:
                                path = path.split("/workspace", 1)[1].lstrip("/")
                            else:
                                return json.dumps({"success": False, "error": "非法路径，超出项目根目录，请使用相对路径"}, ensure_ascii=False)
                        if host_unrestricted and (Path(path).is_absolute() or (len(path) > 1 and path[1] == ":")):
                            abs_path = Path(path).expanduser().resolve()
                        else:
                            abs_path = (Path(self.context_manager.project_path) / path).resolve()
                            if not host_unrestricted:
                                try:
                                    abs_path.relative_to(Path(self.context_manager.project_path).resolve())
                                except Exception:
                                    return json.dumps({"success": False, "error": "非法路径，超出项目根目录，请使用相对路径"}, ensure_ascii=False)
                        if not abs_path.exists() or not abs_path.is_file():
                            return json.dumps({"success": False, "error": f"视频不存在: {path}"}, ensure_ascii=False)
                        allowed_ext = {".mp4", ".mov", ".mkv", ".avi", ".webm"}
                        if abs_path.suffix.lower() not in allowed_ext:
                            return json.dumps({"success": False, "error": f"不支持的视频格式: {abs_path.suffix}"}, ensure_ascii=False)
                        if abs_path.stat().st_size > 50 * 1024 * 1024:
                            return json.dumps({"success": False, "error": "视频过大，需 <= 50MB"}, ensure_ascii=False)
                        self.pending_video_view = {"path": str(path)}
                        result = {
                            "success": True,
                            "message": "视频已附加到工具结果中，将随 tool 返回。",
                            "path": path
                        }

                    # 终端会话管理工具
                    elif tool_name == "terminal_session":
                        action = arguments["action"]

                        if action == "open":
                            result = self.terminal_manager.open_terminal(
                                session_name=arguments.get("session_name", "default"),
                                working_dir=arguments.get("working_dir"),
                                make_active=True
                            )
                            if result["success"]:
                                print(f"{OUTPUT_FORMATS['session']} 终端会话已打开: {arguments.get('session_name', 'default')}")

                        elif action == "close":
                            result = self.terminal_manager.close_terminal(
                                session_name=arguments.get("session_name", "default")
                            )
                            if result["success"]:
                                print(f"{OUTPUT_FORMATS['session']} 终端会话已关闭: {arguments.get('session_name', 'default')}")

                        elif action == "list":
                            result = self.terminal_manager.list_terminals()

                        elif action == "reset":
                            result = self.terminal_manager.reset_terminal(
                                session_name=arguments.get("session_name")
                            )
                            if result["success"]:
                                print(f"{OUTPUT_FORMATS['session']} 终端会话已重置: {result['session']}")

                        else:
                            result = {"success": False, "error": f"未知操作: {action}"}
                        result["action"] = action

                    # 终端输入工具
                    elif tool_name == "terminal_input":
                        result = self.terminal_manager.send_to_terminal(
                            command=arguments["command"],
                            session_name=arguments.get("session_name"),
                            timeout=arguments.get("timeout")
                        )
                        if result["success"]:
                            print(f"{OUTPUT_FORMATS['terminal']} 执行命令: {arguments['command']}")

                    elif tool_name == "terminal_snapshot":
                        result = self.terminal_manager.get_terminal_snapshot(
                            session_name=arguments.get("session_name"),
                            lines=arguments.get("lines"),
                            max_chars=arguments.get("max_chars")
                        )

                    # sleep工具
                    elif tool_name == "sleep":
                        seconds = arguments.get("seconds", 1)
                        reason = arguments.get("reason", "等待操作完成")

                        # 限制最大等待时间
                        max_sleep = 600  # 最多等待60秒
                        if seconds > max_sleep:
                            result = {
                                "success": False,
                                "error": f"等待时间过长，最多允许 {max_sleep} 秒",
                                "suggestion": f"建议分多次等待或减少等待时间"
                            }
                        else:
                            # 确保秒数为正数
                            if seconds <= 0:
                                result = {
                                    "success": False,
                                    "error": "等待时间必须大于0"
                                }
                            else:
                                print(f"{OUTPUT_FORMATS['info']} 等待 {seconds} 秒: {reason}")

                                # 执行等待
                                import asyncio
                                await asyncio.sleep(seconds)

                                result = {
                                    "success": True,
                                    "message": f"已等待 {seconds} 秒",
                                    "reason": reason,
                                    "timestamp": datetime.now().isoformat()
                                }

                                print(f"{OUTPUT_FORMATS['success']} 等待完成")

                    elif tool_name == "create_file":
                        result = self.file_manager.create_file(
                            path=arguments["path"],
                            file_type=arguments["file_type"]
                        )
                        # 添加备注
                        if result["success"] and arguments.get("annotation"):
                            self.context_manager.update_annotation(
                                result["path"],
                                arguments["annotation"]
                            )
                        if result.get("success"):
                            result["message"] = (
                                f"已创建空文件: {result['path']}。请使用 write_file 写入内容，或使用 edit_file 进行替换。"
                            )

                    elif tool_name == "delete_file":
                        result = self.file_manager.delete_file(arguments["path"])
                        # 如果删除成功，同时删除备注
                        if result.get("success") and result.get("action") == "deleted":
                            deleted_path = result.get("path")
                            # 删除备注
                            if deleted_path in self.context_manager.file_annotations:
                                del self.context_manager.file_annotations[deleted_path]
                                self.context_manager.save_annotations()
                                print(f"🧹 已删除文件备注: {deleted_path}")

                    elif tool_name == "rename_file":
                        result = self.file_manager.rename_file(
                            arguments["old_path"],
                            arguments["new_path"]
                        )
                        # 如果重命名成功，更新备注和聚焦的key
                        # 如果重命名成功，更新备注
                        if result.get("success") and result.get("action") == "renamed":
                            old_path = result.get("old_path")
                            new_path = result.get("new_path")
                            # 更新备注
                            if old_path in self.context_manager.file_annotations:
                                annotation = self.context_manager.file_annotations[old_path]
                                del self.context_manager.file_annotations[old_path]
                                self.context_manager.file_annotations[new_path] = annotation
                                self.context_manager.save_annotations()
                                print(f"📝 已更新文件备注: {old_path} -> {new_path}")

                    elif tool_name == "write_file":
                        path = arguments.get("file_path")
                        content = arguments.get("content", "")
                        append_flag = bool(arguments.get("append", False))
                        if not path:
                            result = {"success": False, "error": "缺少必要参数: file_path"}
                        else:
                            mode = "a" if append_flag else "w"
                            result = self.file_manager.write_file(path, content, mode=mode)

                    elif tool_name == "edit_file":
                        path = arguments.get("file_path")
                        old_text = arguments.get("old_string")
                        new_text = arguments.get("new_string")
                        if not path:
                            result = {"success": False, "error": "缺少必要参数: file_path"}
                        elif old_text is None or new_text is None:
                            result = {"success": False, "error": "缺少必要参数: old_string/new_string"}
                        elif old_text == new_text:
                            result = {"success": False, "error": "old_string 与 new_string 相同，无法执行替换"}
                        elif not old_text:
                            result = {"success": False, "error": "old_string 不能为空，请从 read_file 内容中精确复制"}
                        else:
                            result = self.file_manager.replace_in_file(path, old_text, new_text)
                    elif tool_name == "create_folder":
                        result = self.file_manager.create_folder(arguments["path"])

                    elif tool_name == "web_search":
                        allowed, quota_info = self.record_search_call()
                        if not allowed:
                            return json.dumps({
                                "success": False,
                                "error": f"搜索配额已用尽，将在 {quota_info.get('reset_at')} 重置。请向用户说明情况并提供替代方案。",
                                "quota": quota_info
                            }, ensure_ascii=False)
                        search_response = await self.search_engine.search_with_summary(
                            query=arguments["query"],
                            max_results=arguments.get("max_results"),
                            topic=arguments.get("topic"),
                            time_range=arguments.get("time_range"),
                            days=arguments.get("days"),
                            start_date=arguments.get("start_date"),
                            end_date=arguments.get("end_date"),
                            country=arguments.get("country"),
                            include_domains=arguments.get("include_domains")
                        )

                        if search_response["success"]:
                            result = {
                                "success": True,
                                "summary": search_response["summary"],
                                "filters": search_response.get("filters", {}),
                                "query": search_response.get("query"),
                                "results": search_response.get("results", []),
                                "total_results": search_response.get("total_results", 0)
                            }
                        else:
                            result = {
                                "success": False,
                                "error": search_response.get("error", "搜索失败"),
                                "filters": search_response.get("filters", {}),
                                "query": search_response.get("query"),
                                "results": search_response.get("results", []),
                                "total_results": search_response.get("total_results", 0)
                            }

                    elif tool_name == "extract_webpage":
                        url = arguments["url"]
                        try:
                            # 从config获取API密钥
                            from config import TAVILY_API_KEY
                            full_content, _ = await extract_webpage_content(
                                urls=url, 
                                api_key=TAVILY_API_KEY,
                                extract_depth="basic",
                                max_urls=1
                            )

                            # 字符数检查
                            char_count = len(full_content)
                            if char_count > MAX_EXTRACT_WEBPAGE_CHARS:
                                result = {
                                    "success": False,
                                    "error": f"网页提取返回了过长的{char_count}字符，请不要提取这个网页，可以使用网页保存功能，然后使用read工具查找或查看网页",
                                    "char_count": char_count,
                                    "limit": MAX_EXTRACT_WEBPAGE_CHARS,
                                    "url": url
                                }
                            else:
                                result = {
                                    "success": True,
                                    "url": url,
                                    "content": full_content
                                }
                        except Exception as e:
                            result = {
                                "success": False,
                                "error": f"网页提取失败: {str(e)}",
                                "url": url
                            }

                    elif tool_name == "save_webpage":
                        url = arguments["url"]
                        target_path = arguments["target_path"]
                        try:
                            from config import TAVILY_API_KEY
                        except ImportError:
                            TAVILY_API_KEY = None

                        if not TAVILY_API_KEY or TAVILY_API_KEY == "your-tavily-api-key":
                            result = {
                                "success": False,
                                "error": "Tavily API密钥未配置，无法保存网页",
                                "url": url,
                                "path": target_path
                            }
                        else:
                            try:
                                extract_result = await tavily_extract(
                                    urls=url,
                                    api_key=TAVILY_API_KEY,
                                    extract_depth="basic",
                                    max_urls=1
                                )

                                if not extract_result or "error" in extract_result:
                                    error_message = extract_result.get("error", "提取失败，未返回任何内容") if isinstance(extract_result, dict) else "提取失败"
                                    result = {
                                        "success": False,
                                        "error": error_message,
                                        "url": url,
                                        "path": target_path
                                    }
                                else:
                                    results_list = extract_result.get("results", []) if isinstance(extract_result, dict) else []

                                    primary_result = None
                                    for item in results_list:
                                        if item.get("raw_content"):
                                            primary_result = item
                                            break
                                    if primary_result is None and results_list:
                                        primary_result = results_list[0]

                                    if not primary_result:
                                        failed_list = extract_result.get("failed_results", []) if isinstance(extract_result, dict) else []
                                        result = {
                                            "success": False,
                                            "error": "提取成功结果为空，无法保存",
                                            "url": url,
                                            "path": target_path,
                                            "failed": failed_list
                                        }
                                    else:
                                        content_to_save = primary_result.get("raw_content") or primary_result.get("content") or ""

                                        if not content_to_save:
                                            result = {
                                                "success": False,
                                                "error": "网页内容为空，未写入文件",
                                                "url": url,
                                                "path": target_path
                                            }
                                        else:
                                            write_result = self.file_manager.write_file(target_path, content_to_save, mode="w")

                                            if not write_result.get("success"):
                                                result = {
                                                    "success": False,
                                                    "error": write_result.get("error", "写入文件失败"),
                                                    "url": url,
                                                    "path": target_path
                                                }
                                            else:
                                                char_count = len(content_to_save)
                                                byte_size = len(content_to_save.encode("utf-8"))
                                                result = {
                                                    "success": True,
                                                    "url": url,
                                                    "path": write_result.get("path", target_path),
                                                    "char_count": char_count,
                                                    "byte_size": byte_size,
                                                    "message": f"网页内容已以纯文本保存到 {write_result.get('path', target_path)}，可用 read_file 的 search/extract 查看，必要时再用终端命令。"
                                                }

                                                if isinstance(extract_result, dict) and extract_result.get("failed_results"):
                                                    result["warnings"] = extract_result["failed_results"]

                            except Exception as e:
                                result = {
                                    "success": False,
                                    "error": f"网页保存失败: {str(e)}",
                                    "url": url,
                                    "path": target_path
                                }

                    elif tool_name == "run_python":
                        result = await self.terminal_ops.run_python_code(
                            arguments["code"],
                            timeout=arguments.get("timeout")
                        )

                    elif tool_name == "run_command":
                        result = await self.terminal_ops.run_command(
                            arguments["command"],
                            timeout=arguments.get("timeout")
                        )

                        # 字符数检查
                        if result.get("success") and "output" in result:
                            char_count = len(result["output"])
                            if char_count > MAX_RUN_COMMAND_CHARS:
                                result = {
                                    "success": False,
                                    "error": f"结果内容过大，有{char_count}字符，请使用限制字符数的获取内容方式，根据程度选择10k以内的数",
                                    "char_count": char_count,
                                    "limit": MAX_RUN_COMMAND_CHARS,
                                    "command": arguments["command"]
                                }

                    elif tool_name == "update_memory":
                        memory_type = arguments["memory_type"]
                        operation = arguments["operation"]
                        content = arguments.get("content")
                        index = arguments.get("index")

                        # 参数校验
                        if operation == "append" and (not content or not str(content).strip()):
                            result = {"success": False, "error": "append 操作需要 content"}
                        elif operation == "replace" and (index is None or index <= 0 or not content or not str(content).strip()):
                            result = {"success": False, "error": "replace 操作需要有效的 index 和 content"}
                        elif operation == "delete" and (index is None or index <= 0):
                            result = {"success": False, "error": "delete 操作需要有效的 index"}
                        else:
                            result = self.memory_manager.update_entries(
                                memory_type=memory_type,
                                operation=operation,
                                content=content,
                                index=index
                            )

                    elif tool_name == "todo_create":
                        result = self.todo_manager.create_todo_list(
                            overview=arguments.get("overview", ""),
                            tasks=arguments.get("tasks", [])
                        )

                    elif tool_name == "todo_update_task":
                        task_indices = arguments.get("task_indices")
                        if task_indices is None:
                            task_indices = arguments.get("task_index")
                        result = self.todo_manager.update_task_status(
                            task_indices=task_indices,
                            completed=arguments.get("completed", True)
                        )

                    elif tool_name == "create_sub_agent":
                        result = self.sub_agent_manager.create_sub_agent(
                            agent_id=arguments.get("agent_id"),
                            summary=arguments.get("summary", ""),
                            task=arguments.get("task", ""),
                            target_dir=arguments.get("target_dir", ""),
                            reference_files=arguments.get("reference_files", []),
                            timeout_seconds=arguments.get("timeout_seconds"),
                            conversation_id=self.context_manager.current_conversation_id
                        )

                    elif tool_name == "wait_sub_agent":
                        wait_timeout = arguments.get("timeout_seconds")
                        if not wait_timeout:
                            task_ref = self.sub_agent_manager.lookup_task(
                                task_id=arguments.get("task_id"),
                                agent_id=arguments.get("agent_id")
                            )
                            if task_ref:
                                wait_timeout = task_ref.get("timeout_seconds")
                        result = self.sub_agent_manager.wait_for_completion(
                            task_id=arguments.get("task_id"),
                            agent_id=arguments.get("agent_id"),
                            timeout_seconds=wait_timeout
                        )

                    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")
                        )

                    elif tool_name == "trigger_easter_egg":
                        result = self.easter_egg_manager.trigger_effect(arguments.get("effect"))

                    else:
                        result = {"success": False, "error": f"未知工具: {tool_name}"}

                except Exception as e:
                    logger.error(f"工具执行失败: {tool_name} - {e}")
                    result = {"success": False, "error": f"工具执行异常: {str(e)}"}

                return json.dumps(result, ensure_ascii=False)

    async def confirm_action(self, action: str, arguments: Dict) -> bool:
                """确认危险操作"""
                print(f"\n{OUTPUT_FORMATS['confirm']} 需要确认的操作:")
                print(f"  操作: {action}")
                print(f"  参数: {json.dumps(arguments, ensure_ascii=False, indent=2)}")

                response = input("\n是否继续? (y/n): ").strip().lower()
                return response == 'y'
