Files
abot/tool_loader.py
2026-01-15 17:01:02 -08:00

81 lines
2.6 KiB
Python

import importlib
import inspect
import logging
from pathlib import Path
from types import SimpleNamespace
class ToolWrapper:
"""
Wraps a legacy tool function to provide a standard run() interface.
"""
def __init__(self, definition, func):
self.definition = definition
self.function = func
def run(self, **kwargs):
return self.function(**kwargs)
def load_tools(tools_path: Path):
registry = {}
for file in tools_path.glob("*.py"):
if file.name.startswith("_"):
continue
module_name = f"tools.{file.stem}"
try:
module = importlib.import_module(module_name)
# --------------------------------------------------
# TOOL_DEFINITION is mandatory
# --------------------------------------------------
if not hasattr(module, "TOOL_DEFINITION"):
logging.warning(f"Tool {file.name} missing TOOL_DEFINITION, skipping")
continue
tool_def = module.TOOL_DEFINITION
tool_name = tool_def.get("name", file.stem)
# --------------------------------------------------
# Preferred: explicit run()
# --------------------------------------------------
if hasattr(module, "run") and callable(module.run):
registry[tool_name] = {
"definition": tool_def,
"function": module.run,
}
logging.info(f"Loaded tool (run): {tool_name}")
continue
# --------------------------------------------------
# Legacy auto-wrap (single public function)
# --------------------------------------------------
public_funcs = [
obj for name, obj in inspect.getmembers(module, inspect.isfunction)
if not name.startswith("_")
]
if len(public_funcs) == 1:
wrapped = ToolWrapper(tool_def, public_funcs[0])
registry[tool_name] = {
"definition": tool_def,
"function": wrapped.run,
}
logging.info(f"Wrapped legacy tool: {tool_name}")
continue
# --------------------------------------------------
# Failure case
# --------------------------------------------------
logging.error(
f"Tool {file.name} has no run() and multiple public functions; skipping"
)
except Exception:
logging.error(f"Failed to load tool {file.name}", exc_info=True)
return registry