v1.0 - Version stable: multi-PC, détection UI-DETR-1, 3 modes exécution

- Frontend v4 accessible sur réseau local (192.168.1.40)
- Ports ouverts: 3002 (frontend), 5001 (backend), 5004 (dashboard)
- Ollama GPU fonctionnel
- Self-healing interactif
- Dashboard confiance

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Dom
2026-01-29 11:23:51 +01:00
parent 21bfa3b337
commit a27b74cf22
1595 changed files with 412691 additions and 400 deletions

View File

@@ -0,0 +1,296 @@
#!/usr/bin/env python3
"""
Diagnostic et réparation complète du backend VWB
Auteur : Dom, Alice, Kiro - 8 janvier 2026
"""
import os
import sys
import subprocess
import requests
import time
import json
import psutil
from pathlib import Path
class DiagnosticBackend:
"""Classe pour diagnostiquer et réparer le backend VWB"""
def __init__(self):
self.backend_port = 5002
self.backend_url = f'http://localhost:{self.backend_port}'
self.backend_path = 'visual_workflow_builder/backend'
self.venv_path = './venv_v3'
def verifier_environnement(self):
"""Vérifier l'environnement Python et les dépendances"""
print("🔍 Vérification de l'environnement...")
# Vérifier Python
try:
python_version = sys.version_info
print(f" ✅ Python {python_version.major}.{python_version.minor}.{python_version.micro}")
except Exception as e:
print(f" ❌ Problème Python: {e}")
return False
# Vérifier l'environnement virtuel
if os.path.exists(self.venv_path):
print(f" ✅ Environnement virtuel trouvé: {self.venv_path}")
else:
print(f" ❌ Environnement virtuel manquant: {self.venv_path}")
return False
# Vérifier les dépendances critiques
dependances_critiques = ['flask', 'flask_cors', 'flask_socketio', 'requests']
for dep in dependances_critiques:
try:
__import__(dep)
print(f" ✅ Dépendance {dep} disponible")
except ImportError:
print(f" ❌ Dépendance {dep} manquante")
return False
return True
def nettoyer_processus_existants(self):
"""Nettoyer les processus backend existants"""
print("🧹 Nettoyage des processus existants...")
processus_tues = 0
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
try:
cmdline = ' '.join(proc.info['cmdline'] or [])
if 'visual_workflow_builder/backend/app.py' in cmdline:
print(f" 🔪 Arrêt du processus PID {proc.info['pid']}")
proc.terminate()
processus_tues += 1
except (psutil.NoSuchProcess, psutil.AccessDenied):
continue
if processus_tues > 0:
print(f"{processus_tues} processus arrêtés")
time.sleep(2) # Attendre que les processus se terminent
else:
print(" Aucun processus backend en cours")
return True
def verifier_fichiers_backend(self):
"""Vérifier l'intégrité des fichiers backend"""
print("📁 Vérification des fichiers backend...")
fichiers_critiques = [
'visual_workflow_builder/backend/app.py',
'visual_workflow_builder/backend/api/__init__.py',
'visual_workflow_builder/backend/api/workflows.py',
'visual_workflow_builder/backend/api/screen_capture.py',
]
for fichier in fichiers_critiques:
if os.path.exists(fichier):
taille = os.path.getsize(fichier)
print(f"{fichier} ({taille} bytes)")
else:
print(f"{fichier} manquant")
return False
return True
def demarrer_backend(self):
"""Démarrer le backend en mode diagnostic"""
print("🚀 Démarrage du backend...")
# Commande pour démarrer le backend
cmd = [
f'{self.venv_path}/bin/python',
'visual_workflow_builder/backend/app.py'
]
try:
# Démarrer en arrière-plan
process = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd='.',
env=dict(os.environ, FLASK_ENV='development')
)
print(f" 🔄 Processus démarré (PID: {process.pid})")
# Attendre que le serveur démarre
for tentative in range(10):
try:
response = requests.get(f'{self.backend_url}/health', timeout=2)
if response.status_code == 200:
print(f" ✅ Backend démarré avec succès sur le port {self.backend_port}")
return process
except requests.exceptions.ConnectionError:
pass
print(f" ⏳ Tentative {tentative + 1}/10...")
time.sleep(2)
# Si on arrive ici, le démarrage a échoué
stdout, stderr = process.communicate(timeout=5)
print(f" ❌ Échec du démarrage")
print(f" 📝 STDOUT: {stdout.decode()}")
print(f" 📝 STDERR: {stderr.decode()}")
return None
except Exception as e:
print(f" ❌ Erreur lors du démarrage: {e}")
return None
def tester_endpoints(self):
"""Tester tous les endpoints critiques"""
print("🧪 Test des endpoints critiques...")
endpoints = [
('/health', 'GET', None),
('/api/workflows/', 'GET', None),
('/api/screen-capture/', 'POST', {}),
]
resultats = {}
for endpoint, methode, data in endpoints:
try:
url = f'{self.backend_url}{endpoint}'
if methode == 'GET':
response = requests.get(url, timeout=10)
elif methode == 'POST':
response = requests.post(url, json=data, timeout=10)
resultats[endpoint] = {
'status': response.status_code,
'success': response.status_code < 400
}
status_icon = "" if response.status_code < 400 else ""
print(f" {status_icon} {methode} {endpoint}: {response.status_code}")
except Exception as e:
resultats[endpoint] = {
'status': 'ERREUR',
'success': False,
'error': str(e)
}
print(f"{methode} {endpoint}: ERREUR - {e}")
return resultats
def generer_rapport(self, resultats_tests):
"""Générer un rapport de diagnostic"""
print("\n" + "=" * 60)
print("📊 RAPPORT DE DIAGNOSTIC BACKEND")
print("=" * 60)
total_tests = len(resultats_tests)
tests_reussis = sum(1 for r in resultats_tests.values() if r['success'])
taux_reussite = (tests_reussis / total_tests) * 100 if total_tests > 0 else 0
print(f"📈 Taux de réussite: {tests_reussis}/{total_tests} ({taux_reussite:.1f}%)")
if taux_reussite == 100:
print("🎉 Backend entièrement fonctionnel !")
statut = "EXCELLENT"
elif taux_reussite >= 70:
print("⚠️ Backend partiellement fonctionnel")
statut = "ACCEPTABLE"
else:
print("🚨 Backend défaillant")
statut = "CRITIQUE"
# Sauvegarder le rapport
rapport = {
'timestamp': time.time(),
'statut': statut,
'taux_reussite': taux_reussite,
'tests': resultats_tests,
'recommandations': self.generer_recommandations(resultats_tests)
}
with open('diagnostic_backend_rapport.json', 'w', encoding='utf-8') as f:
json.dump(rapport, f, indent=2, ensure_ascii=False)
print(f"📄 Rapport sauvegardé: diagnostic_backend_rapport.json")
return statut
def generer_recommandations(self, resultats_tests):
"""Générer des recommandations basées sur les résultats"""
recommandations = []
for endpoint, resultat in resultats_tests.items():
if not resultat['success']:
if endpoint == '/health':
recommandations.append("Vérifier la configuration Flask de base")
elif endpoint == '/api/workflows/':
recommandations.append("Vérifier la base de données et les modèles")
elif endpoint == '/api/screen-capture/':
recommandations.append("Vérifier les dépendances de capture d'écran")
if not recommandations:
recommandations.append("Backend fonctionnel - aucune action requise")
return recommandations
def executer_diagnostic_complet(self):
"""Exécuter le diagnostic complet"""
print("🏥 DIAGNOSTIC COMPLET DU BACKEND VWB")
print("=" * 50)
# Étape 1: Vérifier l'environnement
if not self.verifier_environnement():
print("❌ Environnement défaillant - arrêt du diagnostic")
return False
# Étape 2: Nettoyer les processus existants
self.nettoyer_processus_existants()
# Étape 3: Vérifier les fichiers
if not self.verifier_fichiers_backend():
print("❌ Fichiers backend manquants - arrêt du diagnostic")
return False
# Étape 4: Démarrer le backend
process = self.demarrer_backend()
if not process:
print("❌ Impossible de démarrer le backend")
return False
try:
# Étape 5: Tester les endpoints
resultats_tests = self.tester_endpoints()
# Étape 6: Générer le rapport
statut = self.generer_rapport(resultats_tests)
return statut in ['EXCELLENT', 'ACCEPTABLE']
finally:
# Nettoyer le processus de test
if process and process.poll() is None:
print("🧹 Nettoyage du processus de test...")
process.terminate()
def main():
"""Fonction principale"""
diagnostic = DiagnosticBackend()
try:
succes = diagnostic.executer_diagnostic_complet()
exit_code = 0 if succes else 1
print(f"\n🏁 Diagnostic terminé (code de sortie: {exit_code})")
return exit_code
except KeyboardInterrupt:
print("\n⚠️ Diagnostic interrompu par l'utilisateur")
return 2
except Exception as e:
print(f"\n❌ Erreur critique lors du diagnostic: {e}")
return 3
if __name__ == "__main__":
sys.exit(main())