| |
| """ |
| Fresh Start Validation Script |
| Checks all requirements for launching the system from scratch |
| """ |
|
|
| import os |
| import sys |
| import subprocess |
| import json |
|
|
| def check_file_exists(filepath, description): |
| """Check if a critical file exists""" |
| if os.path.exists(filepath): |
| print(f"β
{description}: {filepath}") |
| return True |
| else: |
| print(f"β MISSING {description}: {filepath}") |
| return False |
|
|
| def check_docker_files(): |
| """Check all Docker-related files""" |
| print("π³ Checking Docker files...") |
| files = [ |
| ("docker-compose.yml", "Main orchestration file"), |
| ("agent/Dockerfile", "Agent service Docker config"), |
| ("mcp/Dockerfile", "MCP service Docker config"), |
| ("frontend/Dockerfile", "Frontend service Docker config"), |
| ("neo4j/Dockerfile", "Neo4j service Docker config"), |
| (".env.example", "Environment template") |
| ] |
| |
| all_good = True |
| for filepath, desc in files: |
| all_good &= check_file_exists(filepath, desc) |
| |
| return all_good |
|
|
| def check_frontend_files(): |
| """Check frontend critical files""" |
| print("\nπ Checking Frontend files...") |
| files = [ |
| ("frontend/package.json", "Frontend dependencies"), |
| ("frontend/tsconfig.json", "TypeScript config"), |
| ("frontend/tailwind.config.js", "Tailwind CSS config"), |
| ("frontend/next.config.js", "Next.js config"), |
| ("frontend/app/page.tsx", "Main chat interface"), |
| ("frontend/app/layout.tsx", "Root layout"), |
| ("frontend/types/cytoscape-fcose.d.ts", "Cytoscape types") |
| ] |
| |
| all_good = True |
| for filepath, desc in files: |
| all_good &= check_file_exists(filepath, desc) |
| |
| return all_good |
|
|
| def check_backend_files(): |
| """Check backend service files""" |
| print("\nπ§ Checking Backend files...") |
| files = [ |
| ("agent/main.py", "Agent service main file"), |
| ("agent/requirements.txt", "Agent dependencies"), |
| ("mcp/main.py", "MCP service main file"), |
| ("mcp/requirements.txt", "MCP dependencies"), |
| ("postgres/init.sql", "PostgreSQL initialization"), |
| ] |
| |
| all_good = True |
| for filepath, desc in files: |
| all_good &= check_file_exists(filepath, desc) |
| |
| return all_good |
|
|
| def check_operational_files(): |
| """Check operational scripts""" |
| print("\nπ οΈ Checking Operational files...") |
| files = [ |
| ("ops/scripts/seed.py", "Basic seeding script"), |
| ("ops/scripts/seed_comprehensive.py", "Comprehensive seeding script"), |
| ("ops/scripts/validate.py", "System validation script"), |
| ("ops/scripts/demo.ps1", "PowerShell demo script"), |
| ("Makefile", "Build automation"), |
| ("README.md", "Main documentation"), |
| ("SYSTEM_OVERVIEW.md", "System overview") |
| ] |
| |
| all_good = True |
| for filepath, desc in files: |
| all_good &= check_file_exists(filepath, desc) |
| |
| return all_good |
|
|
| def check_env_variables(): |
| """Check if .env.example has all required variables""" |
| print("\nβοΈ Checking Environment variables...") |
| |
| if not os.path.exists(".env.example"): |
| print("β .env.example file missing") |
| return False |
| |
| with open(".env.example", "r") as f: |
| env_content = f.read() |
| |
| required_vars = [ |
| "NEO4J_AUTH", |
| "NEO4J_BOLT_URL", |
| "POSTGRES_PASSWORD", |
| "POSTGRES_CONNECTION", |
| "MCP_API_KEYS", |
| "MCP_PORT", |
| "AGENT_POLL_INTERVAL", |
| "PAUSE_DURATION", |
| "LLM_API_KEY", |
| "LLM_MODEL" |
| ] |
| |
| all_good = True |
| for var in required_vars: |
| if var in env_content: |
| print(f"β
Environment variable: {var}") |
| else: |
| print(f"β MISSING environment variable: {var}") |
| all_good = False |
| |
| return all_good |
|
|
| def check_docker_compose_structure(): |
| """Check docker-compose.yml structure""" |
| print("\nπ Checking Docker Compose structure...") |
| |
| if not os.path.exists("docker-compose.yml"): |
| print("β docker-compose.yml missing") |
| return False |
| |
| try: |
| import yaml |
| with open("docker-compose.yml", "r") as f: |
| compose = yaml.safe_load(f) |
| |
| required_services = ["neo4j", "postgres", "mcp", "agent", "frontend"] |
| all_good = True |
| |
| for service in required_services: |
| if service in compose.get("services", {}): |
| print(f"β
Service defined: {service}") |
| else: |
| print(f"β MISSING service: {service}") |
| all_good = False |
| |
| return all_good |
| |
| except ImportError: |
| print("β οΈ PyYAML not available, skipping structure check") |
| return True |
| except Exception as e: |
| print(f"β Error parsing docker-compose.yml: {e}") |
| return False |
|
|
| def check_package_json(): |
| """Check frontend package.json for required dependencies""" |
| print("\nπ¦ Checking Frontend dependencies...") |
| |
| if not os.path.exists("frontend/package.json"): |
| print("β frontend/package.json missing") |
| return False |
| |
| with open("frontend/package.json", "r") as f: |
| package = json.load(f) |
| |
| required_deps = [ |
| "next", "react", "react-dom", "typescript", |
| "cytoscape", "cytoscape-fcose", "tailwindcss" |
| ] |
| |
| all_deps = {**package.get("dependencies", {}), **package.get("devDependencies", {})} |
| all_good = True |
| |
| for dep in required_deps: |
| if dep in all_deps: |
| print(f"β
Frontend dependency: {dep}") |
| else: |
| print(f"β MISSING frontend dependency: {dep}") |
| all_good = False |
| |
| return all_good |
|
|
| def generate_startup_commands(): |
| """Generate the exact commands for fresh startup""" |
| print("\nπ Fresh Startup Commands:") |
| print("=" * 50) |
| print("# 1. Copy environment file") |
| print("cp .env.example .env") |
| print("") |
| print("# 2. Edit .env and add your LLM API key") |
| print("# LLM_API_KEY=your-openai-or-anthropic-key-here") |
| print("") |
| print("# 3. Clean any existing containers") |
| print("docker-compose down") |
| print("docker system prune -f") |
| print("") |
| print("# 4. Build and start services") |
| print("docker-compose build") |
| print("docker-compose up -d") |
| print("") |
| print("# 5. Wait for services to be healthy (30 seconds)") |
| print("Start-Sleep 30") |
| print("") |
| print("# 6. Seed the database") |
| print("docker-compose exec mcp python /app/ops/scripts/seed.py") |
| print("") |
| print("# 7. Open the interface") |
| print("# Frontend: http://localhost:3000") |
| print("# Neo4j Browser: http://localhost:7474 (neo4j/password)") |
| print("=" * 50) |
|
|
| def main(): |
| print("π FRESH START VALIDATION") |
| print("========================") |
| print("") |
| |
| checks = [ |
| ("Docker Files", check_docker_files), |
| ("Frontend Files", check_frontend_files), |
| ("Backend Files", check_backend_files), |
| ("Operational Files", check_operational_files), |
| ("Environment Variables", check_env_variables), |
| ("Docker Compose Structure", check_docker_compose_structure), |
| ("Frontend Dependencies", check_package_json) |
| ] |
| |
| all_passed = True |
| |
| for check_name, check_func in checks: |
| try: |
| result = check_func() |
| all_passed &= result |
| except Exception as e: |
| print(f"β ERROR in {check_name}: {e}") |
| all_passed = False |
| |
| print("\n" + "=" * 50) |
| if all_passed: |
| print("β
ALL CHECKS PASSED!") |
| print("System is ready for fresh deployment") |
| generate_startup_commands() |
| else: |
| print("β SOME CHECKS FAILED") |
| print("Please fix the missing files/configurations before deploying") |
| |
| print("=" * 50) |
| return all_passed |
|
|
| if __name__ == "__main__": |
| success = main() |
| sys.exit(0 if success else 1) |
|
|