import re
from dataclasses import dataclass
from typing import Callable


@dataclass
class Tool:
    name: str
    description: str
    run: Callable[[str], str]


class ToolRegistry:
    def __init__(self) -> None:
        self._tools: dict[str, Tool] = {}

    def register(self, tool: Tool) -> None:
        self._tools[tool.name] = tool

    def get(self, name: str) -> Tool:
        if name not in self._tools:
            raise KeyError(f"未知工具：{name}")
        return self._tools[name]

    def describe(self) -> str:
        return "\n".join(f"{tool.name}: {tool.description}" for tool in self._tools.values())


def calculator(expression: str) -> str:
    if not re.fullmatch(r"[0-9+\-*/(). ]+", expression):
        return "计算失败：表达式包含不允许字符"
    return str(eval(expression, {"__builtins__": {}}, {}))


def local_search(query: str) -> str:
    knowledge = {
        "ReAct": "ReAct 把推理痕迹和工具行动放在同一个循环中。",
        "Plan-and-Solve": "Plan-and-Solve 先规划，再按步骤执行。",
        "Reflection": "Reflection 通过审查反馈改进下一轮答案。",
    }
    return knowledge.get(query.strip(), "没有找到本地资料")


def default_registry() -> ToolRegistry:
    registry = ToolRegistry()
    registry.register(Tool("calculator", "执行基础数学表达式", calculator))
    registry.register(Tool("local_search", "查询本地 Agent 范式说明", local_search))
    return registry


if __name__ == "__main__":
    tools = default_registry()
    print(tools.describe())
    print(tools.get("calculator").run("18 * 7 + 6"))
