diff --git a/docs/swarms/cli/cli_examples.md b/docs/swarms/cli/cli_examples.md index c3ec9997..d3a6ecd9 100644 --- a/docs/swarms/cli/cli_examples.md +++ b/docs/swarms/cli/cli_examples.md @@ -76,6 +76,41 @@ swarms check-login ✓ Authentication verified ``` +#### Run Environment Setup Check + +```bash +swarms setup-check +``` + +**Expected Output:** +``` +🔍 Running Swarms Environment Setup Check + +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Environment Check Results │ +├─────────┬─────────────────────────┬─────────────────────────────────────────┤ +│ Status │ Check │ Details │ +├─────────┼─────────────────────────┼─────────────────────────────────────────┤ +│ ✓ │ Python Version │ Python 3.11.5 │ +│ ✓ │ Swarms Version │ Current version: 8.1.1 │ +│ ✓ │ API Keys │ API keys found: OPENAI_API_KEY │ +│ ✓ │ Dependencies │ All required dependencies available │ +│ ✓ │ Environment File │ .env file exists with 1 API key(s) │ +│ ⚠ │ Workspace Directory │ WORKSPACE_DIR environment variable is not set │ +└─────────┴─────────────────────────┴─────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Setup Check Complete │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ ⚠️ Some checks failed. Please review the issues above. │ +└─────────────────────────────────────────────────────────────────────────────┘ + +💡 Recommendations: + 1. Set WORKSPACE_DIR environment variable: export WORKSPACE_DIR=/path/to/your/workspace + +Run 'swarms setup-check' again after making changes to verify. +``` + ## Agent Management Examples ### 2. Creating Custom Agents @@ -549,9 +584,34 @@ This will provide detailed output including: - Internal state changes - Performance metrics +## Environment Setup + +### 12. Environment Verification + +The `setup-check` command is essential for ensuring your environment is properly configured: + +```bash +# Run comprehensive environment check +swarms setup-check +``` + +This command checks: +- Python version compatibility (3.10+) +- Swarms package version and updates +- API key configuration +- Required dependencies +- Environment file setup +- Workspace directory configuration + +**Use Cases:** +- **Before starting a new project**: Verify all requirements are met +- **After environment changes**: Confirm configuration updates +- **Troubleshooting**: Identify missing dependencies or configuration issues +- **Team onboarding**: Ensure consistent environment setup across team members + ## Best Practices -### 12. Performance Optimization +### 13. Performance Optimization #### Use Concurrent Processing ```bash @@ -579,7 +639,7 @@ swarms load-markdown \ --context-length 4000 --max-loops 2 ``` -### 13. Security Considerations +### 14. Security Considerations #### Environment Variable Usage ```bash @@ -608,6 +668,7 @@ The Swarms CLI provides a powerful and flexible interface for managing AI agents | **Agent Management** | Creating and configuring custom agents | | **Multi-Agent Workflows** | Coordinating multiple agents | | **Configuration** | YAML and markdown configuration formats | +| **Environment Setup** | Environment verification and setup checks | | **Advanced Features** | Dynamic configuration and MCP integration | | **Troubleshooting** | Common issues and solutions | | **Best Practices** | Performance and security considerations | diff --git a/docs/swarms/cli/cli_reference.md b/docs/swarms/cli/cli_reference.md index 750eb76d..7c1ad2e5 100644 --- a/docs/swarms/cli/cli_reference.md +++ b/docs/swarms/cli/cli_reference.md @@ -51,6 +51,7 @@ swarms [options] | `auto-upgrade` | Update Swarms to latest version | None | | `book-call` | Schedule strategy session | None | | `autoswarm` | Generate and execute autonomous swarm | `--task`, `--model` | +| `setup-check` | Run comprehensive environment setup check | None | ## Global Arguments @@ -154,7 +155,7 @@ swarms agent \ Generate and execute an autonomous swarm configuration. ```bash -python -m swarms.cli.main autoswarm [options] +swarms autoswarm [options] ``` | Argument | Type | Default | Required | Description | @@ -168,6 +169,58 @@ python -m swarms.cli.main autoswarm [options] swarms autoswarm --task "analyze this data" --model "gpt-4" ``` +### `setup-check` Command + +Run a comprehensive environment setup check to verify your Swarms installation and configuration. + +```bash +swarms setup-check [--verbose] +``` + +**Arguments:** +- `--verbose`: Enable detailed debug output showing version detection methods + +This command performs the following checks: +- **Python Version**: Verifies Python 3.10+ compatibility +- **Swarms Version**: Checks current version and compares with latest available +- **API Keys**: Verifies presence of common API keys in environment variables +- **Dependencies**: Ensures required packages are available +- **Environment File**: Checks for .env file existence and content +- **Workspace Directory**: Verifies WORKSPACE_DIR environment variable + +**Examples:** +```bash +# Basic setup check +swarms setup-check + +# Verbose setup check with debug information +swarms setup-check --verbose +``` + +**Expected Output:** +``` +🔍 Running Swarms Environment Setup Check + +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Environment Check Results │ +├─────────┬─────────────────────────┬─────────────────────────────────────────┤ +│ Status │ Check │ Details │ +├─────────┼─────────────────────────┼─────────────────────────────────────────┤ +│ ✓ │ Python Version │ Python 3.11.5 │ +│ ✓ │ Swarms Version │ Current version: 8.1.1 │ +│ ✓ │ API Keys │ API keys found: OPENAI_API_KEY │ +│ ✓ │ Dependencies │ All required dependencies available │ +│ ✓ │ Environment File │ .env file exists with 1 API key(s) │ +│ ✓ │ Workspace Directory │ WORKSPACE_DIR is set to: /path/to/ws │ +└─────────┴─────────────────────────┴─────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────────────────────────────────┐ +│ Setup Check Complete │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ 🎉 All checks passed! Your environment is ready for Swarms. │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + ## Error Handling The CLI provides comprehensive error handling with formatted error messages: diff --git a/swarms/cli/main.py b/swarms/cli/main.py index 5dadbfde..afa09270 100644 --- a/swarms/cli/main.py +++ b/swarms/cli/main.py @@ -1,8 +1,11 @@ import argparse import os +import sys import time import webbrowser +from pathlib import Path +from rich.align import Align from rich.console import Console from rich.panel import Panel from rich.progress import Progress, SpinnerColumn, TextColumn @@ -65,12 +68,501 @@ def show_ascii_art(): panel = Panel( Text(ASCII_ART, style=f"bold {COLORS['primary']}"), border_style=COLORS["secondary"], - title="[bold]Welcome to Swarms[/bold]", + title="[bold]Welcome to Swarms CLI[/bold]", subtitle="[dim]swarms.ai[/dim]", ) console.print(panel) +def check_workspace_dir() -> tuple[bool, str, str]: + """Check if WORKSPACE_DIR environment variable is set.""" + workspace_dir = os.getenv("WORKSPACE_DIR") + if workspace_dir: + path = Path(workspace_dir) + if path.exists(): + return ( + True, + "✓", + f"WORKSPACE_DIR is set to: {workspace_dir}", + ) + else: + return ( + False, + "⚠", + f"WORKSPACE_DIR is set but path doesn't exist: {workspace_dir}", + ) + else: + return ( + False, + "✗", + "WORKSPACE_DIR environment variable is not set", + ) + + +def check_env_file() -> tuple[bool, str, str]: + """Check if .env file exists and has content.""" + env_path = Path(".env") + if env_path.exists(): + try: + content = env_path.read_text().strip() + if content: + # Count API keys + api_keys = [ + line + for line in content.split("\n") + if "API_KEY" in line and not line.startswith("#") + ] + return ( + True, + "✓", + f".env file exists with {len(api_keys)} API key(s)", + ) + else: + return False, "⚠", ".env file exists but is empty" + except Exception as e: + return ( + False, + "✗", + f".env file exists but cannot be read: {str(e)}", + ) + else: + return False, "✗", ".env file not found in current directory" + + +def check_swarms_version( + verbose: bool = False, +) -> tuple[bool, str, str, str]: + """Check if swarms is at the latest version.""" + try: + # Get current version using multiple methods + current_version = "Unknown" + + if verbose: + console.print( + "[dim]🔍 Attempting to detect Swarms version...[/dim]" + ) + + # Method 1: Try importlib.metadata (Python 3.8+) + try: + import importlib.metadata + + current_version = importlib.metadata.version("swarms") + if verbose: + console.print( + f"[dim] ✓ Method 1 (importlib.metadata): {current_version}[/dim]" + ) + except ImportError: + if verbose: + console.print( + "[dim] ✗ Method 1 (importlib.metadata): Not available[/dim]" + ) + pass + + # Method 2: Try pkg_resources (older method) + if current_version == "Unknown": + try: + import pkg_resources + + current_version = pkg_resources.get_distribution( + "swarms" + ).version + if verbose: + console.print( + f"[dim] ✓ Method 2 (pkg_resources): {current_version}[/dim]" + ) + except ImportError: + if verbose: + console.print( + "[dim] ✗ Method 2 (pkg_resources): Not available[/dim]" + ) + pass + + # Method 3: Try direct attribute access + if current_version == "Unknown": + try: + import swarms + + current_version = getattr( + swarms, "__version__", "Unknown" + ) + if verbose: + console.print( + f"[dim] ✓ Method 3 (direct attribute): {current_version}[/dim]" + ) + except ImportError: + if verbose: + console.print( + "[dim] ✗ Method 3 (direct attribute): Import failed[/dim]" + ) + pass + + # Method 4: Try to get from pyproject.toml or setup.py + if current_version == "Unknown": + try: + import subprocess + + result = subprocess.run( + ["pip", "show", "swarms"], + capture_output=True, + text=True, + timeout=10, + ) + if result.returncode == 0: + for line in result.stdout.split("\n"): + if line.startswith("Version:"): + current_version = line.split(":", 1)[ + 1 + ].strip() + if verbose: + console.print( + f"[dim] ✓ Method 4 (pip show): {current_version}[/dim]" + ) + break + except Exception: + if verbose: + console.print( + "[dim] ✗ Method 4 (pip show): Failed[/dim]" + ) + pass + + # Method 5: Try to read from __init__.py file + if current_version == "Unknown": + try: + import swarms + + swarms_path = swarms.__file__ + if swarms_path: + init_file = os.path.join( + os.path.dirname(swarms_path), "__init__.py" + ) + if os.path.exists(init_file): + with open(init_file, "r") as f: + content = f.read() + # Look for version patterns like __version__ = "8.1.1" + import re + + version_match = re.search( + r'__version__\s*=\s*["\']([^"\']+)["\']', + content, + ) + if version_match: + current_version = version_match.group( + 1 + ) + if verbose: + console.print( + f"[dim] ✓ Method 5 (__init__.py): {current_version}[/dim]" + ) + except Exception: + if verbose: + console.print( + "[dim] ✗ Method 5 (__init__.py): Failed[/dim]" + ) + pass + + # Method 6: Try to read from pyproject.toml + if current_version == "Unknown": + try: + import swarms + + swarms_path = swarms.__file__ + if swarms_path: + # Go up to find pyproject.toml + current_dir = os.path.dirname(swarms_path) + for _ in range(5): # Go up max 5 levels + pyproject_path = os.path.join( + current_dir, "pyproject.toml" + ) + if os.path.exists(pyproject_path): + with open(pyproject_path, "r") as f: + content = f.read() + # Look for version in pyproject.toml + import re + + version_match = re.search( + r'version\s*=\s*["\']([^"\']+)["\']', + content, + ) + if version_match: + current_version = ( + version_match.group(1) + ) + break + current_dir = os.path.dirname(current_dir) + if current_dir == os.path.dirname( + current_dir + ): # Reached root + break + except Exception: + pass + + if verbose: + console.print( + f"[dim]🎯 Final detected version: {current_version}[/dim]\n" + ) + + # Try to get latest version from PyPI + try: + import httpx + + with httpx.Client(timeout=5.0) as client: + response = client.get( + "https://pypi.org/pypi/swarms/json" + ) + if response.status_code == 200: + latest_version = response.json()["info"][ + "version" + ] + is_latest = current_version == latest_version + if is_latest: + return ( + True, + "✓", + f"Current version: {current_version}", + latest_version, + ) + else: + return ( + False, + "⚠", + f"Current version: {current_version}", + latest_version, + ) + else: + return ( + True, + "✓", + f"Current version: {current_version}", + "Unknown (PyPI unreachable)", + ) + except ImportError: + return ( + True, + "✓", + f"Current version: {current_version}", + "Unknown (httpx not available)", + ) + except Exception: + return ( + True, + "✓", + f"Current version: {current_version}", + "Unknown (PyPI check failed)", + ) + + # If we still don't have a version, try one more method + if current_version == "Unknown": + try: + # Try to get from environment variable (sometimes set during build) + current_version = os.getenv( + "SWARMS_VERSION", "Unknown" + ) + if verbose and current_version != "Unknown": + console.print( + f"[dim] ✓ Method 7 (env var): {current_version}[/dim]" + ) + except Exception: + if verbose: + console.print( + "[dim] ✗ Method 7 (env var): Failed[/dim]" + ) + pass + + except Exception as e: + return ( + False, + "✗", + f"Error checking version: {str(e)}", + "Unknown", + ) + + +def check_python_version() -> tuple[bool, str, str]: + """Check Python version compatibility.""" + version = sys.version_info + if version.major == 3 and version.minor >= 10: + return ( + True, + "✓", + f"Python {version.major}.{version.minor}.{version.micro}", + ) + else: + return ( + False, + "✗", + f"Python {version.major}.{version.minor}.{version.micro} (requires 3.10+)", + ) + + +def check_api_keys() -> tuple[bool, str, str]: + """Check if common API keys are set.""" + api_keys = { + "OPENAI_API_KEY": os.getenv("OPENAI_API_KEY"), + "ANTHROPIC_API_KEY": os.getenv("ANTHROPIC_API_KEY"), + "GOOGLE_API_KEY": os.getenv("GOOGLE_API_KEY"), + "COHERE_API_KEY": os.getenv("COHERE_API_KEY"), + } + + set_keys = [key for key, value in api_keys.items() if value] + if set_keys: + return True, "✓", f"API keys found: {', '.join(set_keys)}" + else: + return ( + False, + "✗", + "No API keys found in environment variables", + ) + + +def check_dependencies() -> tuple[bool, str, str]: + """Check if key dependencies are available.""" + required_deps = ["torch", "transformers", "litellm", "rich"] + missing_deps = [] + + for dep in required_deps: + try: + __import__(dep) + except ImportError: + missing_deps.append(dep) + + if not missing_deps: + return True, "✓", "All required dependencies available" + else: + return ( + False, + "⚠", + f"Missing dependencies: {', '.join(missing_deps)}", + ) + + +def run_setup_check(verbose: bool = False): + """Run comprehensive setup check with beautiful formatting.""" + console.print( + "\n[bold blue]🔍 Running Swarms Environment Setup Check[/bold blue]\n" + ) + + if verbose: + console.print( + "[dim]Debug mode enabled - showing detailed version detection steps[/dim]\n" + ) + + # Create results table + table = Table( + show_header=True, + header_style=f"bold {COLORS['primary']}", + border_style=COLORS["secondary"], + title="Environment Check Results", + padding=(0, 2), + ) + + table.add_column("Status", style="bold", width=8) + table.add_column("Check", style="bold white", width=25) + table.add_column("Details", style="dim white") + + # Run all checks + checks = [ + ("Python Version", check_python_version()), + ("Swarms Version", check_swarms_version(verbose)), + ("API Keys", check_api_keys()), + ("Dependencies", check_dependencies()), + ("Environment File", check_env_file()), + ("Workspace Directory", check_workspace_dir()), + ] + + all_passed = True + + for check_name, (passed, status_icon, details, *extra) in checks: + if not passed: + all_passed = False + + # Color code the status + if passed: + status_style = f"bold {COLORS['success']}" + elif status_icon == "⚠": + status_style = f"bold {COLORS['warning']}" + else: + status_style = f"bold {COLORS['error']}" + + table.add_row( + f"[{status_style}]{status_icon}[/{status_style}]", + check_name, + details, + ) + + console.print(table) + + # Show summary + if all_passed: + summary_panel = Panel( + Align.center( + "[bold green]🎉 All checks passed! Your environment is ready for Swarms.[/bold green]" + ), + border_style=COLORS["success"], + title="[bold]Setup Check Complete[/bold]", + padding=(1, 2), + ) + else: + summary_panel = Panel( + Align.center( + "[bold yellow]⚠️ Some checks failed. Please review the issues above.[/bold yellow]" + ), + border_style=COLORS["warning"], + title="[bold]Setup Check Complete[/bold]", + padding=(1, 2), + ) + + console.print(summary_panel) + + # Show recommendations + if not all_passed: + console.print("\n[bold blue]💡 Recommendations:[/bold blue]") + + recommendations = [] + + # Check specific failures and provide recommendations + for check_name, ( + passed, + status_icon, + details, + *extra, + ) in checks: + if not passed: + if "WORKSPACE_DIR" in check_name: + recommendations.append( + "Set WORKSPACE_DIR environment variable: export WORKSPACE_DIR=/path/to/your/workspace" + ) + elif "API Keys" in check_name: + recommendations.append( + "Set API keys: export OPENAI_API_KEY='your-key-here'" + ) + elif "Environment File" in check_name: + recommendations.append( + "Create .env file with your API keys" + ) + elif ( + "Swarms Version" in check_name and len(extra) > 0 + ): + latest_version = extra[0] + if latest_version != "Unknown": + recommendations.append( + f"Update Swarms: pip install --upgrade swarms (latest: {latest_version})" + ) + elif "Dependencies" in check_name: + recommendations.append( + "Install missing dependencies: pip install -r requirements.txt" + ) + + if recommendations: + for i, rec in enumerate(recommendations, 1): + console.print(f" {i}. [yellow]{rec}[/yellow]") + + console.print( + "\n[dim]Run 'swarms setup-check' again after making changes to verify.[/dim]" + ) + + return all_passed + + def create_command_table() -> Table: """Create a beautifully formatted table of commands.""" table = Table( @@ -94,10 +586,17 @@ def create_command_table() -> Table: "load-markdown", "Load agents from markdown files with YAML frontmatter", ), - ("agent", "Create and run a custom agent with specified parameters"), + ( + "agent", + "Create and run a custom agent with specified parameters", + ), ("auto-upgrade", "Update Swarms to the latest version"), ("book-call", "Schedule a strategy session with our team"), ("autoswarm", "Generate and execute an autonomous swarm"), + ( + "setup-check", + "Run a comprehensive environment setup check", + ), ] for cmd, desc in commands: @@ -351,7 +850,7 @@ def create_swarm_agent( system_prompt: str, model_name: str, task: str, - **kwargs + **kwargs, ): """Create and run a custom agent with the specified parameters.""" try: @@ -362,9 +861,7 @@ def create_swarm_agent( # Create progress display progress = Progress( SpinnerColumn(), - TextColumn( - "[progress.description]{task.description}" - ), + TextColumn("[progress.description]{task.description}"), console=console, ) @@ -379,19 +876,21 @@ def create_swarm_agent( init_task, description="Creating agent with specified parameters...", ) - + # Build agent configuration agent_config = { "agent_name": name, "agent_description": description, "system_prompt": system_prompt, "model_name": model_name, - **kwargs + **kwargs, } - + # Remove None values to use defaults - agent_config = {k: v for k, v in agent_config.items() if v is not None} - + agent_config = { + k: v for k, v in agent_config.items() if v is not None + } + agent = Agent(**agent_config) # Update progress @@ -405,7 +904,7 @@ def create_swarm_agent( init_task, description=f"Executing task: {task[:50]}...", ) - + result = agent.run(task) # Update progress on completion @@ -420,7 +919,7 @@ def create_swarm_agent( console.print( f"\n[bold green]✓ Agent '{name}' completed the task successfully![/bold green]" ) - + # Display agent info agent_info = Panel( f"[bold]Agent Name:[/bold] {name}\n" @@ -429,10 +928,10 @@ def create_swarm_agent( f"[bold]Result:[/bold]\n{result}", title="Agent Execution Results", border_style="green", - padding=(1, 2) + padding=(1, 2), ) console.print(agent_info) - + return result else: console.print( @@ -448,7 +947,7 @@ def create_swarm_agent( "1. Your API keys are set correctly\n" "2. The model name is valid\n" "3. All required parameters are provided\n" - "4. Your system prompt is properly formatted" + "4. Your system prompt is properly formatted", ) return None @@ -474,6 +973,7 @@ def main(): "auto-upgrade", "book-call", "autoswarm", + "setup-check", ], help="Command to execute", ) @@ -735,13 +1235,12 @@ def main(): "Example usage: python cli.py load-markdown --markdown-path ./agents/", ) exit(1) - + # Load agents from markdown agents = load_markdown_agents( - args.markdown_path, - concurrent=args.concurrent + args.markdown_path, concurrent=args.concurrent ) - + if agents: console.print( f"\n[bold green]Ready to use {len(agents)} agents![/bold green]\n" @@ -749,9 +1248,18 @@ def main(): ) elif args.command == "agent": # Validate required arguments - required_args = ["name", "description", "system_prompt", "task"] - missing_args = [arg for arg in required_args if not getattr(args, arg)] - + required_args = [ + "name", + "description", + "system_prompt", + "task", + ] + missing_args = [ + arg + for arg in required_args + if not getattr(args, arg) + ] + if missing_args: show_error( "Missing required arguments", @@ -763,36 +1271,36 @@ def main(): " --system-prompt 'You are an expert trader...' \\\n" " --task 'Analyze market trends' \\\n" " --model-name 'gpt-4' \\\n" - " --temperature 0.1" + " --temperature 0.1", ) exit(1) - + # Build kwargs for additional parameters additional_params = {} param_mapping = { - 'temperature': 'temperature', - 'max_loops': 'max_loops', - 'auto_generate_prompt': 'auto_generate_prompt', - 'dynamic_temperature_enabled': 'dynamic_temperature_enabled', - 'dynamic_context_window': 'dynamic_context_window', - 'output_type': 'output_type', - 'verbose': 'verbose', - 'streaming_on': 'streaming_on', - 'context_length': 'context_length', - 'retry_attempts': 'retry_attempts', - 'return_step_meta': 'return_step_meta', - 'dashboard': 'dashboard', - 'autosave': 'autosave', - 'saved_state_path': 'saved_state_path', - 'user_name': 'user_name', - 'mcp_url': 'mcp_url' + "temperature": "temperature", + "max_loops": "max_loops", + "auto_generate_prompt": "auto_generate_prompt", + "dynamic_temperature_enabled": "dynamic_temperature_enabled", + "dynamic_context_window": "dynamic_context_window", + "output_type": "output_type", + "verbose": "verbose", + "streaming_on": "streaming_on", + "context_length": "context_length", + "retry_attempts": "retry_attempts", + "return_step_meta": "return_step_meta", + "dashboard": "dashboard", + "autosave": "autosave", + "saved_state_path": "saved_state_path", + "user_name": "user_name", + "mcp_url": "mcp_url", } - + for cli_arg, agent_param in param_mapping.items(): value = getattr(args, cli_arg) if value is not None: additional_params[agent_param] = value - + # Create and run the custom agent result = create_swarm_agent( name=args.name, @@ -800,9 +1308,9 @@ def main(): system_prompt=args.system_prompt, model_name=args.model_name, task=args.task, - **additional_params + **additional_params, ) - + if result: console.print( f"\n[bold green]Agent '{args.name}' executed successfully![/bold green]" @@ -819,6 +1327,8 @@ def main(): ) exit(1) run_autoswarm(args.task, args.model) + elif args.command == "setup-check": + run_setup_check(verbose=args.verbose) except Exception as e: console.print( f"[{COLORS['error']}]Error: {str(e)}[/{COLORS['error']}]"