From 9d87ed64c5230f403336fefe499a83f8699cd351 Mon Sep 17 00:00:00 2001 From: Dom Date: Wed, 22 Apr 2026 11:17:20 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20corrections=20audit=20qualit=C3=A9=20?= =?UTF-8?q?=E2=80=94=20stop/pause=20ORA=20+=20nettoyage=20debug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CRITIQUE : ajout should_continue callback dans ORALoop pour supporter les boutons Stop/Pause du frontend en mode verified et instruction. HAUTE : suppression sys.stdout.write de debug, logger.warning→debug dans _grounding_ocr. BASSE : suppression import mort 'field' dans observe_reason_act.py. Co-Authored-By: Claude Opus 4.6 (1M context) --- core/execution/input_handler.py | 3 +-- core/execution/observe_reason_act.py | 15 +++++++++++++-- visual_workflow_builder/backend/api_v3/execute.py | 6 +++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/core/execution/input_handler.py b/core/execution/input_handler.py index b9aab44f3..bd0bd9e5b 100644 --- a/core/execution/input_handler.py +++ b/core/execution/input_handler.py @@ -450,8 +450,7 @@ def _grounding_ocr(target_text: str, anchor_bbox: Optional[Dict] = None) -> Opti - Si anchor_bbox fourni → le plus proche de la position originale - Sinon → le plus proche du centre de l'écran (zone contenu) """ - logger.warning(f"[OCR-V2] Entrée _grounding_ocr target='{target_text}' bbox={anchor_bbox}") - import sys; sys.stdout.write(f" [OCR-V2] target='{target_text}' bbox={anchor_bbox}\n"); sys.stdout.flush() + logger.debug(f"[Grounding/OCR] target='{target_text}' bbox={anchor_bbox}") if not target_text: return None diff --git a/core/execution/observe_reason_act.py b/core/execution/observe_reason_act.py index d32c33030..4de925ed6 100644 --- a/core/execution/observe_reason_act.py +++ b/core/execution/observe_reason_act.py @@ -17,7 +17,7 @@ import base64 import os import json import re -from dataclasses import dataclass, field +from dataclasses import dataclass from typing import Any, Callable, Dict, List, Optional logger = logging.getLogger(__name__) @@ -135,10 +135,12 @@ class ORALoop: - auto : pHash toujours, VLM seulement si confiance < 0.95 """ - def __init__(self, max_retries: int = 2, max_steps: int = 50, verify_level: str = 'auto'): + def __init__(self, max_retries: int = 2, max_steps: int = 50, verify_level: str = 'auto', + should_continue: Optional[Callable[[], bool]] = None): self.max_retries = max_retries self.max_steps = max_steps self.verify_level = verify_level + self._should_continue = should_continue or (lambda: True) # Variables runtime injectées par le workflow self._variables: Dict[str, Any] = {} @@ -450,6 +452,11 @@ Règles: logger.warning("🧠 [ORA/instruction] CognitiveContext non disponible — mode dégradé") for step_num in range(self.max_steps): + if not self._should_continue(): + logger.info("⛔ [ORA/instruction] Arrêt demandé") + return LoopResult(success=False, steps_completed=step_num, + total_steps=self.max_steps, reason="stopped") + logger.info(f"\n{'='*60}") logger.info(f"📋 [ORA/instruction] Étape {step_num + 1}/{self.max_steps}") @@ -746,6 +753,10 @@ Règles: logger.info(f"🚀 [ORA] Démarrage workflow: {total} étapes, verify={self.verify_level}, retries={self.max_retries}") for i, step in enumerate(steps): + if not self._should_continue(): + logger.info("⛔ [ORA] Arrêt demandé") + return LoopResult(success=False, steps_completed=i, total_steps=total, reason="stopped") + logger.info(f"\n{'='*60}") logger.info(f"📋 [ORA] Étape {i+1}/{total}: {step.get('action_type', '?')} — {step.get('label', '')}") diff --git a/visual_workflow_builder/backend/api_v3/execute.py b/visual_workflow_builder/backend/api_v3/execute.py index 6804a5de7..93d922a07 100644 --- a/visual_workflow_builder/backend/api_v3/execute.py +++ b/visual_workflow_builder/backend/api_v3/execute.py @@ -1430,7 +1430,10 @@ def run_workflow_verified(execution_id: str, workflow_id: str, app): # --- Créer et lancer la boucle ORA --- from core.execution.observe_reason_act import ORALoop - ora = ORALoop(max_retries=2, max_steps=50, verify_level='auto') + ora = ORALoop( + max_retries=2, max_steps=50, verify_level='auto', + should_continue=lambda: not _execution_state.get('should_stop', False) + ) ora._variables = _execution_state.get('variables', {}) # Créer les ExecutionStep en amont pour le suivi @@ -1955,6 +1958,7 @@ def execute_instruction(): max_retries=2, max_steps=max_steps, verify_level=verify_level, + should_continue=lambda: not _execution_state.get('should_stop', False), ) logger.info(f"🚀 [Instruction] Démarrage: '{instruction}' (exec_id={exec_id})")