From 599dd0239913531ef750fc2de57170a0b20f0d72 Mon Sep 17 00:00:00 2001 From: Dom Date: Sat, 14 Mar 2026 17:43:49 +0100 Subject: [PATCH] fix(agent-chat): suivi replay distant + timeout 15s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Session ID vide pour auto-détection de la session Agent V1 active - Timeout augmenté de 5s à 15s pour la requête replay - Ajout _poll_replay_progress : suit la progression réelle du replay (polling /replay/{id} toutes les 2s, max 120s) au lieu de marquer faussement "terminé avec succès" immédiatement Co-Authored-By: Claude Opus 4.6 --- agent_chat/app.py | 91 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 12 deletions(-) diff --git a/agent_chat/app.py b/agent_chat/app.py index d793d6818..508d9a541 100644 --- a/agent_chat/app.py +++ b/agent_chat/app.py @@ -994,10 +994,10 @@ def _try_streaming_server_replay(workflow_id: str, params: Dict[str, Any]) -> Op f"{STREAMING_SERVER_URL}/api/v1/traces/stream/replay", json={ "workflow_id": workflow_id, - "session_id": f"chat_{datetime.now().strftime('%H%M%S')}", + "session_id": "", # Vide = auto-détection de la session Agent V1 active "params": params or {}, }, - timeout=5, + timeout=15, ) if resp.status_code == 200: data = resp.json() @@ -1018,6 +1018,64 @@ def _try_streaming_server_replay(workflow_id: str, params: Dict[str, Any]) -> Op return None +def _poll_replay_progress(replay_id: str, workflow_name: str, total_actions: int): + """Suivre la progression d'un replay distant via polling.""" + import time + + max_wait = 120 # 2 minutes max + poll_interval = 2.0 + elapsed = 0 + + while elapsed < max_wait and execution_status.get("running"): + time.sleep(poll_interval) + elapsed += poll_interval + + try: + resp = http_requests.get( + f"{STREAMING_SERVER_URL}/api/v1/traces/stream/replay/{replay_id}", + timeout=3, + ) + if not resp.ok: + continue + + data = resp.json() + status = data.get("status", "unknown") + completed = data.get("completed_actions", 0) + failed = data.get("failed_actions", 0) + progress = int(10 + (completed / max(total_actions, 1)) * 80) + + socketio.emit('execution_progress', { + "progress": progress, + "step": f"Action {completed}/{total_actions} exécutée", + "current": completed, + "total": total_actions, + }) + + if status == "completed": + finish_execution( + workflow_name, failed == 0, + f"Replay terminé : {completed} actions exécutées" + + (f", {failed} échecs" if failed else "") + ) + return + elif status == "failed": + finish_execution( + workflow_name, False, + f"Replay échoué : {completed}/{total_actions} actions, {failed} échecs" + ) + return + + except Exception as e: + logger.debug(f"Poll replay progress: {e}") + + # Timeout + if execution_status.get("running"): + finish_execution( + workflow_name, False, + f"Timeout — replay toujours en cours après {max_wait}s" + ) + + def execute_workflow(match, params): """ Exécuter un workflow — tente d'abord le streaming server, @@ -1031,22 +1089,31 @@ def execute_workflow(match, params): replay_result = _try_streaming_server_replay(match.workflow_id, params) if replay_result: # Le streaming server a accepté le replay + total_actions = replay_result.get("total_actions", 1) + target_session = replay_result.get("session_id", "?") execution_status["running"] = True execution_status["workflow"] = match.workflow_name - execution_status["progress"] = 50 - execution_status["message"] = "Envoyé au streaming server (Agent V1)" + execution_status["progress"] = 10 + execution_status["message"] = f"Envoyé à l'Agent V1 ({target_session})" socketio.emit('execution_progress', { - "progress": 50, - "step": "Exécution via streaming server...", - "current": 1, - "total": 1, + "progress": 10, + "step": f"Replay envoyé à l'Agent V1 — {total_actions} actions en attente", + "current": 0, + "total": total_actions, }) - finish_execution( - match.workflow_name, True, - f"Workflow envoyé au streaming server ({replay_result.get('status', 'ok')})" - ) + # Suivre la progression du replay (polling toutes les 2s, max 120s) + replay_id = replay_result.get("replay_id") + if replay_id: + socketio.start_background_task( + _poll_replay_progress, replay_id, match.workflow_name, total_actions + ) + else: + finish_execution( + match.workflow_name, True, + f"Replay envoyé ({total_actions} actions)" + ) return # Fallback : exécution locale