Rebase onto upstream (a4d95fd)
#12
@@ -32,8 +32,19 @@ class ToolRegistry:
|
||||
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()]
|
||||
"""Get tool definitions for all registered tools.
|
||||
|
||||
Supports both function tools (with to_schema) and native tools (with to_params).
|
||||
"""
|
||||
definitions = []
|
||||
for tool in self._tools.values():
|
||||
if hasattr(tool, 'to_params'): # Native Anthropic tool
|
||||
definitions.append(tool.to_params())
|
||||
elif hasattr(tool, 'to_schema'): # Function tool
|
||||
definitions.append(tool.to_schema())
|
||||
else:
|
||||
raise ValueError(f"Tool {tool.name} has no schema method (to_params or to_schema)")
|
||||
return definitions
|
||||
|
||||
async def execute(self, name: str, params: dict[str, Any]) -> str:
|
||||
"""Execute a tool by name with given parameters."""
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
"""Tests for registry duck typing support."""
|
||||
|
||||
import pytest
|
||||
from nanobot.agent.tools.registry import ToolRegistry
|
||||
from nanobot.agent.tools.anthropic.base import BaseAnthropicTool, ToolResult
|
||||
|
||||
|
||||
class MockNativeTool(BaseAnthropicTool):
|
||||
"""Mock native tool for testing."""
|
||||
api_type = "test_20250227"
|
||||
name = "native_test"
|
||||
beta_flag = "test-beta"
|
||||
|
||||
async def __call__(self, **kwargs):
|
||||
return ToolResult(output="native result")
|
||||
|
||||
def to_params(self):
|
||||
return {"type": self.api_type, "name": self.name}
|
||||
|
||||
|
||||
class MockFunctionTool:
|
||||
"""Mock function tool for testing."""
|
||||
def __init__(self):
|
||||
self.name = "function_test"
|
||||
|
||||
def to_schema(self):
|
||||
return {
|
||||
"type": "function",
|
||||
"function": {
|
||||
"name": self.name,
|
||||
"description": "Test function tool",
|
||||
"parameters": {"type": "object", "properties": {}}
|
||||
}
|
||||
}
|
||||
|
||||
async def execute(self, **kwargs):
|
||||
return "function result"
|
||||
|
||||
|
||||
def test_registry_supports_native_tools():
|
||||
"""Test registry can register and get definitions from native tools."""
|
||||
registry = ToolRegistry()
|
||||
native_tool = MockNativeTool()
|
||||
registry.register(native_tool)
|
||||
|
||||
definitions = registry.get_definitions()
|
||||
assert len(definitions) == 1
|
||||
assert definitions[0]["type"] == "test_20250227"
|
||||
assert definitions[0]["name"] == "native_test"
|
||||
|
||||
|
||||
def test_registry_supports_function_tools():
|
||||
"""Test registry still supports function tools."""
|
||||
registry = ToolRegistry()
|
||||
function_tool = MockFunctionTool()
|
||||
registry.register(function_tool)
|
||||
|
||||
definitions = registry.get_definitions()
|
||||
assert len(definitions) == 1
|
||||
assert definitions[0]["type"] == "function"
|
||||
assert definitions[0]["function"]["name"] == "function_test"
|
||||
|
||||
|
||||
def test_registry_supports_mixed_tools():
|
||||
"""Test registry can handle both native and function tools."""
|
||||
registry = ToolRegistry()
|
||||
native_tool = MockNativeTool()
|
||||
function_tool = MockFunctionTool()
|
||||
|
||||
registry.register(native_tool)
|
||||
registry.register(function_tool)
|
||||
|
||||
definitions = registry.get_definitions()
|
||||
assert len(definitions) == 2
|
||||
|
||||
# Find each tool type in definitions
|
||||
native_def = next(d for d in definitions if d.get("type") == "test_20250227")
|
||||
function_def = next(d for d in definitions if d.get("type") == "function")
|
||||
|
||||
assert native_def["name"] == "native_test"
|
||||
assert function_def["function"]["name"] == "function_test"
|
||||
|
||||
|
||||
def test_registry_rejects_tools_without_schema_method():
|
||||
"""Test registry raises error for tools with no schema method."""
|
||||
registry = ToolRegistry()
|
||||
|
||||
class BadTool:
|
||||
name = "bad"
|
||||
|
||||
registry.register(BadTool())
|
||||
|
||||
with pytest.raises(ValueError, match="has no schema method"):
|
||||
registry.get_definitions()
|
||||
Reference in New Issue
Block a user