Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored tools.py into ToolBox class for modular tools. #129

Open
wants to merge 3 commits into
base: claude-eng-plus-agents
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__pycache__/
11 changes: 6 additions & 5 deletions Plus agents/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from anthropic import Anthropic
from config import ANTHROPIC_API_KEY, COORDINATOR_MODEL, COORDINATOR_BASE_PROMPT, CONTINUATION_EXIT_PHRASE
from tool_agent import ToolAgent
from tools import tool_definitions, execute_tool
from tool_box import ToolBox
from utils import parse_goals, print_panel

logging.basicConfig(level=logging.INFO)
Expand All @@ -13,7 +13,8 @@ class Coordinator:
def __init__(self):
self.client = Anthropic(api_key=ANTHROPIC_API_KEY)
self.conversation_history = []
self.tool_agents = {tool["name"]: ToolAgent(tool["name"], tool["description"], tool["input_schema"]) for tool in tool_definitions}
self.toolbox = ToolBox()
self.tool_agents = {tool["name"]: ToolAgent(tool["name"], tool["description"], tool["input_schema"]) for tool in self.toolbox.tool_definitions}
self.current_goals = []
self.automode = False

Expand Down Expand Up @@ -45,7 +46,7 @@ def chat(self, user_input, image_base64=None, max_retries=3):
max_tokens=4000,
system=COORDINATOR_BASE_PROMPT,
messages=messages,
tools=tool_definitions
tools=self.toolbox.tool_definitions
)

self.conversation_history.append({"role": "user", "content": message_content})
Expand All @@ -61,7 +62,7 @@ def chat(self, user_input, image_base64=None, max_retries=3):
logger.info(f"Tool input: {tool_input}")

# Execute the actual tool function
actual_result = execute_tool(tool_name, tool_input)
actual_result = self.toolbox.execute_tool(tool_name, tool_input)

logger.info(f"Tool result: {actual_result}")

Expand All @@ -87,7 +88,7 @@ def chat(self, user_input, image_base64=None, max_retries=3):
max_tokens=2000,
system=COORDINATOR_BASE_PROMPT,
messages=self.conversation_history,
tools=tool_definitions
tools=self.toolbox.tool_definitions
)

# Process the continuation response
Expand Down
52 changes: 52 additions & 0 deletions Plus agents/tool_box.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import os
import sys
import json
import importlib
import inspect

class ToolBox:
def __init__(self):
self.tools = []
self.tool_definitions = []
tools_folder = os.path.join(os.path.dirname(__file__), "tools")
self.tools = self.import_tools(tools_folder)

def import_tools(self, subfolder_path):
sys.path.append(os.path.dirname(subfolder_path))

for filename in os.listdir(subfolder_path):
if filename.endswith('.py') and not filename.startswith('__') and filename != 'base_tool.py':
file_path = os.path.join(subfolder_path, filename)
module_name = f"tools.{os.path.splitext(filename)[0]}"

try:
spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

# Import base_tool here to ensure it's in the module's namespace
from tools.base_tool import base_tool

for name, obj in inspect.getmembers(module):
if inspect.isclass(obj):
try:
if issubclass(obj, base_tool) and obj is not base_tool:
tool_instance = obj()
self.tools.append(tool_instance)
self.tool_definitions.append(tool_instance.definition)
except TypeError as e:
print(f"TypeError when checking {name}: {e}")
print(f"obj: {obj}, base_tool: {base_tool}")
print(f"obj type: {type(obj)}, base_tool type: {type(base_tool)}")
except Exception as e:
print(f"Error importing {filename}: {e}")

sys.path.remove(os.path.dirname(subfolder_path))

return self.tools

def execute_tool(self, tool_name, tool_input):
for tool in self.tools:
if tool_name == tool.name:
return tool.execute(tool_input)
return f"Unknown tool: {tool_name}"
186 changes: 0 additions & 186 deletions Plus agents/tools.py

This file was deleted.

Empty file added Plus agents/tools/__init__.py
Empty file.
11 changes: 11 additions & 0 deletions Plus agents/tools/base_tool.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from abc import ABC, abstractmethod
from typing import Dict, Any

class base_tool(ABC):
def __init__(self):
self.name = None
pass

@abstractmethod
def execute(self, tool_input: Dict[str, Any]) -> Any:
pass
34 changes: 34 additions & 0 deletions Plus agents/tools/create_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from tools.base_tool import base_tool

class create_file(base_tool):
def __init__(self):
super().__init__()
self.definition = {
"name": "create_file",
"description": "Create a new file at the specified path with content. Use this when you need to create a new file in the project structure.",
"input_schema": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "The path where the file should be created"
},
"content": {
"type": "string",
"description": "The content of the file"
}
},
"required": ["path", "content"]
}
}
self.name = self.definition["name"]

def execute(self, tool_input):
try:
path = tool_input["path"]
content = tool_input["content"]
with open(path, 'w') as f:
f.write(content)
return f"File created: {path}"
except Exception as e:
return f"Error creating file: {str(e)}"
29 changes: 29 additions & 0 deletions Plus agents/tools/create_folder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import os
from tools.base_tool import base_tool

class create_folder(base_tool):
def __init__(self):
super().__init__()
self.definition = {
"name": "create_folder",
"description": "Create a new folder at the specified path. Use this when you need to create a new directory in the project structure.",
"input_schema": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "The path where the folder should be created"
}
},
"required": ["path"]
}
}
self.name = self.definition["name"]

def execute(self, tool_input):
try:
path = tool_input["path"]
os.makedirs(path, exist_ok=True)
return f"Folder created: {path}"
except Exception as e:
return f"Error creating folder: {str(e)}"
Loading