# src/haive/core/engine/agent/registry.py"""Agent registry module for managing and resolving agent classes.from typing import AnyThis module provides a registry for associating agent configurations withtheir implementing classes, allowing dynamic discovery and resolution."""importimportlibimportlogginglogger=logging.getLogger(__name__)# Global registry mapping config classes to agent classesAGENT_REGISTRY:dict[type,type]={}
[docs]defregister_agent(config_class:type):"""Register an agent class with its configuration class. Args: config_class: The agent config class to register Returns: A decorator function that registers the agent class """defdecorator(agent_class:type):"""Decorator. Args: agent_class: [TODO: Add description] """AGENT_REGISTRY[config_class]=agent_classlogger.debug(f"Registered agent {agent_class.__name__} for config {config_class.__name__}")returnagent_classreturndecorator
[docs]defresolve_agent_class(config_class:type)->type|None:"""Resolve an agent class for a given config class. First checks the registry, then tries to resolve by naming convention, looking in the same module or sibling modules. Args: config_class: The agent config class to find an implementation for Returns: The agent class if found, None otherwise """# Try to find agent class in registryagent_class=AGENT_REGISTRY.get(config_class)# Try class attribute if not in registryifagent_classisNoneandhasattr(config_class,"agent_class"):agent_class=config_class.agent_class# Try to resolve by naming conventionifagent_classisNone:agent_class=_resolve_agent_class_by_name(config_class)ifagent_classisNone:logger.warning(f"No agent class found for {config_class.__name__}")returnagent_class
def_resolve_agent_class_by_name(config_class:type)->type|None:"""Try to resolve agent class by naming convention. Args: config_class: The agent config class to find an implementation for Returns: The agent class if found, None otherwise """agent_class_name=config_class.__name__.replace("Config","")# Try same moduletry:module=importlib.import_module(config_class.__module__)agent_class=getattr(module,agent_class_name,None)ifagent_class:returnagent_classexcept(ImportError,AttributeError):pass# Try sibling moduletry:base_module=config_class.__module__.rsplit(".",1)[0]forsuffixin["agent","impl",""]:try:agent_module=importlib.import_module(f"{base_module}.{suffix}")agent_class=getattr(agent_module,agent_class_name,None)ifagent_class:returnagent_classexcept(ImportError,AttributeError):continueexceptException:passreturnNone
[docs]defregister_agents_from_module(module_path:str)->int:"""Register all agents from a module. Args: module_path: The module path to scan for agents Returns: Number of agents registered """try:module=importlib.import_module(module_path)count=0fornameindir(module):obj=getattr(module,name)# Look for classes with a ClassVar[Type] annotation named# "config_class"ifisinstance(obj,type)andhasattr(obj,"__annotations__"):annotations=getattr(obj,"__annotations__",{})if"config_class"inannotations:config_class=getattr(obj,"config_class",None)ifconfig_classandisinstance(config_class,type):AGENT_REGISTRY[config_class]=objcount+=1logger.debug(f"Registered agent {obj.__name__} for config {config_class.__name__}")returncountexceptImportErrorase:logger.exception(f"Error importing module {module_path}: {e}")return0