- 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>
399 lines
14 KiB
Python
399 lines
14 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Script de Vérification Complète des Propriétés d'Étapes VWB
|
|
Auteur : Dom, Alice, Kiro - 12 janvier 2026
|
|
|
|
Ce script vérifie que toutes les actions du catalogue VWB ont leurs propriétés
|
|
correctement définies et implémentées dans le système de propriétés.
|
|
"""
|
|
|
|
import json
|
|
import sys
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Dict, List, Any, Set
|
|
from datetime import datetime
|
|
|
|
# Ajouter le répertoire racine au path
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
def analyser_catalogue_statique() -> Dict[str, Any]:
|
|
"""
|
|
Analyse le catalogue statique pour extraire toutes les actions et leurs paramètres.
|
|
|
|
Returns:
|
|
Dictionnaire avec les actions et leurs configurations
|
|
"""
|
|
print("📋 Analyse du catalogue statique...")
|
|
|
|
# Lire le fichier TypeScript du catalogue statique
|
|
catalogue_path = Path("visual_workflow_builder/frontend/src/data/staticCatalog.ts")
|
|
|
|
if not catalogue_path.exists():
|
|
print(f"❌ Fichier catalogue non trouvé : {catalogue_path}")
|
|
return {}
|
|
|
|
try:
|
|
with open(catalogue_path, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
# Extraire les actions (analyse simple du contenu)
|
|
actions_trouvees = {}
|
|
|
|
# Rechercher les définitions d'actions
|
|
import re
|
|
|
|
# Pattern pour extraire les IDs d'actions
|
|
pattern_id = r"id:\s*['\"]([^'\"]+)['\"]"
|
|
ids = re.findall(pattern_id, contenu)
|
|
|
|
# Pattern pour extraire les noms d'actions
|
|
pattern_name = r"name:\s*['\"]([^'\"]+)['\"]"
|
|
names = re.findall(pattern_name, contenu)
|
|
|
|
# Pattern pour extraire les catégories
|
|
pattern_category = r"category:\s*['\"]([^'\"]+)['\"]"
|
|
categories = re.findall(pattern_category, contenu)
|
|
|
|
# Combiner les informations
|
|
for i, action_id in enumerate(ids):
|
|
actions_trouvees[action_id] = {
|
|
'id': action_id,
|
|
'name': names[i] if i < len(names) else action_id,
|
|
'category': categories[i] if i < len(categories) else 'unknown',
|
|
'parameters_found': True, # Présumé vrai pour le catalogue statique
|
|
}
|
|
|
|
print(f"✅ {len(actions_trouvees)} actions trouvées dans le catalogue statique")
|
|
return actions_trouvees
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur lors de l'analyse du catalogue : {e}")
|
|
return {}
|
|
|
|
def analyser_backend_registry() -> Dict[str, Any]:
|
|
"""
|
|
Analyse le registry backend pour vérifier les actions disponibles.
|
|
|
|
Returns:
|
|
Dictionnaire avec les actions du backend
|
|
"""
|
|
print("🔧 Analyse du registry backend...")
|
|
|
|
try:
|
|
# Importer le registry
|
|
from visual_workflow_builder.backend.actions.registry import get_global_registry
|
|
|
|
registry = get_global_registry()
|
|
|
|
# Obtenir les informations du registry
|
|
info = registry.get_registry_stats()
|
|
actions = registry.list_actions()
|
|
|
|
actions_backend = {}
|
|
for action_id in actions:
|
|
metadata = registry.get_action_metadata(action_id)
|
|
actions_backend[action_id] = {
|
|
'id': action_id,
|
|
'metadata': metadata,
|
|
'class_available': registry.get_action_class(action_id) is not None,
|
|
}
|
|
|
|
print(f"✅ {len(actions_backend)} actions trouvées dans le registry backend")
|
|
return {
|
|
'stats': info,
|
|
'actions': actions_backend,
|
|
}
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur lors de l'analyse du registry backend : {e}")
|
|
return {}
|
|
|
|
def analyser_composants_frontend() -> Dict[str, Any]:
|
|
"""
|
|
Analyse les composants frontend pour vérifier l'implémentation des propriétés.
|
|
|
|
Returns:
|
|
Dictionnaire avec l'état des composants frontend
|
|
"""
|
|
print("🎨 Analyse des composants frontend...")
|
|
|
|
composants_analyses = {}
|
|
|
|
# Analyser PropertiesPanel principal
|
|
properties_panel_path = Path("visual_workflow_builder/frontend/src/components/PropertiesPanel/index.tsx")
|
|
if properties_panel_path.exists():
|
|
try:
|
|
with open(properties_panel_path, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
composants_analyses['PropertiesPanel'] = {
|
|
'exists': True,
|
|
'has_step_parameters_config': 'stepParametersConfig' in contenu,
|
|
'has_vwb_integration': 'useVWBStepIntegration' in contenu,
|
|
'has_visual_selector': 'VisualSelector' in contenu,
|
|
'has_variable_autocomplete': 'VariableAutocomplete' in contenu,
|
|
'file_size': len(contenu),
|
|
}
|
|
except Exception as e:
|
|
composants_analyses['PropertiesPanel'] = {'exists': True, 'error': str(e)}
|
|
else:
|
|
composants_analyses['PropertiesPanel'] = {'exists': False}
|
|
|
|
# Analyser VWBActionProperties
|
|
vwb_properties_path = Path("visual_workflow_builder/frontend/src/components/PropertiesPanel/VWBActionProperties.tsx")
|
|
if vwb_properties_path.exists():
|
|
try:
|
|
with open(vwb_properties_path, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
composants_analyses['VWBActionProperties'] = {
|
|
'exists': True,
|
|
'has_visual_anchor_editor': 'VisualAnchorEditor' in contenu,
|
|
'has_parameter_validation': 'validateParameters' in contenu,
|
|
'has_real_time_validation': 'validation' in contenu,
|
|
'has_examples_display': 'examples' in contenu,
|
|
'file_size': len(contenu),
|
|
}
|
|
except Exception as e:
|
|
composants_analyses['VWBActionProperties'] = {'exists': True, 'error': str(e)}
|
|
else:
|
|
composants_analyses['VWBActionProperties'] = {'exists': False}
|
|
|
|
# Analyser useVWBStepIntegration hook
|
|
hook_path = Path("visual_workflow_builder/frontend/src/hooks/useVWBStepIntegration.ts")
|
|
if hook_path.exists():
|
|
try:
|
|
with open(hook_path, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
composants_analyses['useVWBStepIntegration'] = {
|
|
'exists': True,
|
|
'has_create_vwb_step': 'createVWBStep' in contenu,
|
|
'has_validation': 'validateVWBStep' in contenu,
|
|
'has_drag_drop_support': 'convertDragDataToVWBStep' in contenu,
|
|
'file_size': len(contenu),
|
|
}
|
|
except Exception as e:
|
|
composants_analyses['useVWBStepIntegration'] = {'exists': True, 'error': str(e)}
|
|
else:
|
|
composants_analyses['useVWBStepIntegration'] = {'exists': False}
|
|
|
|
print(f"✅ {len(composants_analyses)} composants analysés")
|
|
return composants_analyses
|
|
|
|
def verifier_coherence_types() -> Dict[str, Any]:
|
|
"""
|
|
Vérifie la cohérence des types TypeScript entre les différents fichiers.
|
|
|
|
Returns:
|
|
Résultats de la vérification de cohérence
|
|
"""
|
|
print("🔍 Vérification de la cohérence des types...")
|
|
|
|
coherence = {
|
|
'catalog_types_exists': False,
|
|
'main_types_exists': False,
|
|
'types_coherent': False,
|
|
'issues': [],
|
|
}
|
|
|
|
# Vérifier catalog.ts
|
|
catalog_types_path = Path("visual_workflow_builder/frontend/src/types/catalog.ts")
|
|
if catalog_types_path.exists():
|
|
coherence['catalog_types_exists'] = True
|
|
try:
|
|
with open(catalog_types_path, 'r', encoding='utf-8') as f:
|
|
contenu = f.read()
|
|
|
|
# Vérifier la présence des types essentiels
|
|
types_essentiels = [
|
|
'VWBCatalogAction',
|
|
'VWBActionParameter',
|
|
'VWBVisualAnchor',
|
|
'VWBActionValidationResult',
|
|
]
|
|
|
|
for type_name in types_essentiels:
|
|
if type_name not in contenu:
|
|
coherence['issues'].append(f"Type manquant : {type_name}")
|
|
|
|
except Exception as e:
|
|
coherence['issues'].append(f"Erreur lecture catalog.ts : {e}")
|
|
else:
|
|
coherence['issues'].append("Fichier catalog.ts manquant")
|
|
|
|
# Vérifier index.ts principal
|
|
main_types_path = Path("visual_workflow_builder/frontend/src/types/index.ts")
|
|
if main_types_path.exists():
|
|
coherence['main_types_exists'] = True
|
|
else:
|
|
coherence['issues'].append("Fichier types/index.ts manquant")
|
|
|
|
coherence['types_coherent'] = len(coherence['issues']) == 0
|
|
|
|
print(f"✅ Vérification de cohérence terminée - {len(coherence['issues'])} problèmes trouvés")
|
|
return coherence
|
|
|
|
def generer_rapport_complet() -> Dict[str, Any]:
|
|
"""
|
|
Génère un rapport complet de l'état des propriétés d'étapes.
|
|
|
|
Returns:
|
|
Rapport complet
|
|
"""
|
|
print("📊 Génération du rapport complet...")
|
|
|
|
rapport = {
|
|
'timestamp': datetime.now().isoformat(),
|
|
'version': '1.0.0',
|
|
'auteur': 'Dom, Alice, Kiro',
|
|
'catalogue_statique': analyser_catalogue_statique(),
|
|
'backend_registry': analyser_backend_registry(),
|
|
'composants_frontend': analyser_composants_frontend(),
|
|
'coherence_types': verifier_coherence_types(),
|
|
}
|
|
|
|
# Calculer des métriques globales
|
|
catalogue_actions = rapport['catalogue_statique']
|
|
backend_actions = rapport['backend_registry'].get('actions', {})
|
|
|
|
rapport['metriques'] = {
|
|
'total_actions_catalogue': len(catalogue_actions),
|
|
'total_actions_backend': len(backend_actions),
|
|
'actions_communes': len(set(catalogue_actions.keys()) & set(backend_actions.keys())),
|
|
'actions_catalogue_seulement': list(set(catalogue_actions.keys()) - set(backend_actions.keys())),
|
|
'actions_backend_seulement': list(set(backend_actions.keys()) - set(catalogue_actions.keys())),
|
|
}
|
|
|
|
# Évaluer l'état global
|
|
composants = rapport['composants_frontend']
|
|
coherence = rapport['coherence_types']
|
|
|
|
rapport['etat_global'] = {
|
|
'properties_panel_ok': composants.get('PropertiesPanel', {}).get('exists', False),
|
|
'vwb_properties_ok': composants.get('VWBActionProperties', {}).get('exists', False),
|
|
'integration_hook_ok': composants.get('useVWBStepIntegration', {}).get('exists', False),
|
|
'types_coherents': coherence.get('types_coherent', False),
|
|
'pret_pour_production': False, # Sera calculé
|
|
}
|
|
|
|
# Calculer si prêt pour production
|
|
etat = rapport['etat_global']
|
|
etat['pret_pour_production'] = all([
|
|
etat['properties_panel_ok'],
|
|
etat['vwb_properties_ok'],
|
|
etat['integration_hook_ok'],
|
|
etat['types_coherents'],
|
|
rapport['metriques']['total_actions_catalogue'] > 0,
|
|
])
|
|
|
|
return rapport
|
|
|
|
def sauvegarder_rapport(rapport: Dict[str, Any]) -> str:
|
|
"""
|
|
Sauvegarde le rapport dans un fichier JSON.
|
|
|
|
Args:
|
|
rapport: Rapport à sauvegarder
|
|
|
|
Returns:
|
|
Chemin du fichier sauvegardé
|
|
"""
|
|
# Créer le répertoire docs s'il n'existe pas
|
|
docs_dir = Path("docs")
|
|
docs_dir.mkdir(exist_ok=True)
|
|
|
|
# Nom du fichier avec timestamp
|
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
fichier_rapport = docs_dir / f"rapport_verification_proprietes_etapes_{timestamp}.json"
|
|
|
|
try:
|
|
with open(fichier_rapport, 'w', encoding='utf-8') as f:
|
|
json.dump(rapport, f, indent=2, ensure_ascii=False)
|
|
|
|
print(f"✅ Rapport sauvegardé : {fichier_rapport}")
|
|
return str(fichier_rapport)
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur sauvegarde rapport : {e}")
|
|
return ""
|
|
|
|
def afficher_resume(rapport: Dict[str, Any]):
|
|
"""
|
|
Affiche un résumé du rapport.
|
|
|
|
Args:
|
|
rapport: Rapport à résumer
|
|
"""
|
|
print("\n" + "="*60)
|
|
print("📋 RÉSUMÉ DE LA VÉRIFICATION DES PROPRIÉTÉS D'ÉTAPES")
|
|
print("="*60)
|
|
|
|
metriques = rapport['metriques']
|
|
etat = rapport['etat_global']
|
|
|
|
print(f"📊 Actions catalogue : {metriques['total_actions_catalogue']}")
|
|
print(f"🔧 Actions backend : {metriques['total_actions_backend']}")
|
|
print(f"🤝 Actions communes : {metriques['actions_communes']}")
|
|
|
|
print(f"\n🎨 Composants Frontend :")
|
|
print(f" - PropertiesPanel : {'✅' if etat['properties_panel_ok'] else '❌'}")
|
|
print(f" - VWBActionProperties : {'✅' if etat['vwb_properties_ok'] else '❌'}")
|
|
print(f" - useVWBStepIntegration : {'✅' if etat['integration_hook_ok'] else '❌'}")
|
|
|
|
print(f"\n🔍 Types TypeScript : {'✅' if etat['types_coherents'] else '❌'}")
|
|
|
|
print(f"\n🚀 Prêt pour production : {'✅' if etat['pret_pour_production'] else '❌'}")
|
|
|
|
# Afficher les problèmes s'il y en a
|
|
coherence = rapport['coherence_types']
|
|
if coherence.get('issues'):
|
|
print(f"\n⚠️ Problèmes détectés :")
|
|
for issue in coherence['issues']:
|
|
print(f" - {issue}")
|
|
|
|
# Afficher les actions manquantes
|
|
if metriques['actions_catalogue_seulement']:
|
|
print(f"\n📋 Actions catalogue non implémentées backend :")
|
|
for action in metriques['actions_catalogue_seulement']:
|
|
print(f" - {action}")
|
|
|
|
if metriques['actions_backend_seulement']:
|
|
print(f"\n🔧 Actions backend non référencées catalogue :")
|
|
for action in metriques['actions_backend_seulement']:
|
|
print(f" - {action}")
|
|
|
|
def main():
|
|
"""Fonction principale du script."""
|
|
print("🔍 Vérification Complète des Propriétés d'Étapes VWB")
|
|
print("Auteur : Dom, Alice, Kiro - 12 janvier 2026")
|
|
print("-" * 60)
|
|
|
|
try:
|
|
# Générer le rapport complet
|
|
rapport = generer_rapport_complet()
|
|
|
|
# Sauvegarder le rapport
|
|
fichier_rapport = sauvegarder_rapport(rapport)
|
|
|
|
# Afficher le résumé
|
|
afficher_resume(rapport)
|
|
|
|
# Déterminer le code de sortie
|
|
if rapport['etat_global']['pret_pour_production']:
|
|
print(f"\n✅ Système prêt - Toutes les propriétés d'étapes sont correctement implémentées")
|
|
return 0
|
|
else:
|
|
print(f"\n⚠️ Système nécessite des améliorations - Voir le rapport : {fichier_rapport}")
|
|
return 1
|
|
|
|
except Exception as e:
|
|
print(f"❌ Erreur lors de la vérification : {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
return 2
|
|
|
|
if __name__ == "__main__":
|
|
exit_code = main()
|
|
sys.exit(exit_code) |