"""工具注册表 - 工具系统重构 Phase 6.1""" from collections import defaultdict from typing import Any, Callable from app.agents.tools.manifest import HookConfig, ToolManifest class ToolRegistry: """工具注册表 统一管理所有工具的注册、发现和调用。 支持工具元数据、权限分类、Hook 拦截。 """ def __init__(self): self._tools: dict[str, ToolManifest] = {} self._executors: dict[str, Callable] = {} self._hooks: dict[str, list[HookConfig]] = defaultdict(list) def register( self, manifest: ToolManifest, executor: Callable, hooks: list[HookConfig] | None = None ) -> None: """注册工具 Args: manifest: 工具元数据 executor: 工具执行函数 hooks: 可选的 Hook 配置列表 """ if manifest.name in self._tools: raise ValueError(f"Tool already registered: {manifest.name}") self._tools[manifest.name] = manifest self._executors[manifest.name] = executor if hooks: for hook in hooks: self._hooks[manifest.name].append(hook) def unregister(self, name: str) -> bool: """注销工具 Args: name: 工具名称 Returns: 是否成功注销 """ if name not in self._tools: return False del self._tools[name] del self._executors[name] if name in self._hooks: del self._hooks[name] return True def get(self, name: str) -> ToolManifest | None: """获取工具元数据 Args: name: 工具名称 Returns: 工具元数据,不存在返回 None """ return self._tools.get(name) def get_executor(self, name: str) -> Callable | None: """获取工具执行器 Args: name: 工具名称 Returns: 工具执行函数,不存在返回 None """ return self._executors.get(name) def get_hooks(self, name: str) -> list[HookConfig]: """获取工具的 Hook 配置 Args: name: 工具名称 Returns: Hook 配置列表 """ return self._hooks.get(name, []) def list_all(self) -> list[ToolManifest]: """列出所有已注册的工具 Returns: 工具元数据列表 """ return list(self._tools.values()) def list_by_category(self, category: Any) -> list[ToolManifest]: """按类别列出工具 Args: category: 工具类别 Returns: 该类别下的所有工具 """ return [t for t in self._tools.values() if t.category == category] def list_by_permission(self, permission: Any) -> list[ToolManifest]: """按权限级别列出工具 Args: permission: 权限级别 Returns: 该权限级别下的所有工具 """ return [t for t in self._tools.values() if t.permission_class == permission] def search_by_tag(self, tag: str) -> list[ToolManifest]: """按标签搜索工具 Args: tag: 标签 Returns: 包含该标签的工具 """ return [t for t in self._tools.values() if tag in t.tags] def search_by_name(self, keyword: str) -> list[ToolManifest]: """按名称关键词搜索工具 Args: keyword: 关键词 Returns: 名称包含关键词的工具 """ keyword = keyword.lower() return [t for t in self._tools.values() if keyword in t.name.lower()] def get_requires_confirmation(self, name: str) -> bool: """检查工具是否需要确认 Args: name: 工具名称 Returns: 是否需要确认 """ manifest = self._tools.get(name) return manifest.requires_confirmation if manifest else False def get_is_streaming(self, name: str) -> bool: """检查工具是否支持流式执行 Args: name: 工具名称 Returns: 是否支持流式 """ manifest = self._tools.get(name) return manifest.is_streaming if manifest else False def clear(self) -> None: """清空注册表""" self._tools.clear() self._executors.clear() self._hooks.clear() def __len__(self) -> int: return len(self._tools) def __contains__(self, name: str) -> bool: return name in self._tools def __iter__(self): return iter(self._tools.values()) # 全局单例实例 _global_registry: ToolRegistry | None = None def get_tool_registry() -> ToolRegistry: """获取全局工具注册表单例 Returns: 全局 ToolRegistry 实例 """ global _global_registry if _global_registry is None: _global_registry = ToolRegistry() return _global_registry def reset_tool_registry() -> None: """重置全局工具注册表(用于测试)""" global _global_registry if _global_registry is not None: _global_registry.clear() _global_registry = None