"""Plugin marketplace/registry: discover, install, and manage custom heads.""" from __future__ import annotations from typing import Any from fastapi import APIRouter from fusionagi._logger import logger router = APIRouter() # In-memory plugin registry (in production, back with DB) _registry: dict[str, dict[str, Any]] = {} @router.get("/plugins") def list_plugins(category: str | None = None) -> dict[str, Any]: """List available and installed plugins (custom heads).""" from fusionagi.agents.head_registry import HeadRegistry registry = HeadRegistry() installed = registry.list_heads() plugins = list(_registry.values()) if category: plugins = [p for p in plugins if p.get("category") == category] return { "available": plugins, "installed": [{"name": name, "status": "active"} for name in installed], "categories": ["reasoning", "creativity", "research", "safety", "custom"], } @router.post("/plugins") def register_plugin(body: dict[str, Any]) -> dict[str, Any]: """Register a plugin in the marketplace.""" plugin_id = body.get("id", "") if not plugin_id: return {"error": "Plugin ID required"} entry = { "id": plugin_id, "name": body.get("name", plugin_id), "description": body.get("description", ""), "version": body.get("version", "0.1.0"), "author": body.get("author", ""), "category": body.get("category", "custom"), "entry_point": body.get("entry_point", ""), "status": "available", } _registry[plugin_id] = entry logger.info("Plugin registered", extra={"plugin_id": plugin_id}) return entry @router.post("/plugins/{plugin_id}/install") def install_plugin(plugin_id: str) -> dict[str, Any]: """Install a plugin from the registry.""" if plugin_id not in _registry: return {"error": f"Plugin not found: {plugin_id}"} _registry[plugin_id]["status"] = "installed" logger.info("Plugin installed", extra={"plugin_id": plugin_id}) return {"plugin_id": plugin_id, "status": "installed"} @router.delete("/plugins/{plugin_id}") def uninstall_plugin(plugin_id: str) -> dict[str, Any]: """Uninstall a plugin.""" if plugin_id in _registry: _registry[plugin_id]["status"] = "available" logger.info("Plugin uninstalled", extra={"plugin_id": plugin_id}) return {"plugin_id": plugin_id, "status": "uninstalled"}