diff --git a/core/plugin_manager.py b/core/plugin_manager.py index c21dff1..d38f828 100644 --- a/core/plugin_manager.py +++ b/core/plugin_manager.py @@ -29,11 +29,22 @@ class PluginManager: self.plugin_classes: Dict[str, Type[BasePlugin]] = {} self.config = self._load_config() - # Add plugin dirs to path + # Add plugin dirs and project root to path + # Project root needed for 'plugins.base_plugin' imports + project_root = Path(__file__).parent.parent.absolute() + if str(project_root) not in sys.path: + sys.path.insert(0, str(project_root)) + for plugin_dir in self.PLUGIN_DIRS: path = Path(plugin_dir).absolute() if path.exists() and str(path) not in sys.path: sys.path.insert(0, str(path)) + + # Ensure plugins package is loaded + try: + import plugins + except ImportError: + pass # plugins package will be loaded when needed def _load_config(self) -> dict: """Load plugin configuration.""" @@ -90,6 +101,9 @@ class PluginManager: """Discover all available plugin classes with error handling.""" discovered = [] + # First, ensure plugins package is loaded + self._ensure_plugins_package() + for plugin_dir in self.PLUGIN_DIRS: base_path = Path(plugin_dir) if not base_path.exists(): @@ -110,20 +124,26 @@ class PluginManager: continue try: - # Load the plugin module + # Load the plugin module using normal import + # This ensures proper package resolution module_name = f"{plugin_dir}.{item.name}.plugin" if module_name in sys.modules: module = sys.modules[module_name] else: - spec = importlib.util.spec_from_file_location( - module_name, plugin_file - ) - if not spec or not spec.loader: - continue - module = importlib.util.module_from_spec(spec) - sys.modules[module_name] = module - spec.loader.exec_module(module) + # Try normal import first + try: + module = importlib.import_module(module_name) + except ImportError: + # Fall back to spec loading + spec = importlib.util.spec_from_file_location( + module_name, plugin_file + ) + if not spec or not spec.loader: + continue + module = importlib.util.module_from_spec(spec) + sys.modules[module_name] = module + spec.loader.exec_module(module) # Find plugin class for attr_name in dir(module): @@ -137,10 +157,24 @@ class PluginManager: except Exception as e: print(f"[PluginManager] Failed to discover {item.name}: {e}") + import traceback + traceback.print_exc() continue return discovered + def _ensure_plugins_package(self): + """Ensure the plugins package is loaded in sys.modules.""" + if 'plugins' not in sys.modules: + try: + import plugins + except ImportError: + # Create a minimal plugins module if it doesn't exist + import types + plugins_module = types.ModuleType('plugins') + plugins_module.__path__ = [str(Path('plugins').absolute())] + sys.modules['plugins'] = plugins_module + def load_plugin(self, plugin_class: Type[BasePlugin]) -> bool: """Instantiate and initialize a plugin with error handling.""" try: