From ded0e997ed55b81ff01413b71c56c073751b9575 Mon Sep 17 00:00:00 2001 From: Jordan Diaz Date: Fri, 3 Apr 2026 23:32:45 +0000 Subject: [PATCH] Emitir plan como bloque tool_use visible en el frontend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit El plan del planner se emite como tool_use(name="plan") + tool_result con los steps formateados. El frontend lo renderiza como un bloque colapsable de herramienta con el plan de ejecución. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/orchestrator/engine.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/orchestrator/engine.py b/src/orchestrator/engine.py index 9018808..c9e97aa 100644 --- a/src/orchestrator/engine.py +++ b/src/orchestrator/engine.py @@ -201,6 +201,33 @@ class OrchestratorEngine: task.task_id, ) + # Emit plan to frontend as a visible block + plan_tool_id = f"plan_{task.task_id}" + plan_steps_list = [ + {"step": i + 1, "agent": s.agent_role, "description": s.description} + for i, s in enumerate(plan_result) + ] + await self.sse.emit( + EventType.TOOL_STARTED, + {"tool": "plan", "step": 0, "tool_call_id": plan_tool_id}, + session_id=session.session_id, + ) + plan_text = "\n".join( + f" {s['step']}. [{s['agent']}] {s['description']}" + for s in plan_steps_list + ) + await self.sse.emit( + EventType.TOOL_COMPLETED, + { + "tool": "plan", + "status": "completed", + "summary": f"Plan: {len(plan_result)} steps", + "raw_output": f"Plan de ejecución ({len(plan_result)} pasos):\n{plan_text}", + "tool_call_id": plan_tool_id, + }, + session_id=session.session_id, + ) + # 3. Execute each step — failures are logged and skipped results: list[dict[str, Any]] = [] failed_steps: list[int] = []