From 9188bd7df1524a9532c2160faf73c6e9d1cc5a7d Mon Sep 17 00:00:00 2001 From: Dom Date: Fri, 10 Apr 2026 22:18:11 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20masquer=20la=20fen=C3=AAtre=20console=20?= =?UTF-8?q?lors=20du=20spawn=20lea=5Fuia.exe=20sur=20Windows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajoute creationflags=CREATE_NO_WINDOW (0x08000000) au subprocess.run() qui appelle lea_uia.exe dans UIAHelper._run(). Sans ce flag, Windows ouvre brièvement une fenêtre cmd noire à CHAQUE appel — et le captor appelle UIA à chaque clic utilisateur pendant l'enregistrement. Symptômes rapportés par Dom : - Flash de fenêtre terminal à chaque clic (visible à l'œil) - Ralentissement de la souris pendant les enregistrements - Pollution des données d'apprentissage : le VLM de post-analyse "voit" la fenêtre cmd et l'enregistre comme élément cliqué (log serveur : "gemma4 a lu l'élément : 'C:\\Lea\\helpers\\lea_uia.exe'") Implémentation portable : - Flag calculé au niveau module : 0x08000000 sur Windows, 0 sur Linux/Mac - getattr(subprocess, "CREATE_NO_WINDOW", ...) pour gérer l'absence de la constante sur Linux - creationflags=0 est un no-op sur Linux, safe Appliqué aux 2 copies synchronisées : - agent_v0/agent_v1/core/uia_helper.py (source active pour l'agent) - core/workflow/uia_helper.py (copie identique) 85 tests in silico OK (29 UIA + 56 E2E/Phase0). Le vrai test c'est Dom qui refait un enregistrement et vérifie qu'il n'y a plus de flash de terminal. Co-Authored-By: Claude Opus 4.6 (1M context) --- agent_v0/agent_v1/core/uia_helper.py | 16 ++++++++++++++++ core/workflow/uia_helper.py | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/agent_v0/agent_v1/core/uia_helper.py b/agent_v0/agent_v1/core/uia_helper.py index 80061f853..ff63d4c25 100644 --- a/agent_v0/agent_v1/core/uia_helper.py +++ b/agent_v0/agent_v1/core/uia_helper.py @@ -37,6 +37,21 @@ logger = logging.getLogger(__name__) # Timeout par défaut pour les appels UIA (en secondes) _DEFAULT_TIMEOUT = 5.0 +# Masquer la fenêtre console lors du spawn de lea_uia.exe sur Windows. +# Sans ce flag, chaque appel (à chaque clic utilisateur pendant +# l'enregistrement) fait apparaître une fenêtre cmd noire brièvement +# visible à l'écran → ralentit la souris et pollue les screenshots +# capturés (le VLM peut "voir" le chemin lea_uia.exe comme texte cliqué). +# +# La valeur 0x08000000 correspond à CREATE_NO_WINDOW défini dans +# l'API Windows. Sur Linux/Mac, la valeur est 0 et `creationflags` +# est ignoré. getattr() gère le cas où Python expose déjà la constante +# sur Windows. +if platform.system() == "Windows": + _SUBPROCESS_CREATION_FLAGS = getattr(subprocess, "CREATE_NO_WINDOW", 0x08000000) +else: + _SUBPROCESS_CREATION_FLAGS = 0 + @dataclass class UiaElement: @@ -166,6 +181,7 @@ class UIAHelper: timeout=self._timeout, encoding="utf-8", errors="replace", + creationflags=_SUBPROCESS_CREATION_FLAGS, ) if result.returncode != 0: logger.debug( diff --git a/core/workflow/uia_helper.py b/core/workflow/uia_helper.py index 80061f853..ff63d4c25 100644 --- a/core/workflow/uia_helper.py +++ b/core/workflow/uia_helper.py @@ -37,6 +37,21 @@ logger = logging.getLogger(__name__) # Timeout par défaut pour les appels UIA (en secondes) _DEFAULT_TIMEOUT = 5.0 +# Masquer la fenêtre console lors du spawn de lea_uia.exe sur Windows. +# Sans ce flag, chaque appel (à chaque clic utilisateur pendant +# l'enregistrement) fait apparaître une fenêtre cmd noire brièvement +# visible à l'écran → ralentit la souris et pollue les screenshots +# capturés (le VLM peut "voir" le chemin lea_uia.exe comme texte cliqué). +# +# La valeur 0x08000000 correspond à CREATE_NO_WINDOW défini dans +# l'API Windows. Sur Linux/Mac, la valeur est 0 et `creationflags` +# est ignoré. getattr() gère le cas où Python expose déjà la constante +# sur Windows. +if platform.system() == "Windows": + _SUBPROCESS_CREATION_FLAGS = getattr(subprocess, "CREATE_NO_WINDOW", 0x08000000) +else: + _SUBPROCESS_CREATION_FLAGS = 0 + @dataclass class UiaElement: @@ -166,6 +181,7 @@ class UIAHelper: timeout=self._timeout, encoding="utf-8", errors="replace", + creationflags=_SUBPROCESS_CREATION_FLAGS, ) if result.returncode != 0: logger.debug(