""" Function registry for dynamic AI function discovery Lazy loading - functions are only imported when actually needed """ import logging from typing import Dict, Type, Optional from igny8_core.ai.base import BaseAIFunction logger = logging.getLogger(__name__) _FUNCTION_REGISTRY: Dict[str, Type[BaseAIFunction]] = {} _FUNCTION_LOADERS: Dict[str, callable] = {} def register_function(name: str, function_class: Type[BaseAIFunction]): """Register an AI function""" if not issubclass(function_class, BaseAIFunction): raise ValueError(f"{function_class} must inherit from BaseAIFunction") _FUNCTION_REGISTRY[name] = function_class logger.info(f"Registered AI function: {name}") def register_lazy_function(name: str, loader_func: callable): """Register a lazy loader for a function - will only import when needed""" _FUNCTION_LOADERS[name] = loader_func def get_function(name: str) -> Optional[Type[BaseAIFunction]]: """Get function class by name - lazy loads if not already registered""" # Check if already loaded if name in _FUNCTION_REGISTRY: return _FUNCTION_REGISTRY[name] # Try lazy loading if name in _FUNCTION_LOADERS: try: loader = _FUNCTION_LOADERS[name] fn_class = loader() _FUNCTION_REGISTRY[name] = fn_class logger.info(f"Lazy loaded AI function: {name}") return fn_class except Exception as e: logger.error(f"Failed to lazy load function {name}: {e}", exc_info=True) return None return None def list_functions() -> list: """List all registered functions""" return list(_FUNCTION_REGISTRY.keys()) def get_function_instance(name: str) -> Optional[BaseAIFunction]: """Get function instance by name - lazy loads if needed""" # Resolve alias first to support legacy function names try: from igny8_core.ai.settings import FUNCTION_ALIASES except ImportError: FUNCTION_ALIASES = {} actual_name = FUNCTION_ALIASES.get(name, name) fn_class = get_function(actual_name) if fn_class: return fn_class() return None # Register lazy loaders - functions are only imported when actually called def _load_auto_cluster(): """Lazy loader for auto_cluster function""" from igny8_core.ai.functions.auto_cluster import AutoClusterFunction return AutoClusterFunction def _load_generate_ideas(): """Lazy loader for generate_ideas function""" from igny8_core.ai.functions.generate_ideas import GenerateIdeasFunction return GenerateIdeasFunction def _load_generate_content(): """Lazy loader for generate_content function""" from igny8_core.ai.functions.generate_content import GenerateContentFunction return GenerateContentFunction def _load_generate_images(): """Lazy loader for generate_images function""" from igny8_core.ai.functions.generate_images import GenerateImagesFunction return GenerateImagesFunction def _load_auto_cluster_v2(): """Lazy loader for auto_cluster_v2 function""" from igny8_core.ai.functions.workflow_functions.auto_cluster_v2 import AutoClusterV2Function return AutoClusterV2Function def _load_generate_ideas_v2(): """Lazy loader for generate_ideas_v2 function""" from igny8_core.ai.functions.workflow_functions.generate_ideas_v2 import GenerateIdeasV2Function return GenerateIdeasV2Function register_lazy_function('auto_cluster', _load_auto_cluster) register_lazy_function('generate_ideas', _load_generate_ideas) register_lazy_function('generate_content', _load_generate_content) register_lazy_function('generate_images', _load_generate_images) register_lazy_function('auto_cluster_v2', _load_auto_cluster_v2) register_lazy_function('generate_ideas_v2', _load_generate_ideas_v2)