Skip to main content
Glama
manager.py4.54 kB
from typing import Dict, List, Optional, Type from pathlib import Path import importlib import inspect from .base import StandardsPlugin, Standard class PluginManager: """Manages loading and accessing standards plugins""" def __init__(self, plugins_dir: Path, data_dir: Path): self.plugins_dir = plugins_dir self.data_dir = data_dir self.plugins: Dict[str, StandardsPlugin] = {} self.plugin_classes: Dict[str, Type[StandardsPlugin]] = {} self._discover_plugins() self._load_plugins() def _discover_plugins(self): """Discover available plugin classes""" self.plugin_classes = {} # Import all Python files in plugins directory for file in self.plugins_dir.glob("*.py"): if file.name.startswith("_") or file.name in ["base.py", "manager.py"]: continue module_name = f"src.plugins.{file.stem}" try: module = importlib.import_module(module_name) # Find StandardsPlugin subclasses for name, obj in inspect.getmembers(module, inspect.isclass): if (issubclass(obj, StandardsPlugin) and obj != StandardsPlugin and obj.__module__ == module_name): # Create a temporary instance to get the name temp_instance = obj(self.data_dir) self.plugin_classes[temp_instance.name] = obj except Exception as e: print(f"Error loading plugin module {module_name}: {e}") def _load_plugins(self): """Instantiate all discovered plugins""" for plugin_name, plugin_class in self.plugin_classes.items(): try: # Create data directory for plugin if it doesn't exist plugin_data_dir = self.data_dir / plugin_name plugin_data_dir.mkdir(exist_ok=True, parents=True) # Instantiate plugin plugin = plugin_class(plugin_data_dir) self.plugins[plugin.name] = plugin print(f"Loaded plugin: {plugin.name} v{plugin.version}") except Exception as e: print(f"Error instantiating plugin {plugin_name}: {e}") def get_all_standards(self) -> List[Standard]: """Get all standards from all plugins""" standards = [] for plugin in self.plugins.values(): standards.extend(plugin.load_standards()) return standards def get_standards_by_category(self, category: str) -> List[Standard]: """Get standards filtered by category""" standards = [] for plugin in self.plugins.values(): plugin_standards = plugin.load_standards() standards.extend([s for s in plugin_standards if s.category == category]) return standards def search_standards(self, query: str, categories: Optional[List[str]] = None, tags: Optional[List[str]] = None) -> List[Standard]: """Search standards by query text, categories, and tags""" all_standards = self.get_all_standards() results = [] query_lower = query.lower() if query else "" for standard in all_standards: # Filter by categories if categories and standard.category not in categories: continue # Filter by tags if tags and not any(tag in standard.tags for tag in tags): continue # Search in text fields if query: searchable_text = " ".join([ standard.title, standard.description, standard.rationale or "", standard.fix_guidance or "", " ".join(standard.tags) ]).lower() if query_lower not in searchable_text: continue results.append(standard) return results def get_plugin_info(self) -> List[Dict[str, str]]: """Get information about loaded plugins""" return [ { "name": plugin.name, "version": plugin.version, "description": plugin.description } for plugin in self.plugins.values() ]

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ivangrynenko/devstandards_mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server