import inspect import json from typing import Dict, Any, Callable, List class ToolRegistry: """ Singleton registry for cognitive tools in the ECH0-PRIME architecture. """ _instance = None _tools: Dict[str, Dict[str, Any]] = {} def __new__(cls): if cls._instance is None: cls._instance = super(ToolRegistry, cls).__new__(cls) return cls._instance @classmethod def register(cls, name: str = None): """Decorator to register a function as a tool.""" def decorator(func: Callable): tool_name = name or func.__name__ cls.register_tool(tool_name, func) return func return decorator @classmethod def register_tool(cls, name: str, func: Callable, description: str = None): """Manually register a tool (useful for bound methods).""" sig = inspect.signature(func) doc = description or func.__doc__ or "No description provided." parameters = { "type": "object", "properties": {}, "required": [] } for param_name, param in sig.parameters.items(): if param_name == 'self': continue p_type = "string" if param.annotation == int: p_type = "integer" elif param.annotation == float: p_type = "number" elif param.annotation == bool: p_type = "boolean" elif param.annotation == dict: p_type = "object" elif param.annotation == list: p_type = "array" parameters["properties"][param_name] = { "type": p_type, "description": f"Argument {param_name}" } if param.default is inspect.Parameter.empty: parameters["required"].append(param_name) cls._tools[name] = { "name": name, "description": doc.strip(), "parameters": parameters, "func": func } @classmethod def get_schemas(cls) -> List[Dict[str, Any]]: """Returns JSON schemas for all registered tools.""" schemas = [] for tool in cls._tools.values(): schemas.append({ "name": tool["name"], "description": tool["description"], "parameters": tool["parameters"] }) return schemas @classmethod def call_tool(cls, name: str, args: Dict[str, Any]) -> Any: """Invokes a registered tool by name.""" if name not in cls._tools: return f"Error: Tool '{name}' not found." try: return cls._tools[name]["func"](**args) except Exception as e: return f"Error executing tool '{name}': {str(e)}"