Files
beaver_project/app-instance/backend-old/nanobot/agent/tools/registry.py

97 lines
3.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""工具注册中心。
职责很单一:
1. 保存当前可用工具实例;
2. 向 LLM 暴露 function schema
3. 在执行前做基础参数校验,并把异常统一转成文本结果。
"""
from typing import Any
from nanobot.agent.tools.base import Tool
class ToolRegistry:
"""
Registry for agent tools.
Allows dynamic registration and execution of tools.
"""
def __init__(self):
# 工具名到实例的映射表;工具名在整个 registry 内必须唯一。
self._tools: dict[str, Tool] = {}
def register(self, tool: Tool) -> None:
"""注册一个工具实例。"""
self._tools[tool.name] = tool
def clone(self) -> "ToolRegistry":
"""创建一个浅拷贝,复用同一批工具实例。"""
# 这里不深拷贝工具对象,因为很多工具本身持有运行时状态或外部连接。
# 当前需求只是“在一个请求里临时附加额外工具”,复用实例即可。
other = ToolRegistry()
other._tools = dict(self._tools)
return other
def unregister(self, name: str) -> None:
"""Unregister a tool by name."""
self._tools.pop(name, None)
def get(self, name: str) -> Tool | None:
"""Get a tool by name."""
return self._tools.get(name)
def has(self, name: str) -> bool:
"""Check if a tool is registered."""
return name in self._tools
def get_definitions(self) -> list[dict[str, Any]]:
"""Get all tool definitions in OpenAI format."""
return [tool.to_schema() for tool in self._tools.values()]
async def execute(self, name: str, params: dict[str, Any]) -> str:
"""
Execute a tool by name with given parameters.
Args:
name: Tool name.
params: Tool parameters.
Returns:
Tool execution result as string.
Raises:
KeyError: If tool not found.
"""
_hint = "\n\n[Analyze the error above and try a different approach.]"
tool = self._tools.get(name)
if not tool:
return f"Error: Tool '{name}' not found. Available: {', '.join(self.tool_names)}"
try:
# schema 级参数校验放在真正调用前做,尽量把错误反馈成模型能自修复的文本。
errors = tool.validate_params(params)
if errors:
return f"Error: Invalid parameters for tool '{name}': " + "; ".join(errors) + _hint
result = await tool.execute(**params)
# 约定:工具若返回以 Error 开头的文本,说明是业务失败而非程序崩溃。
if isinstance(result, str) and result.startswith("Error"):
return result + _hint
return result
except Exception as e:
# 保持“不抛异常到模型层”的接口语义,统一回成可读文本。
return f"Error executing {name}: {str(e)}" + _hint
@property
def tool_names(self) -> list[str]:
"""Get list of registered tool names."""
return list(self._tools.keys())
def __len__(self) -> int:
return len(self._tools)
def __contains__(self, name: str) -> bool:
return name in self._tools