"""External tool capability detection via dynamic plugin scanning.""" import os import yaml from typing import Dict, Any, List def _get_active_plugins() -> List[str]: """Scan all plugin roots for active plugins.""" active_plugins = [] plugin_roots = ["/a0/plugins", "/a0/usr/plugins"] for root in plugin_roots: if not os.path.isdir(root): continue for plugin_name in os.listdir(root): plugin_dir = os.path.join(root, plugin_name) if not os.path.isdir(plugin_dir): continue plugin_yaml = os.path.join(plugin_dir, "plugin.yaml") if not os.path.isfile(plugin_yaml): continue # Check if plugin is active is_active = False if os.path.isfile(os.path.join(plugin_dir, ".toggle-1")): is_active = True elif os.path.isfile(os.path.join(plugin_dir, ".toggle-0")): is_active = False else: # No toggle files, check always_enabled try: with open(plugin_yaml, "r") as f: config = yaml.safe_load(f) if config and config.get("always_enabled", False): is_active = True except (yaml.YAMLError) as e: pass if is_active: active_plugins.append(plugin_name) return active_plugins def generate_capability_report(config: Dict[str, Any] = None) -> Dict[str, Any]: """Generate a capability report for all actively registered tools.""" active_plugins = _get_active_plugins() report = {} for name in active_plugins: report[name] = { "available": True, "fallback": "plugin is active", } # Add a few standard tools not represented as plugins if they exist in config if config: tools_config = config.get("external_tools", {}) for name, cfg in tools_config.items(): if name not in report: report[name] = { "available": False, "fallback": cfg.get("fallback", "not available"), } return report def check_tool(tool_name: str) -> Dict[str, Any]: """Return availability for one plugin/tool capability name.""" active_plugins = _get_active_plugins() if tool_name in active_plugins: return {"available": True, "fallback": "plugin is active"} # Also match by declared tool name inside active plugin manifests. for plugin_name in active_plugins: plugin_dir = os.path.join("/a0/usr/plugins", plugin_name) plugin_yaml = os.path.join(plugin_dir, "plugin.yaml") try: with open(plugin_yaml, "r", encoding="utf-8") as f: config = yaml.safe_load(f) or {} for tool in config.get("tools", []) or []: if tool.get("name") == tool_name: return {"available": True, "fallback": f"declared by plugin {plugin_name}"} except Exception: continue return {"available": False, "fallback": "not active or not declared"}