- 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>
746 lines
21 KiB
Python
746 lines
21 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Correction des Erreurs Backend Visual Workflow Builder
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
|
|
Ce script identifie et corrige automatiquement les erreurs communes
|
|
du backend Visual Workflow Builder.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import shutil
|
|
from pathlib import Path
|
|
from typing import List, Dict, Any
|
|
|
|
def print_section(title: str):
|
|
"""Affiche une section avec formatage."""
|
|
print(f"\n{'='*60}")
|
|
print(f" {title}")
|
|
print(f"{'='*60}")
|
|
|
|
def print_subsection(title: str):
|
|
"""Affiche une sous-section."""
|
|
print(f"\n{'-'*40}")
|
|
print(f" {title}")
|
|
print(f"{'-'*40}")
|
|
|
|
def fix_missing_api_modules():
|
|
"""Crée les modules API manquants avec des implémentations minimales."""
|
|
print_subsection("Correction des Modules API Manquants")
|
|
|
|
backend_path = Path("visual_workflow_builder/backend")
|
|
api_path = backend_path / "api"
|
|
|
|
# Créer le répertoire api s'il n'existe pas
|
|
api_path.mkdir(exist_ok=True)
|
|
|
|
# Créer __init__.py
|
|
init_file = api_path / "__init__.py"
|
|
if not init_file.exists():
|
|
init_file.write_text('"""API Package"""')
|
|
print("✅ Créé api/__init__.py")
|
|
|
|
# Modules API essentiels à créer
|
|
api_modules = {
|
|
"errors.py": '''"""
|
|
Gestionnaire d'erreurs pour l'API
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import jsonify
|
|
from typing import Any, Dict
|
|
|
|
class APIError(Exception):
|
|
"""Erreur API de base."""
|
|
def __init__(self, message: str, status_code: int = 400):
|
|
super().__init__(message)
|
|
self.message = message
|
|
self.status_code = status_code
|
|
|
|
class ValidationError(APIError):
|
|
"""Erreur de validation."""
|
|
pass
|
|
|
|
class NotFoundError(APIError):
|
|
"""Erreur ressource non trouvée."""
|
|
def __init__(self, message: str):
|
|
super().__init__(message, 404)
|
|
|
|
class BadRequestError(APIError):
|
|
"""Erreur requête invalide."""
|
|
pass
|
|
|
|
def error_response(status_code: int, message: str) -> tuple:
|
|
"""Retourne une réponse d'erreur formatée."""
|
|
return jsonify({
|
|
'error': message,
|
|
'status_code': status_code
|
|
}), status_code
|
|
''',
|
|
|
|
"validation.py": '''"""
|
|
Validation des données pour l'API
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from typing import Dict, Any, List
|
|
|
|
def validate_workflow_data(data: Dict[str, Any]) -> List[str]:
|
|
"""Valide les données d'un workflow."""
|
|
errors = []
|
|
|
|
if not isinstance(data, dict):
|
|
errors.append("Les données doivent être un objet JSON")
|
|
return errors
|
|
|
|
# Validation du nom
|
|
name = data.get('name')
|
|
if not name or not str(name).strip():
|
|
errors.append("Le nom est requis")
|
|
|
|
# Validation created_by
|
|
created_by = data.get('created_by')
|
|
if not created_by:
|
|
errors.append("Le champ 'created_by' est requis")
|
|
|
|
return errors
|
|
|
|
def validate_update_data(data: Dict[str, Any]) -> List[str]:
|
|
"""Valide les données de mise à jour d'un workflow."""
|
|
errors = []
|
|
|
|
if not isinstance(data, dict):
|
|
errors.append("Les données doivent être un objet JSON")
|
|
return errors
|
|
|
|
# Si le nom est fourni, il doit être valide
|
|
if 'name' in data:
|
|
name = data['name']
|
|
if not name or not str(name).strip():
|
|
errors.append("Le nom ne peut pas être vide")
|
|
|
|
return errors
|
|
''',
|
|
|
|
"screen_capture.py": '''"""
|
|
API de capture d'écran (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
screen_capture_bp = Blueprint('screen_capture', __name__)
|
|
|
|
@screen_capture_bp.route('/capture', methods=['POST'])
|
|
def capture_screen():
|
|
"""Capture d'écran (placeholder)."""
|
|
return jsonify({
|
|
'message': 'Capture d\\'écran non implémentée dans la version allégée',
|
|
'status': 'not_implemented'
|
|
}), 501
|
|
|
|
@screen_capture_bp.route('/status', methods=['GET'])
|
|
def capture_status():
|
|
"""Statut du service de capture."""
|
|
return jsonify({
|
|
'status': 'disabled',
|
|
'message': 'Service de capture désactivé en mode allégé'
|
|
})
|
|
''',
|
|
|
|
"real_demo.py": '''"""
|
|
API de démonstration réelle (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
real_demo_bp = Blueprint('real_demo', __name__)
|
|
|
|
@real_demo_bp.route('/demo/start', methods=['POST'])
|
|
def start_demo():
|
|
"""Démarre une démonstration (placeholder)."""
|
|
return jsonify({
|
|
'message': 'Démonstration non implémentée dans la version allégée',
|
|
'status': 'not_implemented'
|
|
}), 501
|
|
|
|
@real_demo_bp.route('/demo/status', methods=['GET'])
|
|
def demo_status():
|
|
"""Statut de la démonstration."""
|
|
return jsonify({
|
|
'status': 'disabled',
|
|
'message': 'Démonstration désactivée en mode allégé'
|
|
})
|
|
''',
|
|
|
|
"node_types.py": '''"""
|
|
API des types de nœuds
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
node_types_bp = Blueprint('node_types', __name__)
|
|
|
|
# Types de nœuds de base
|
|
NODE_TYPES = [
|
|
{
|
|
'id': 'start',
|
|
'name': 'Début',
|
|
'description': 'Point de départ du workflow',
|
|
'category': 'control',
|
|
'inputs': [],
|
|
'outputs': ['next']
|
|
},
|
|
{
|
|
'id': 'end',
|
|
'name': 'Fin',
|
|
'description': 'Point de fin du workflow',
|
|
'category': 'control',
|
|
'inputs': ['previous'],
|
|
'outputs': []
|
|
},
|
|
{
|
|
'id': 'action',
|
|
'name': 'Action',
|
|
'description': 'Action générique',
|
|
'category': 'action',
|
|
'inputs': ['previous'],
|
|
'outputs': ['next', 'error']
|
|
},
|
|
{
|
|
'id': 'condition',
|
|
'name': 'Condition',
|
|
'description': 'Branchement conditionnel',
|
|
'category': 'logic',
|
|
'inputs': ['previous'],
|
|
'outputs': ['true', 'false']
|
|
}
|
|
]
|
|
|
|
@node_types_bp.route('/', methods=['GET'])
|
|
def list_node_types():
|
|
"""Liste tous les types de nœuds disponibles."""
|
|
return jsonify(NODE_TYPES)
|
|
|
|
@node_types_bp.route('/<node_type_id>', methods=['GET'])
|
|
def get_node_type(node_type_id: str):
|
|
"""Récupère un type de nœud spécifique."""
|
|
for node_type in NODE_TYPES:
|
|
if node_type['id'] == node_type_id:
|
|
return jsonify(node_type)
|
|
|
|
return jsonify({'error': 'Type de nœud non trouvé'}), 404
|
|
'''
|
|
}
|
|
|
|
# Créer les modules manquants
|
|
for filename, content in api_modules.items():
|
|
file_path = api_path / filename
|
|
if not file_path.exists():
|
|
file_path.write_text(content)
|
|
print(f"✅ Créé api/{filename}")
|
|
else:
|
|
print(f"⚠️ api/{filename} existe déjà")
|
|
|
|
def fix_services_directory():
|
|
"""Crée le répertoire services avec les modules nécessaires."""
|
|
print_subsection("Correction du Répertoire Services")
|
|
|
|
backend_path = Path("visual_workflow_builder/backend")
|
|
services_path = backend_path / "services"
|
|
|
|
# Créer le répertoire services
|
|
services_path.mkdir(exist_ok=True)
|
|
|
|
# Créer __init__.py
|
|
init_file = services_path / "__init__.py"
|
|
if not init_file.exists():
|
|
init_file.write_text('"""Services Package"""')
|
|
print("✅ Créé services/__init__.py")
|
|
|
|
# Modules services essentiels
|
|
services_modules = {
|
|
"converter.py": '''"""
|
|
Convertisseur de workflows visuels vers graphes
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from typing import Any, Dict, List
|
|
from models import VisualWorkflow
|
|
|
|
class ConversionError(Exception):
|
|
"""Erreur de conversion."""
|
|
pass
|
|
|
|
class WorkflowGraph:
|
|
"""Représentation graphe d'un workflow."""
|
|
|
|
def __init__(self, workflow_id: str):
|
|
self.workflow_id = workflow_id
|
|
self.nodes = []
|
|
self.edges = []
|
|
self.metadata = {}
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
'workflow_id': self.workflow_id,
|
|
'nodes': self.nodes,
|
|
'edges': self.edges,
|
|
'metadata': self.metadata
|
|
}
|
|
|
|
class VisualToGraphConverter:
|
|
"""Convertit un workflow visuel en graphe."""
|
|
|
|
def __init__(self):
|
|
self.warnings = []
|
|
|
|
def convert(self, workflow: VisualWorkflow) -> WorkflowGraph:
|
|
"""Convertit un workflow visuel en graphe."""
|
|
graph = WorkflowGraph(workflow.id)
|
|
|
|
# Conversion basique
|
|
graph.nodes = [node.to_dict() for node in workflow.nodes]
|
|
graph.edges = [edge.to_dict() for edge in workflow.edges]
|
|
graph.metadata = {
|
|
'name': workflow.name,
|
|
'description': workflow.description,
|
|
'variables': [var.to_dict() for var in workflow.variables]
|
|
}
|
|
|
|
return graph
|
|
|
|
def get_warnings(self) -> List[str]:
|
|
"""Retourne les avertissements de conversion."""
|
|
return self.warnings
|
|
|
|
def convert_visual_to_graph(workflow: VisualWorkflow) -> WorkflowGraph:
|
|
"""Fonction utilitaire de conversion."""
|
|
converter = VisualToGraphConverter()
|
|
return converter.convert(workflow)
|
|
''',
|
|
|
|
"execution_integration.py": '''"""
|
|
Intégration avec le système d'exécution
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from enum import Enum
|
|
from typing import Dict, Any, List, Optional
|
|
from datetime import datetime
|
|
|
|
class ExecutionStatus(Enum):
|
|
"""Statuts d'exécution."""
|
|
PENDING = "pending"
|
|
RUNNING = "running"
|
|
COMPLETED = "completed"
|
|
FAILED = "failed"
|
|
CANCELLED = "cancelled"
|
|
|
|
class ExecutionResult:
|
|
"""Résultat d'exécution."""
|
|
|
|
def __init__(self, execution_id: str, status: ExecutionStatus):
|
|
self.execution_id = execution_id
|
|
self.status = status
|
|
self.started_at = datetime.now().isoformat()
|
|
self.completed_at = None
|
|
self.error_message = None
|
|
self.result_data = {}
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
return {
|
|
'execution_id': self.execution_id,
|
|
'status': self.status.value,
|
|
'started_at': self.started_at,
|
|
'completed_at': self.completed_at,
|
|
'error_message': self.error_message,
|
|
'result_data': self.result_data
|
|
}
|
|
|
|
class MockExecutor:
|
|
"""Exécuteur simulé pour la version allégée."""
|
|
|
|
def __init__(self):
|
|
self.executions: Dict[str, ExecutionResult] = {}
|
|
|
|
def execute_workflow(self, workflow_id: str, variables: Dict[str, Any]) -> str:
|
|
"""Lance l'exécution d'un workflow."""
|
|
execution_id = f"exec_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
|
result = ExecutionResult(execution_id, ExecutionStatus.PENDING)
|
|
self.executions[execution_id] = result
|
|
|
|
# Simulation: marquer comme complété immédiatement
|
|
result.status = ExecutionStatus.COMPLETED
|
|
result.completed_at = datetime.now().isoformat()
|
|
result.result_data = {
|
|
'workflow_id': workflow_id,
|
|
'variables': variables,
|
|
'message': 'Exécution simulée (mode allégé)'
|
|
}
|
|
|
|
return execution_id
|
|
|
|
def get_execution_status(self, execution_id: str) -> Optional[ExecutionResult]:
|
|
"""Récupère le statut d'une exécution."""
|
|
return self.executions.get(execution_id)
|
|
|
|
def cancel_execution(self, execution_id: str) -> bool:
|
|
"""Annule une exécution."""
|
|
if execution_id in self.executions:
|
|
result = self.executions[execution_id]
|
|
if result.status in [ExecutionStatus.PENDING, ExecutionStatus.RUNNING]:
|
|
result.status = ExecutionStatus.CANCELLED
|
|
result.completed_at = datetime.now().isoformat()
|
|
return True
|
|
return False
|
|
|
|
def list_executions(self, workflow_id: Optional[str] = None) -> List[Dict[str, Any]]:
|
|
"""Liste les exécutions."""
|
|
executions = []
|
|
for result in self.executions.values():
|
|
if workflow_id is None or result.result_data.get('workflow_id') == workflow_id:
|
|
executions.append(result.to_dict())
|
|
return executions
|
|
|
|
# Instance globale
|
|
_executor = MockExecutor()
|
|
|
|
def get_executor() -> MockExecutor:
|
|
"""Retourne l'instance de l'exécuteur."""
|
|
return _executor
|
|
'''
|
|
}
|
|
|
|
# Créer les modules services
|
|
for filename, content in services_modules.items():
|
|
file_path = services_path / filename
|
|
if not file_path.exists():
|
|
file_path.write_text(content)
|
|
print(f"✅ Créé services/{filename}")
|
|
else:
|
|
print(f"⚠️ services/{filename} existe déjà")
|
|
|
|
def fix_optional_blueprints():
|
|
"""Crée des versions minimales des blueprints optionnels."""
|
|
print_subsection("Correction des Blueprints Optionnels")
|
|
|
|
backend_path = Path("visual_workflow_builder/backend")
|
|
api_path = backend_path / "api"
|
|
|
|
optional_blueprints = {
|
|
"self_healing.py": '''"""
|
|
API Self-Healing (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
self_healing_bp = Blueprint('self_healing', __name__)
|
|
|
|
@self_healing_bp.route('/status', methods=['GET'])
|
|
def self_healing_status():
|
|
"""Statut du self-healing."""
|
|
return jsonify({
|
|
'status': 'disabled',
|
|
'message': 'Self-healing désactivé en mode allégé'
|
|
})
|
|
''',
|
|
|
|
"visual_targets.py": '''"""
|
|
API Visual Targets (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
visual_targets_bp = Blueprint('visual_targets', __name__)
|
|
|
|
def init_visual_target_manager(screen_capturer, ui_detector, fusion_engine):
|
|
"""Initialise le gestionnaire de cibles visuelles (placeholder)."""
|
|
pass
|
|
|
|
@visual_targets_bp.route('/status', methods=['GET'])
|
|
def visual_targets_status():
|
|
"""Statut des cibles visuelles."""
|
|
return jsonify({
|
|
'status': 'disabled',
|
|
'message': 'Cibles visuelles désactivées en mode allégé'
|
|
})
|
|
''',
|
|
|
|
"element_detection.py": '''"""
|
|
API Element Detection (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
element_detection_bp = Blueprint('element_detection', __name__)
|
|
|
|
def init_element_detection(ui_detector, screen_capturer):
|
|
"""Initialise la détection d'éléments (placeholder)."""
|
|
pass
|
|
|
|
@element_detection_bp.route('/status', methods=['GET'])
|
|
def element_detection_status():
|
|
"""Statut de la détection d'éléments."""
|
|
return jsonify({
|
|
'status': 'disabled',
|
|
'message': 'Détection d\\'éléments désactivée en mode allégé'
|
|
})
|
|
''',
|
|
|
|
"analytics.py": '''"""
|
|
API Analytics (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
analytics_bp = Blueprint('analytics', __name__)
|
|
|
|
@analytics_bp.route('/stats', methods=['GET'])
|
|
def get_stats():
|
|
"""Statistiques (placeholder)."""
|
|
return jsonify({
|
|
'workflows': 0,
|
|
'executions': 0,
|
|
'message': 'Analytics désactivées en mode allégé'
|
|
})
|
|
''',
|
|
|
|
"templates.py": '''"""
|
|
API Templates (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
templates_bp = Blueprint('templates', __name__)
|
|
|
|
@templates_bp.route('/', methods=['GET'])
|
|
def list_templates():
|
|
"""Liste des templates."""
|
|
return jsonify([])
|
|
|
|
@templates_bp.route('/<template_id>', methods=['GET'])
|
|
def get_template(template_id):
|
|
"""Récupère un template."""
|
|
return jsonify({'error': 'Template non trouvé'}), 404
|
|
''',
|
|
|
|
"executions.py": '''"""
|
|
API Executions (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
executions_bp = Blueprint('executions', __name__)
|
|
|
|
@executions_bp.route('/', methods=['GET'])
|
|
def list_executions():
|
|
"""Liste des exécutions."""
|
|
return jsonify([])
|
|
|
|
@executions_bp.route('/<execution_id>', methods=['GET'])
|
|
def get_execution(execution_id):
|
|
"""Récupère une exécution."""
|
|
return jsonify({'error': 'Exécution non trouvée'}), 404
|
|
''',
|
|
|
|
"import_export.py": '''"""
|
|
API Import/Export (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
from flask import Blueprint, jsonify
|
|
|
|
import_export_bp = Blueprint('import_export', __name__)
|
|
|
|
@import_export_bp.route('/export/<workflow_id>', methods=['GET'])
|
|
def export_workflow(workflow_id):
|
|
"""Export d'un workflow."""
|
|
return jsonify({'error': 'Export non implémenté en mode allégé'}), 501
|
|
|
|
@import_export_bp.route('/import', methods=['POST'])
|
|
def import_workflow():
|
|
"""Import d'un workflow."""
|
|
return jsonify({'error': 'Import non implémenté en mode allégé'}), 501
|
|
''',
|
|
|
|
"websocket_handlers.py": '''"""
|
|
Gestionnaires WebSocket (version minimale)
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
# Placeholder pour les gestionnaires WebSocket
|
|
# En mode allégé, les WebSockets sont désactivés
|
|
|
|
def init_websocket_handlers():
|
|
"""Initialise les gestionnaires WebSocket (placeholder)."""
|
|
pass
|
|
'''
|
|
}
|
|
|
|
# Créer les blueprints optionnels
|
|
for filename, content in optional_blueprints.items():
|
|
file_path = api_path / filename
|
|
if not file_path.exists():
|
|
file_path.write_text(content)
|
|
print(f"✅ Créé api/{filename}")
|
|
else:
|
|
print(f"⚠️ api/{filename} existe déjà")
|
|
|
|
def create_test_script():
|
|
"""Crée un script de test pour vérifier le backend."""
|
|
print_subsection("Création du Script de Test")
|
|
|
|
test_script = '''#!/usr/bin/env python3
|
|
"""
|
|
Test du Backend Visual Workflow Builder
|
|
|
|
Auteur : Dom, Alice, Kiro - 08 janvier 2026
|
|
"""
|
|
|
|
import requests
|
|
import json
|
|
import time
|
|
import sys
|
|
|
|
def test_backend(base_url="http://localhost:5002"):
|
|
"""Test le backend VWB."""
|
|
print(f"🧪 Test du backend: {base_url}")
|
|
|
|
# Test 1: Health check
|
|
try:
|
|
response = requests.get(f"{base_url}/health", timeout=5)
|
|
if response.status_code == 200:
|
|
print("✅ Health check OK")
|
|
print(f" Réponse: {response.json()}")
|
|
else:
|
|
print(f"❌ Health check échoué: {response.status_code}")
|
|
return False
|
|
except Exception as e:
|
|
print(f"❌ Erreur health check: {e}")
|
|
return False
|
|
|
|
# Test 2: Liste des workflows
|
|
try:
|
|
response = requests.get(f"{base_url}/api/workflows", timeout=5)
|
|
if response.status_code == 200:
|
|
workflows = response.json()
|
|
print(f"✅ Liste workflows OK ({len(workflows)} workflows)")
|
|
else:
|
|
print(f"❌ Liste workflows échoué: {response.status_code}")
|
|
return False
|
|
except Exception as e:
|
|
print(f"❌ Erreur liste workflows: {e}")
|
|
return False
|
|
|
|
# Test 3: Création d'un workflow
|
|
try:
|
|
test_workflow = {
|
|
"name": "Test Workflow",
|
|
"description": "Workflow de test automatique",
|
|
"created_by": "test_script"
|
|
}
|
|
|
|
response = requests.post(
|
|
f"{base_url}/api/workflows",
|
|
json=test_workflow,
|
|
timeout=5
|
|
)
|
|
|
|
if response.status_code == 201:
|
|
created_workflow = response.json()
|
|
workflow_id = created_workflow['id']
|
|
print(f"✅ Création workflow OK (ID: {workflow_id})")
|
|
|
|
# Test 4: Récupération du workflow créé
|
|
response = requests.get(f"{base_url}/api/workflows/{workflow_id}", timeout=5)
|
|
if response.status_code == 200:
|
|
print("✅ Récupération workflow OK")
|
|
return True
|
|
else:
|
|
print(f"❌ Récupération workflow échoué: {response.status_code}")
|
|
return False
|
|
else:
|
|
print(f"❌ Création workflow échoué: {response.status_code}")
|
|
print(f" Réponse: {response.text}")
|
|
return False
|
|
except Exception as e:
|
|
print(f"❌ Erreur création workflow: {e}")
|
|
return False
|
|
|
|
if __name__ == "__main__":
|
|
print("🚀 Test automatique du backend VWB")
|
|
print("=" * 40)
|
|
|
|
# Attendre que le serveur soit prêt
|
|
print("⏳ Attente du démarrage du serveur...")
|
|
time.sleep(2)
|
|
|
|
success = test_backend()
|
|
|
|
if success:
|
|
print("\\n✅ Tous les tests sont passés!")
|
|
sys.exit(0)
|
|
else:
|
|
print("\\n❌ Certains tests ont échoué")
|
|
sys.exit(1)
|
|
'''
|
|
|
|
test_path = Path("visual_workflow_builder/backend/test_backend.py")
|
|
test_path.write_text(test_script)
|
|
print(f"✅ Script de test créé: {test_path}")
|
|
|
|
def main():
|
|
"""Fonction principale de correction."""
|
|
print_section("CORRECTION DES ERREURS BACKEND VWB")
|
|
print("Auteur : Dom, Alice, Kiro - 08 janvier 2026")
|
|
|
|
# Vérifier que nous sommes dans le bon répertoire
|
|
if not Path("visual_workflow_builder/backend").exists():
|
|
print("❌ Erreur: Répertoire backend introuvable")
|
|
print(" Exécutez ce script depuis la racine du projet")
|
|
return
|
|
|
|
# Corrections
|
|
fix_missing_api_modules()
|
|
fix_services_directory()
|
|
fix_optional_blueprints()
|
|
create_test_script()
|
|
|
|
print_section("CORRECTIONS TERMINÉES")
|
|
print("✅ Tous les modules manquants ont été créés")
|
|
print("✅ Le backend devrait maintenant démarrer sans erreurs")
|
|
print("")
|
|
print("Pour tester le backend:")
|
|
print("1. cd visual_workflow_builder/backend")
|
|
print("2. ./start_fast.sh")
|
|
print("3. Dans un autre terminal: python test_backend.py")
|
|
|
|
if __name__ == "__main__":
|
|
main() |