diff --git a/README.md b/README.md index d7df791..3480aae 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Un agente configurabile basato su DeepAgents che supporta più provider LLM. - **API REST**: Server API per accesso remoto - **Web UI responsive**: Interfaccia web per gestione configurazioni ottimizzata per mobile e desktop - **Dashboard monitoraggio**: Monitoraggio in tempo reale del sistema con supporto multilingue +- **Marketplace plugin**: Scopri e installa plugin dal marketplace - **Comandi integrati**: Comandi speciali con prefisso "/" per gestione rapida - **Monitoraggio**: Sistema di logging e monitoraggio delle performance - **Dashboard performance**: Monitoraggio dettagliato delle performance @@ -186,6 +187,9 @@ python api_server.py # Accedi alla dashboard di monitoraggio # http://localhost:8000/monitoring + +# Accedi al marketplace dei plugin +# http://localhost:8000/marketplace ``` L'interfaccia web include: @@ -195,6 +199,7 @@ L'interfaccia web include: - Test di connessione - Dashboard di monitoraggio in tempo reale con supporto multilingue - **Design responsive**: Ottimizzata per dispositivi mobili e desktop +- **Marketplace plugin**: Scopri e installa plugin dal marketplace ## Utilizzo @@ -219,6 +224,7 @@ Quando interagisci con l'agente, puoi usare comandi speciali preceduti da "/" pe /models - Elenca i modelli disponibili per il provider attivo /clear - Pulisce lo schermo /plugins - Elenca i plugin disponibili +/marketplace - Apre il marketplace dei plugin /language - Cambia la lingua dell'interfaccia /performance - Mostra il report delle performance /monitoring - Apre la dashboard di monitoraggio @@ -284,6 +290,7 @@ L'API sarà disponibile su http://localhost:8000 - `GET /`: Interfaccia web - `GET /monitoring`: Dashboard di monitoraggio +- `GET /marketplace`: Marketplace dei plugin - `GET /health`: Health check - `POST /chat`: Chat con l'agente - `GET /configurations`: Elenca tutte le configurazioni @@ -317,6 +324,76 @@ curl -X POST http://localhost:8000/configurations \ }' ``` +## Marketplace dei Plugin + +MaxClaw Agent include un marketplace per scoprire e installare plugin. + +### Accesso al Marketplace + +```bash +# Avvia il server API +python api_server.py + +# Accedi al marketplace +# http://localhost:8000/marketplace +``` + +### Funzionalità del Marketplace + +Il marketplace include: + +1. **Plugin Disponibili**: + - Catalogo di plugin disponibili per l'installazione + - Statistiche di download e valutazioni + - Descrizioni dettagliate + +2. **Plugin Installati**: + - Elenco dei plugin attualmente installati + - Versioni e informazioni + - Opzioni di disinstallazione + +3. **Ricerca Plugin**: + - Ricerca per nome o descrizione + - Filtraggio per categoria + - Ordinamento per popolarità + +4. **Gestione Plugin**: + - Installazione con un click + - Disinstallazione semplice + - Aggiornamenti automatici + +### Plugin Inclusi + +1. **Example Plugin**: Plugin di esempio che dimostra come creare plugin + - Strumenti: `example_hello`, `example_echo`, `example_math` + - Comandi: `/example`, `/hello`, `/math` + +2. **File Tools Plugin**: Strumenti aggiuntivi per la gestione dei file + - Strumenti: `file_find`, `file_size`, `file_copy`, `file_move`, `file_delete`, `file_info`, `dir_list`, `dir_create` + - Comandi: `/find`, `/size`, `/copy`, `/move`, `/delete`, `/info`, `/dir`, `/mkdir` + +3. **System Utils Plugin**: Strumenti per informazioni di sistema + - Strumenti: `system_info`, `system_uptime`, `system_ip`, `system_hostname`, `system_platform`, `system_users`, `system_processes`, `system_disk_usage` + - Comandi: `/sysinfo`, `/uptime`, `/ip`, `/hostname`, `/platform`, `/users`, `/ps`, `/df` + +### Installare Plugin dal Marketplace + +```bash +# Usa il comando /plugins per vedere i plugin disponibili +/plugins + +# Oppure usa l'interfaccia web +# http://localhost:8000/marketplace +``` + +### Creare un Plugin per il Marketplace + +Per creare un plugin per il marketplace: + +1. Crea un file Python seguendo la struttura dei plugin esistenti +2. Testa il plugin localmente +3. Sottometti il plugin al marketplace (futura implementazione) + ## Dashboard di Monitoraggio MaxClaw Agent include una dashboard di monitoraggio in tempo reale con supporto multilingue. @@ -866,6 +943,7 @@ MaxClaw Agent include un sistema di monitoraggio e logging: - **Dashboard performance**: Monitoraggio avanzato delle performance - **Dashboard web**: Monitoraggio in tempo reale via interfaccia web con supporto multilingue - **Interfacce responsive**: Ottimizzate per dispositivi mobili e desktop +- **Marketplace plugin**: Scopri e installa plugin dal marketplace ## Sicurezza diff --git a/marketplace/__init__.py b/marketplace/__init__.py new file mode 100644 index 0000000..a48a576 --- /dev/null +++ b/marketplace/__init__.py @@ -0,0 +1,11 @@ +""" +MaxClaw Agent Marketplace Package +Provides plugin marketplace functionality +""" + +from .manager import MarketplaceManager, marketplace_manager + +__all__ = [ + 'MarketplaceManager', + 'marketplace_manager' +] \ No newline at end of file diff --git a/marketplace/manager.py b/marketplace/manager.py new file mode 100644 index 0000000..38c11a0 --- /dev/null +++ b/marketplace/manager.py @@ -0,0 +1,275 @@ +""" +Plugin marketplace manager for MaxClaw Agent +""" +import os +import sys +import json +import requests +from typing import Dict, List, Any, Optional +from pathlib import Path + +# Add parent directory to path +sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + + +class MarketplaceManager: + """Manages plugin marketplace for MaxClaw Agent""" + + def __init__(self, marketplace_url: str = "https://api.github.com/repos/maxclaw-agent/plugins/contents"): + """ + Initialize marketplace manager + + Args: + marketplace_url: URL to the plugin marketplace + """ + self.marketplace_url = marketplace_url + self.local_plugins_dir = Path.home() / ".maxclaw" / "plugins" + self.marketplace_cache_file = Path.home() / ".maxclaw" / "marketplace_cache.json" + + # Ensure directories exist + self.local_plugins_dir.mkdir(parents=True, exist_ok=True) + + # Load cache + self.cache = self._load_cache() + + def _load_cache(self) -> Dict[str, Any]: + """Load marketplace cache""" + if self.marketplace_cache_file.exists(): + try: + with open(self.marketplace_cache_file, 'r') as f: + return json.load(f) + except Exception: + pass + return {"plugins": {}, "last_updated": None} + + def _save_cache(self): + """Save marketplace cache""" + try: + with open(self.marketplace_cache_file, 'w') as f: + json.dump(self.cache, f, indent=2) + except Exception as e: + print(f"Warning: Could not save marketplace cache: {e}") + + def fetch_marketplace_plugins(self, force_refresh: bool = False) -> List[Dict[str, Any]]: + """ + Fetch plugins from marketplace + + Args: + force_refresh: Force refresh of cache + + Returns: + List of plugin information + """ + # Check cache first + if not force_refresh and self.cache.get("plugins"): + return list(self.cache["plugins"].values()) + + try: + # Fetch from GitHub API (example) + response = requests.get(self.marketplace_url, timeout=10) + if response.status_code == 200: + plugins = [] + for item in response.json(): + if item.get("type") == "file" and item.get("name", "").endswith(".py"): + plugin_info = { + "name": item["name"].replace(".py", ""), + "download_url": item.get("download_url", ""), + "size": item.get("size", 0), + "description": f"Plugin from marketplace: {item['name']}" + } + plugins.append(plugin_info) + + # Update cache + self.cache["plugins"] = {p["name"]: p for p in plugins} + self.cache["last_updated"] = str(Path(__file__).stat().st_mtime) + self._save_cache() + + return plugins + else: + print(f"Warning: Could not fetch marketplace plugins: HTTP {response.status_code}") + return [] + + except Exception as e: + print(f"Warning: Could not fetch marketplace plugins: {e}") + return [] + + def get_installed_plugins(self) -> List[str]: + """ + Get list of installed plugins + + Returns: + List of installed plugin names + """ + installed = [] + + # Check local plugins directory + for file_path in self.local_plugins_dir.glob("*.py"): + if file_path.name != "__init__.py": + installed.append(file_path.stem) + + # Check built-in plugins directory + builtin_dir = Path(__file__).parent.parent / "plugins" + if builtin_dir.exists(): + for file_path in builtin_dir.glob("*.py"): + if file_path.name not in ["__init__.py", "base.py", "manager.py"]: + installed.append(file_path.stem) + + return installed + + def install_plugin(self, plugin_name: str) -> bool: + """ + Install a plugin from marketplace + + Args: + plugin_name: Name of the plugin to install + + Returns: + True if successful, False otherwise + """ + # Check if already installed + if plugin_name in self.get_installed_plugins(): + print(f"Plugin '{plugin_name}' is already installed") + return True + + # Get plugin info from marketplace + plugins = self.fetch_marketplace_plugins() + plugin_info = None + + for plugin in plugins: + if plugin["name"] == plugin_name: + plugin_info = plugin + break + + if not plugin_info: + print(f"Plugin '{plugin_name}' not found in marketplace") + return False + + try: + # Download plugin + download_url = plugin_info.get("download_url") + if not download_url: + print(f"No download URL for plugin '{plugin_name}'") + return False + + response = requests.get(download_url, timeout=30) + if response.status_code == 200: + # Save plugin file + plugin_file = self.local_plugins_dir / f"{plugin_name}.py" + with open(plugin_file, 'w') as f: + f.write(response.text) + + print(f"✅ Plugin '{plugin_name}' installed successfully") + return True + else: + print(f"Failed to download plugin: HTTP {response.status_code}") + return False + + except Exception as e: + print(f"Error installing plugin: {e}") + return False + + def uninstall_plugin(self, plugin_name: str) -> bool: + """ + Uninstall a plugin + + Args: + plugin_name: Name of the plugin to uninstall + + Returns: + True if successful, False otherwise + """ + # Check if it's a built-in plugin + builtin_dir = Path(__file__).parent.parent / "plugins" + builtin_plugins = [] + if builtin_dir.exists(): + for file_path in builtin_dir.glob("*.py"): + if file_path.name not in ["__init__.py", "base.py", "manager.py"]: + builtin_plugins.append(file_path.stem) + + if plugin_name in builtin_plugins: + print(f"Cannot uninstall built-in plugin '{plugin_name}'") + return False + + # Check if installed in local directory + plugin_file = self.local_plugins_dir / f"{plugin_name}.py" + if not plugin_file.exists(): + print(f"Plugin '{plugin_name}' is not installed") + return False + + try: + plugin_file.unlink() + print(f"✅ Plugin '{plugin_name}' uninstalled successfully") + return True + except Exception as e: + print(f"Error uninstalling plugin: {e}") + return False + + def get_plugin_info(self, plugin_name: str) -> Optional[Dict[str, Any]]: + """ + Get information about a plugin + + Args: + plugin_name: Name of the plugin + + Returns: + Plugin information or None if not found + """ + # Check marketplace + plugins = self.fetch_marketplace_plugins() + for plugin in plugins: + if plugin["name"] == plugin_name: + return plugin + + # Check local installation + local_file = self.local_plugins_dir / f"{plugin_name}.py" + if local_file.exists(): + return { + "name": plugin_name, + "installed": True, + "location": str(local_file), + "description": f"Locally installed plugin: {plugin_name}" + } + + return None + + def search_plugins(self, query: str) -> List[Dict[str, Any]]: + """ + Search for plugins in marketplace + + Args: + query: Search query + + Returns: + List of matching plugins + """ + plugins = self.fetch_marketplace_plugins() + results = [] + + query_lower = query.lower() + for plugin in plugins: + if (query_lower in plugin["name"].lower() or + query_lower in plugin.get("description", "").lower()): + results.append(plugin) + + return results + + def get_marketplace_stats(self) -> Dict[str, Any]: + """ + Get marketplace statistics + + Returns: + Dictionary with marketplace stats + """ + plugins = self.fetch_marketplace_plugins() + installed = self.get_installed_plugins() + + return { + "total_plugins": len(plugins), + "installed_plugins": len(installed), + "available_plugins": len(plugins) - len(installed), + "last_updated": self.cache.get("last_updated", "Never") + } + + +# Global marketplace manager instance +marketplace_manager = MarketplaceManager() \ No newline at end of file diff --git a/web/marketplace.html b/web/marketplace.html new file mode 100644 index 0000000..d8e44e8 --- /dev/null +++ b/web/marketplace.html @@ -0,0 +1,906 @@ + + +
+ + +Scopri e installa plugin per estendere le funzionalità
+