Files
rpa_vision_v3/visual_workflow_builder/backend/app.py
Dom 38a1a5ddd8 feat(coaching): Implement complete COACHING mode infrastructure
Add comprehensive COACHING mode system with:

Backend:
- core/coaching module with session persistence and metrics
- CoachingSessionPersistence for pause/resume sessions
- CoachingMetricsCollector with learning progress tracking
- REST API blueprint for coaching sessions management
- Execution integration with COACHING mode support

Frontend:
- CoachingPanel component with keyboard shortcuts
- Decision buttons (accept/reject/correct/manual/skip)
- Real-time stats display and correction editor
- CorrectionPacksDashboard for pack visualization
- WebSocket hooks for real-time COACHING events

Metrics & Monitoring:
- WorkflowLearningMetrics with confidence scoring
- GlobalCoachingMetrics for system-wide analytics
- AUTO mode readiness detection (85% acceptance threshold)
- Learning progress levels (OBSERVATION → COACHING → AUTO)

Tests:
- E2E tests for complete OBSERVATION → AUTO journey
- Session persistence and recovery tests
- Metrics threshold validation tests

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 08:40:54 +01:00

209 lines
6.9 KiB
Python

"""
Visual Workflow Builder - Backend Flask Application
This is the main entry point for the Visual Workflow Builder backend API.
It provides REST endpoints for workflow management and WebSocket support
for real-time execution updates.
"""
from flask import Flask
from flask_cors import CORS
from flask_socketio import SocketIO
from flask_sqlalchemy import SQLAlchemy
from flask_caching import Cache
import os
from dotenv import load_dotenv
# Load environment variables
load_dotenv()
# Initialize Flask app
app = Flask(__name__)
# Configuration
app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev-secret-key-change-in-production')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL', 'sqlite:///workflows.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 # 10MB max upload
app.config['CACHE_TYPE'] = 'redis' if os.getenv('REDIS_URL') else 'simple'
app.config['CACHE_REDIS_URL'] = os.getenv('REDIS_URL', 'redis://localhost:6379/0')
# Initialize extensions
db = SQLAlchemy(app)
cache = Cache(app)
socketio = SocketIO(
app,
cors_allowed_origins="*",
async_mode='threading',
logger=True,
engineio_logger=True
)
# Enable CORS
CORS(app, resources={
r"/api/*": {
"origins": os.getenv('CORS_ORIGINS', 'http://localhost:3000').split(','),
"methods": ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
"allow_headers": ["Content-Type", "Authorization"]
}
})
# Import and register blueprints (minimal set)
from api.workflows import workflows_bp
from api.screen_capture import screen_capture_bp
from api.real_demo import real_demo_bp
from api.errors import error_response
app.register_blueprint(workflows_bp, url_prefix='/api/workflows')
app.register_blueprint(screen_capture_bp, url_prefix='/api/screen-capture')
app.register_blueprint(real_demo_bp)
# Optional / Phase 2+ blueprints (loaded only if modules are available)
try:
from api.self_healing import self_healing_bp
app.register_blueprint(self_healing_bp)
except ImportError as e:
print(f"⚠️ Blueprint self_healing désactivé: {e}")
try:
from api.visual_targets import visual_targets_bp, init_visual_target_manager
app.register_blueprint(visual_targets_bp)
VISUAL_TARGETS_BP_AVAILABLE = True
except ImportError as e:
print(f"⚠️ Blueprint visual_targets désactivé: {e}")
VISUAL_TARGETS_BP_AVAILABLE = False
init_visual_target_manager = None
try:
from api.element_detection import element_detection_bp, init_element_detection
app.register_blueprint(element_detection_bp)
ELEMENT_DETECTION_BP_AVAILABLE = True
except ImportError as e:
print(f"⚠️ Blueprint element_detection désactivé: {e}")
ELEMENT_DETECTION_BP_AVAILABLE = False
init_element_detection = None
try:
from api.analytics import analytics_bp
app.register_blueprint(analytics_bp, url_prefix='/api/analytics')
except ImportError:
pass
# Register other blueprints (optional - depends on Phase 2+ services)
try:
from api.templates import templates_bp
app.register_blueprint(templates_bp, url_prefix='/api/templates')
except ImportError as e:
print(f"⚠️ Blueprint templates désactivé: {e}")
from api.node_types import node_types_bp
app.register_blueprint(node_types_bp, url_prefix='/api/node-types')
try:
from api.executions import executions_bp
app.register_blueprint(executions_bp, url_prefix='/api/executions')
except ImportError as e:
print(f"⚠️ Blueprint executions désactivé: {e}")
try:
from api.import_export import import_export_bp
app.register_blueprint(import_export_bp, url_prefix='/api')
except ImportError as e:
print(f"⚠️ Blueprint import_export désactivé: {e}")
try:
from api.correction_packs import correction_packs_bp
app.register_blueprint(correction_packs_bp, url_prefix='/api')
print("✅ Blueprint correction_packs enregistré")
except ImportError as e:
print(f"⚠️ Blueprint correction_packs désactivé: {e}")
try:
from api.coaching_sessions import coaching_sessions_bp
app.register_blueprint(coaching_sessions_bp, url_prefix='/api/coaching-sessions')
print("✅ Blueprint coaching_sessions enregistré")
except ImportError as e:
print(f"⚠️ Blueprint coaching_sessions désactivé: {e}")
# Import WebSocket handlers (optional)
try:
from api import websocket_handlers # noqa: F401
except Exception as e:
print(f"⚠️ WebSocket handlers désactivés: {e}")
# Global error handlers
@app.errorhandler(404)
def not_found(error):
"""Handle 404 errors"""
return error_response(404, "Resource not found")
@app.errorhandler(405)
def method_not_allowed(error):
"""Handle 405 errors"""
return error_response(405, "Method not allowed")
@app.errorhandler(500)
def internal_error(error):
"""Handle 500 errors"""
return error_response(500, "Internal server error")
@app.errorhandler(Exception)
def handle_exception(error):
"""Handle all unhandled exceptions"""
import traceback
traceback.print_exc()
return error_response(500, f"Unexpected error: {str(error)}")
# Health check endpoint
@app.route('/health')
def health_check():
"""Health check endpoint for monitoring"""
return {'status': 'healthy', 'version': '1.0.0'}
# Create database tables
with app.app_context():
db.create_all()
# Initialize VisualTargetManager with RPA Vision V3 components (optional)
try:
from core.capture.screen_capturer import ScreenCapturer
from core.detection.ui_detector import UIDetector
from core.embedding.fusion_engine import FusionEngine
# Only initialize if the related blueprints were actually loaded
if VISUAL_TARGETS_BP_AVAILABLE and init_visual_target_manager:
screen_capturer = ScreenCapturer()
ui_detector = UIDetector()
fusion_engine = FusionEngine()
init_visual_target_manager(screen_capturer, ui_detector, fusion_engine)
if ELEMENT_DETECTION_BP_AVAILABLE and init_element_detection:
# Reuse the same instances when possible
if 'ui_detector' not in locals():
ui_detector = UIDetector()
if 'screen_capturer' not in locals():
screen_capturer = ScreenCapturer()
init_element_detection(ui_detector, screen_capturer)
if (VISUAL_TARGETS_BP_AVAILABLE and init_visual_target_manager) or (ELEMENT_DETECTION_BP_AVAILABLE and init_element_detection):
print("✅ Services visuels initialisés (VisualTargets / ElementDetection)")
except ImportError as e:
print(f"⚠️ Core RPA non disponible pour l'initialisation visuelle: {e}")
except Exception as e:
print(f"❌ Erreur lors de l'initialisation des services visuels: {e}")
if __name__ == '__main__':
port = int(os.getenv('PORT', 5002))
debug = os.getenv('FLASK_ENV') == 'development'
socketio.run(
app,
host='0.0.0.0',
port=port,
debug=debug,
use_reloader=debug,
allow_unsafe_werkzeug=True # For development only
)