#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Diagnostic et Correction VWB Auteur : Dom, Alice, Kiro - 8 janvier 2026 Ce script diagnostique et corrige les problèmes du Visual Workflow Builder. """ import subprocess import time import requests import signal import os import sys from typing import Optional, Tuple class Colors: RED = '\033[0;31m' GREEN = '\033[0;32m' YELLOW = '\033[1;33m' BLUE = '\033[0;34m' PURPLE = '\033[0;35m' CYAN = '\033[0;36m' BOLD = '\033[1m' NC = '\033[0m' class VWBDiagnostic: def __init__(self): self.original_dir = os.getcwd() self.vwb_dir = os.path.join(self.original_dir, "visual_workflow_builder") self.backend_dir = os.path.join(self.vwb_dir, "backend") self.frontend_dir = os.path.join(self.vwb_dir, "frontend") def print_header(self): """Affiche l'en-tête du diagnostic""" print(f"{Colors.PURPLE}{Colors.BOLD}") print("╔════════════════════════════════════════════════════════════╗") print("║ 🔧 Diagnostic et Correction VWB ║") print("║ Auteur : Dom, Alice, Kiro - 8 janvier 2026 ║") print("╚════════════════════════════════════════════════════════════╝") print(f"{Colors.NC}") def check_directories(self) -> bool: """Vérifie que les répertoires existent""" print(f"\n{Colors.BLUE}[1/6] Vérification des répertoires{Colors.NC}") print("=" * 50) success = True directories = [ (self.vwb_dir, "Visual Workflow Builder"), (self.backend_dir, "Backend"), (self.frontend_dir, "Frontend") ] for dir_path, name in directories: if os.path.exists(dir_path): print(f"{Colors.GREEN}✅ {name} : {dir_path}{Colors.NC}") else: print(f"{Colors.RED}❌ {name} manquant : {dir_path}{Colors.NC}") success = False return success def check_dependencies(self) -> bool: """Vérifie les dépendances""" print(f"\n{Colors.BLUE}[2/6] Vérification des dépendances{Colors.NC}") print("=" * 50) success = True # Vérifier Python et l'environnement virtuel try: result = subprocess.run( ["source", "venv_v3/bin/activate", "&&", "python3", "--version"], shell=True, capture_output=True, text=True ) if result.returncode == 0: print(f"{Colors.GREEN}✅ Python avec venv_v3 : {result.stdout.strip()}{Colors.NC}") else: print(f"{Colors.RED}❌ Problème avec l'environnement virtuel{Colors.NC}") success = False except Exception as e: print(f"{Colors.RED}❌ Erreur Python : {e}{Colors.NC}") success = False # Vérifier Node.js try: result = subprocess.run(["node", "--version"], capture_output=True, text=True) if result.returncode == 0: print(f"{Colors.GREEN}✅ Node.js : {result.stdout.strip()}{Colors.NC}") else: print(f"{Colors.RED}❌ Node.js non trouvé{Colors.NC}") success = False except Exception as e: print(f"{Colors.RED}❌ Erreur Node.js : {e}{Colors.NC}") success = False return success def cleanup_ports(self) -> bool: """Nettoie les ports utilisés""" print(f"\n{Colors.BLUE}[3/6] Nettoyage des ports{Colors.NC}") print("=" * 50) ports = [3000, 5002] cleaned = False for port in ports: try: result = subprocess.run( f"lsof -ti:{port} | xargs -r kill -9", shell=True, capture_output=True ) if result.returncode == 0: print(f"{Colors.YELLOW}🧹 Port {port} nettoyé{Colors.NC}") cleaned = True else: print(f"{Colors.GREEN}✅ Port {port} libre{Colors.NC}") except Exception as e: print(f"{Colors.YELLOW}⚠️ Erreur nettoyage port {port} : {e}{Colors.NC}") if cleaned: time.sleep(2) # Attendre que les ports se libèrent return True def start_backend(self) -> Tuple[bool, Optional[subprocess.Popen]]: """Démarre le backend""" print(f"\n{Colors.BLUE}[4/6] Démarrage du backend{Colors.NC}") print("=" * 50) try: os.chdir(self.backend_dir) # Commande pour démarrer le backend cmd = [ "bash", "-c", "source ../../../venv_v3/bin/activate && python3 app.py" ] print(f"{Colors.CYAN}🚀 Lancement du backend Flask...{Colors.NC}") process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid ) # Attendre que le backend soit prêt start_time = time.time() timeout = 30 while time.time() - start_time < timeout: try: response = requests.get("http://localhost:5002/health", timeout=2) if response.status_code == 200: print(f"{Colors.GREEN}✅ Backend prêt sur http://localhost:5002{Colors.NC}") os.chdir(self.original_dir) return True, process except requests.exceptions.RequestException: pass # Vérifier si le processus est encore en vie if process.poll() is not None: stdout, stderr = process.communicate() print(f"{Colors.RED}❌ Le backend s'est arrêté{Colors.NC}") print(f"STDERR: {stderr.decode()[-500:]}") # Derniers 500 caractères os.chdir(self.original_dir) return False, None time.sleep(1) print(f"{Colors.RED}❌ Timeout: Le backend n'a pas démarré en {timeout}s{Colors.NC}") os.chdir(self.original_dir) return False, process except Exception as e: print(f"{Colors.RED}❌ Erreur lors du démarrage du backend : {e}{Colors.NC}") os.chdir(self.original_dir) return False, None def start_frontend(self) -> Tuple[bool, Optional[subprocess.Popen]]: """Démarre le frontend""" print(f"\n{Colors.BLUE}[5/6] Démarrage du frontend{Colors.NC}") print("=" * 50) try: os.chdir(self.frontend_dir) # Vérifier si node_modules existe if not os.path.exists("node_modules"): print(f"{Colors.YELLOW}📦 Installation des dépendances npm...{Colors.NC}") result = subprocess.run(["npm", "install"], capture_output=True, text=True) if result.returncode != 0: print(f"{Colors.RED}❌ Erreur lors de l'installation npm{Colors.NC}") os.chdir(self.original_dir) return False, None print(f"{Colors.CYAN}🎨 Lancement du serveur React...{Colors.NC}") # Démarrer le frontend env = os.environ.copy() env['BROWSER'] = 'none' # Ne pas ouvrir le navigateur automatiquement process = subprocess.Popen( ["npm", "start"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, preexec_fn=os.setsid ) # Attendre que le frontend soit prêt start_time = time.time() timeout = 60 while time.time() - start_time < timeout: try: response = requests.get("http://localhost:3000", timeout=2) if response.status_code in [200, 404]: # 404 est OK pour React print(f"{Colors.GREEN}✅ Frontend prêt sur http://localhost:3000{Colors.NC}") os.chdir(self.original_dir) return True, process except requests.exceptions.RequestException: pass # Vérifier si le processus est encore en vie if process.poll() is not None: stdout, stderr = process.communicate() print(f"{Colors.RED}❌ Le frontend s'est arrêté{Colors.NC}") print(f"STDERR: {stderr.decode()[-500:]}") os.chdir(self.original_dir) return False, None time.sleep(2) print(f"{Colors.RED}❌ Timeout: Le frontend n'a pas démarré en {timeout}s{Colors.NC}") os.chdir(self.original_dir) return False, process except Exception as e: print(f"{Colors.RED}❌ Erreur lors du démarrage du frontend : {e}{Colors.NC}") os.chdir(self.original_dir) return False, None def test_integration(self) -> bool: """Teste l'intégration frontend-backend""" print(f"\n{Colors.BLUE}[6/6] Test d'intégration{Colors.NC}") print("=" * 50) success = True # Tester les endpoints du backend backend_endpoints = [ ("/health", "Health Check"), ("/api/workflows", "Workflows API"), ("/api/node-types", "Node Types API") ] for endpoint, description in backend_endpoints: try: response = requests.get(f"http://localhost:5002{endpoint}", timeout=5) if response.status_code in [200, 404, 405]: print(f"{Colors.GREEN}✅ {description}: {endpoint} (status: {response.status_code}){Colors.NC}") else: print(f"{Colors.YELLOW}⚠️ {description}: {endpoint} (status: {response.status_code}){Colors.NC}") except Exception as e: print(f"{Colors.RED}❌ {description}: {endpoint} - Erreur: {e}{Colors.NC}") success = False # Tester le frontend try: response = requests.get("http://localhost:3000", timeout=5) if response.status_code == 200: print(f"{Colors.GREEN}✅ Frontend accessible{Colors.NC}") else: print(f"{Colors.YELLOW}⚠️ Frontend status: {response.status_code}{Colors.NC}") except Exception as e: print(f"{Colors.RED}❌ Frontend non accessible : {e}{Colors.NC}") success = False return success def run_diagnostic(self) -> bool: """Exécute le diagnostic complet""" self.print_header() # Étapes du diagnostic if not self.check_directories(): return False if not self.check_dependencies(): return False self.cleanup_ports() backend_success, backend_process = self.start_backend() if not backend_success: return False frontend_success, frontend_process = self.start_frontend() if not frontend_success: if backend_process: try: os.killpg(os.getpgid(backend_process.pid), signal.SIGTERM) except: pass return False integration_success = self.test_integration() # Afficher le résumé print(f"\n{Colors.PURPLE}{Colors.BOLD}📊 RÉSUMÉ DU DIAGNOSTIC{Colors.NC}") print("=" * 60) if backend_success and frontend_success and integration_success: print(f"{Colors.GREEN}{Colors.BOLD}🎉 VISUAL WORKFLOW BUILDER OPÉRATIONNEL !{Colors.NC}") print(f"\n{Colors.CYAN}URLs d'accès :{Colors.NC}") print(f" Frontend: http://localhost:3000") print(f" Backend: http://localhost:5002") print(f"\n{Colors.YELLOW}Les services restent en cours d'exécution.{Colors.NC}") print(f"{Colors.YELLOW}Appuyez sur Ctrl+C pour les arrêter.{Colors.NC}") # Garder les services en vie try: while True: time.sleep(1) except KeyboardInterrupt: print(f"\n{Colors.YELLOW}🛑 Arrêt des services...{Colors.NC}") if backend_process: try: os.killpg(os.getpgid(backend_process.pid), signal.SIGTERM) except: pass if frontend_process: try: os.killpg(os.getpgid(frontend_process.pid), signal.SIGTERM) except: pass print(f"{Colors.GREEN}✓ Services arrêtés{Colors.NC}") return True else: print(f"{Colors.RED}{Colors.BOLD}❌ PROBLÈMES DÉTECTÉS{Colors.NC}") return False def main(): """Fonction principale""" diagnostic = VWBDiagnostic() success = diagnostic.run_diagnostic() sys.exit(0 if success else 1) if __name__ == "__main__": main()