fix(ORA): logger.info→print pour que les logs apparaissent dans nohup
Some checks failed
security-audit / Bandit (scan statique) (push) Successful in 12s
security-audit / pip-audit (CVE dépendances) (push) Successful in 12s
security-audit / Scan secrets (grep) (push) Successful in 8s
tests / Lint (ruff + black) (push) Successful in 14s
tests / Tests unitaires (sans GPU) (push) Failing after 15s
tests / Tests sécurité (critique) (push) Has been skipped

Le logging Python ne traverse pas le nohup de Flask. Tous les autres
modules (execute.py, intelligent_executor.py) utilisent print().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dom
2026-04-22 16:16:25 +02:00
parent eba6fea779
commit 4ab2c15e5c

View File

@@ -14,15 +14,6 @@ import logging
import time
import subprocess
import sys
# Forcer les logs ORA dans stdout (visible dans nohup)
logging.basicConfig(level=logging.INFO, stream=sys.stdout,
format='%(message)s', force=False)
if not logging.getLogger(__name__).handlers:
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(logging.Formatter('%(message)s'))
logging.getLogger(__name__).addHandler(handler)
logging.getLogger(__name__).setLevel(logging.INFO)
import base64
import os
import json
@@ -171,7 +162,7 @@ class ORALoop:
window_title = self._get_active_window_title()
ts = time.time()
logger.info(f"👁 [ORA/observe] titre='{window_title}' phash={phash}")
print(f"👁 [ORA/observe] titre='{window_title}' phash={phash}")
return Observation(
screenshot=screenshot,
phash=phash,
@@ -284,7 +275,7 @@ class ORALoop:
expected_after=expected,
confidence=confidence,
)
logger.info(f"🧠 [ORA/reason] {decision.action} target='{decision.target}' value='{decision.value[:50]}'")
print(f"🧠 [ORA/reason] {decision.action} target='{decision.target}' value='{decision.value[:50]}'")
return decision
# ─── Phase 2b : RAISONNE (mode instruction) ─────────
@@ -363,7 +354,7 @@ Règles:
ollama_url = os.environ.get("OLLAMA_URL", "http://localhost:11434")
model = os.environ.get("RPA_REASONING_MODEL", "qwen2.5vl:7b")
logger.info(f"🧠 [ORA/reason_instruction] Appel VLM {model}...")
print(f"🧠 [ORA/reason_instruction] Appel VLM {model}...")
response = requests.post(
f"{ollama_url}/api/generate",
@@ -452,7 +443,7 @@ Règles:
Returns:
LoopResult.
"""
logger.info(f"🚀 [ORA/instruction] Démarrage: '{instruction}' (max {self.max_steps} étapes)")
print(f"🚀 [ORA/instruction] Démarrage: '{instruction}' (max {self.max_steps} étapes)")
# --- Initialiser le contexte cognitif ---
if COGNITIVE_AVAILABLE and CognitiveContext is not None:
@@ -467,8 +458,8 @@ Règles:
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}")
print(f"\n{'='*60}")
print(f"📋 [ORA/instruction] Étape {step_num + 1}/{self.max_steps}")
# --- 1. Observer ---
pre = self.observe()
@@ -478,7 +469,7 @@ Règles:
# --- Objectif atteint ---
if decision.done:
logger.info(f"✅ [ORA/instruction] Objectif atteint en {step_num + 1} étapes: {decision.reasoning}")
print(f"✅ [ORA/instruction] Objectif atteint en {step_num + 1} étapes: {decision.reasoning}")
if self.ctx:
self.ctx.record_action('done', decision.target, result='Objectif atteint', success=True)
return LoopResult(
@@ -555,7 +546,7 @@ Règles:
if not verification.success:
retried = False
for retry in range(self.max_retries):
logger.info(f"🔄 [ORA/instruction] Retry {retry + 1}/{self.max_retries}")
print(f"🔄 [ORA/instruction] Retry {retry + 1}/{self.max_retries}")
pre_retry = self.observe()
self.act(decision)
time.sleep(0.3)
@@ -563,7 +554,7 @@ Règles:
verification = self.verify(pre_retry, post_retry, decision)
if verification.success:
retried = True
logger.info(f"✅ [ORA/instruction] Retry {retry + 1} réussi")
print(f"✅ [ORA/instruction] Retry {retry + 1} réussi")
if self.ctx:
self.ctx.record_action(
decision.action, decision.target,
@@ -615,7 +606,7 @@ Règles:
if step_params is None:
step_params = {}
logger.info(f"🎯 [ORA/act] {decision.action} target='{decision.target}' value='{decision.value[:50]}'")
print(f"🎯 [ORA/act] {decision.action} target='{decision.target}' value='{decision.value[:50]}'")
try:
if decision.action == 'click':
@@ -686,7 +677,7 @@ Règles:
distance = self._phash_distance(pre.phash, post.phash)
change_level = self._classify_change(distance)
logger.info(f"🔍 [ORA/verify] pHash distance={distance}{change_level}")
print(f"🔍 [ORA/verify] pHash distance={distance}{change_level}")
# Déterminer le succès selon le niveau de changement
if change_level == 'same':
@@ -720,10 +711,10 @@ Règles:
detail += f" | VLM: matches={matches_expected}, état='{actual_state[:80]}'"
# Le VLM a le dernier mot
success = matches_expected
logger.info(f"🔍 [ORA/verify/VLM] matches={matches_expected} état='{actual_state[:60]}'")
print(f"🔍 [ORA/verify/VLM] matches={matches_expected} état='{actual_state[:60]}'")
emoji = "" if success else ""
logger.info(f"{emoji} [ORA/verify] success={success} level={change_level}{detail[:100]}")
print(f"{emoji} [ORA/verify] success={success} level={change_level}{detail[:100]}")
return VerificationResult(
success=success,
@@ -762,15 +753,15 @@ Règles:
reason=f"Trop d'étapes ({total} > max {self.max_steps})"
)
logger.info(f"🚀 [ORA] Démarrage workflow: {total} étapes, verify={self.verify_level}, retries={self.max_retries}")
print(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', '')}")
print(f"\n{'='*60}")
print(f"📋 [ORA] Étape {i+1}/{total}: {step.get('action_type', '?')}{step.get('label', '')}")
# --- 1. Observer l'état pré-action ---
pre = self.observe()
@@ -820,7 +811,7 @@ Règles:
# Réessayer
retried = False
for retry in range(self.max_retries):
logger.info(f"🔄 [ORA] Retry {retry+1}/{self.max_retries} pour étape {i+1}")
print(f"🔄 [ORA] Retry {retry+1}/{self.max_retries} pour étape {i+1}")
pre_retry = self.observe()
act_success = self.act(decision, step)
time.sleep(0.3)
@@ -828,7 +819,7 @@ Règles:
verification = self.verify(pre_retry, post_retry, decision)
if verification.success:
retried = True
logger.info(f"✅ [ORA] Retry {retry+1} réussi")
print(f"✅ [ORA] Retry {retry+1} réussi")
break
if not retried and not verification.success:
logger.warning(f"❌ [ORA] Étape {i+1} échouée après {self.max_retries} retries")
@@ -841,7 +832,7 @@ Règles:
if on_progress:
on_progress(i + 1, total, verification)
logger.info(f"✅ [ORA] Workflow terminé avec succès: {total}/{total} étapes")
print(f"✅ [ORA] Workflow terminé avec succès: {total}/{total} étapes")
return LoopResult(success=True, steps_completed=total, total_steps=total)
# ═══════════════════════════════════════════════════════════
@@ -872,12 +863,12 @@ Règles:
try:
from core.execution.input_handler import _grounding_ui_tars
click_label = target_desc or target_text
logger.info(f"🎯 [ORA/UI-TARS] Recherche: '{click_label}'")
print(f"🎯 [ORA/UI-TARS] Recherche: '{click_label}'")
result = _grounding_ui_tars(target_text, target_desc)
if result:
x, y = result['x'], result['y']
method_used = 'ui_tars'
logger.info(f"✅ [ORA/UI-TARS] Trouvé à ({x}, {y})")
print(f"✅ [ORA/UI-TARS] Trouvé à ({x}, {y})")
except Exception as e:
logger.debug(f"⚠️ [ORA/UI-TARS] Erreur: {e}")
@@ -902,7 +893,7 @@ Règles:
result_tm = cv2.matchTemplate(screen_cv, anchor_cv, cv2.TM_CCOEFF_NORMED)
_, max_val, _, max_loc = cv2.minMaxLoc(result_tm)
elapsed_ms = (time.time() - t0) * 1000
logger.info(f"⚡ [ORA/template] score={max_val:.3f} pos={max_loc} ({elapsed_ms:.0f}ms)")
print(f"⚡ [ORA/template] score={max_val:.3f} pos={max_loc} ({elapsed_ms:.0f}ms)")
if max_val > 0.75:
x = max_loc[0] + anchor_cv.shape[1] // 2
y = max_loc[1] + anchor_cv.shape[0] // 2
@@ -918,7 +909,7 @@ Règles:
if result:
x, y = result['x'], result['y']
method_used = 'ocr'
logger.info(f"🔍 [ORA/OCR] Trouvé à ({x}, {y})")
print(f"🔍 [ORA/OCR] Trouvé à ({x}, {y})")
except Exception as e:
logger.debug(f"⚠️ [ORA/OCR] Erreur: {e}")
@@ -934,7 +925,7 @@ Règles:
logger.error(f"❌ [ORA/click] Impossible de localiser '{target_text}' — aucune méthode n'a fonctionné")
return False
logger.info(f"🖱️ [ORA/click] {decision.value} à ({x}, {y}) via {method_used}")
print(f"🖱️ [ORA/click] {decision.value} à ({x}, {y}) via {method_used}")
if decision.value == 'double':
pyautogui.doubleClick(x, y)
@@ -999,7 +990,7 @@ Règles:
# Raccourci clavier normal
keys = value.split('+')
logger.info(f"⌨️ [ORA/hotkey] {'+'.join(keys)}")
print(f"⌨️ [ORA/hotkey] {'+'.join(keys)}")
pyautogui.hotkey(*keys)
return True
@@ -1010,7 +1001,7 @@ Règles:
except (ValueError, TypeError):
timeout_ms = 5000
logger.info(f"⏳ [ORA/wait] {timeout_ms}ms")
print(f"⏳ [ORA/wait] {timeout_ms}ms")
time.sleep(timeout_ms / 1000)
return True
@@ -1036,7 +1027,7 @@ Règles:
amount = int(nums[0])
scroll_value = amount if direction in ('up', 'left') else -amount
logger.info(f"📜 [ORA/scroll] {direction} x{amount}")
print(f"📜 [ORA/scroll] {direction} x{amount}")
if direction in ('left', 'right'):
pyautogui.hscroll(scroll_value)