11import importlib
22import importlib .util
33from pathlib import Path
4- from typing import Dict
4+ from typing import Dict , Any , Type
55from agentmesh .tools .base_tool import BaseTool
66from agentmesh .common import config
77from agentmesh .common .utils .log import logger # Import the logging module
@@ -26,17 +26,75 @@ def __init__(self):
2626 if not hasattr (self , 'tool_classes' ):
2727 self .tool_classes = {} # Dictionary to store tool classes
2828
29- def load_tools (self , tools_dir : str = "agentmesh/tools" ):
29+ def load_tools (self , tools_dir : str = "" , config_dict = None ):
3030 """
3131 Load tools from both directory and configuration.
3232
3333 :param tools_dir: Directory to scan for tool modules
3434 """
35- # First, load tools from directory (for backward compatibility)
36- self ._load_tools_from_directory (tools_dir )
35+ if tools_dir :
36+ self ._load_tools_from_directory (tools_dir )
37+ self ._configure_tools_from_config ()
38+ else :
39+ self ._load_tools_from_init ()
40+ self ._configure_tools_from_config (config_dict )
41+
42+ def _load_tools_from_init (self ) -> bool :
43+ """
44+ Load tool classes from tools.__init__.__all__
3745
38- # Then, configure tools from config file
39- self ._configure_tools_from_config ()
46+ :return: True if tools were loaded, False otherwise
47+ """
48+ try :
49+ # Try to import the tools package
50+ tools_package = importlib .import_module ("agentmesh.tools" )
51+
52+ # Check if __all__ is defined
53+ if hasattr (tools_package , "__all__" ):
54+ tool_classes = tools_package .__all__
55+
56+ # Import each tool class directly from the tools package
57+ for class_name in tool_classes :
58+ try :
59+ # Skip base classes
60+ if class_name in ["BaseTool" , "ToolManager" ]:
61+ continue
62+
63+ # Get the class directly from the tools package
64+ if hasattr (tools_package , class_name ):
65+ cls = getattr (tools_package , class_name )
66+
67+ if (
68+ isinstance (cls , type )
69+ and issubclass (cls , BaseTool )
70+ and cls != BaseTool
71+ ):
72+ try :
73+ # Create a temporary instance to get the name
74+ temp_instance = cls ()
75+ tool_name = temp_instance .name
76+ # Store the class, not the instance
77+ self .tool_classes [tool_name ] = cls
78+ logger .debug (f"Loaded tool: { tool_name } from class { class_name } " )
79+ except ImportError as e :
80+ # Ignore browser_use dependency missing errors
81+ if "browser_use" in str (e ):
82+ pass
83+ else :
84+ logger .error (f"Error initializing tool class { cls .__name__ } : { e } " )
85+ except Exception as e :
86+ logger .error (f"Error initializing tool class { cls .__name__ } : { e } " )
87+ except Exception as e :
88+ logger .error (f"Error importing class { class_name } : { e } " )
89+
90+ return len (self .tool_classes ) > 0
91+ return False
92+ except ImportError :
93+ logger .warning ("Could not import agentmesh.tools package" )
94+ return False
95+ except Exception as e :
96+ logger .error (f"Error loading tools from __init__.__all__: { e } " )
97+ return False
4098
4199 def _load_tools_from_directory (self , tools_dir : str ):
42100 """Dynamically load tool classes from directory"""
@@ -83,11 +141,11 @@ def _load_tools_from_directory(self, tools_dir: str):
83141 except Exception as e :
84142 print (f"Error importing module { py_file } : { e } " )
85143
86- def _configure_tools_from_config (self ):
144+ def _configure_tools_from_config (self , config_dict = None ):
87145 """Configure tool classes based on configuration file"""
88146 try :
89147 # Get tools configuration
90- tools_config = config ().get ("tools" , {})
148+ tools_config = config_dict or config ().get ("tools" , {})
91149
92150 # Record tools that are configured but not loaded
93151 missing_tools = []
0 commit comments