"""HostExecutor:in-process 工具调用,沿用原 `Tool.execute` 行为。 用途: - 本地 dogfood / 单租户 / Step 1 默认 backend - Step 3 docker backend 引入后,承担"信任域 = host"那一半(read/write/edit/glob/ grep/load_skill/web_*/seedream/seedance,§7.5 #6),DockerExecutor 内部组合本类 + docker exec 处理 shell/run_python。 行为兼容性:错误分支与原 `AgentLoop._execute_tool_call` 三段(unknown tool / bad args / 抛异常)语义对齐 —— 都包成 `[Error] ...` content 返回,exit_code 区分内部用。 """ from __future__ import annotations from typing import Any, Dict, List from .executor import ExecCtx, Executor, ToolResult from tools.base import Tool class HostExecutor(Executor): def __init__(self, tools: Dict[str, Tool]) -> None: self._tools = tools def has_tool(self, name: str) -> bool: return name in self._tools def schemas(self) -> List[Dict[str, Any]]: return [t.schema for t in self._tools.values()] def call_tool(self, name: str, args: Dict[str, Any], ctx: ExecCtx) -> ToolResult: tool = self._tools.get(name) if tool is None: return ToolResult(content=f"[Error] unknown tool: {name}", exit_code=2) try: result = tool.execute(**args) except TypeError as e: return ToolResult(content=f"[Error] bad arguments to {name}: {e}", exit_code=2) except Exception as e: return ToolResult( content=f"[Error executing {name}] {type(e).__name__}: {e}", exit_code=1, ) if not isinstance(result, str): result = str(result) return ToolResult(content=result, exit_code=0)