From b0aca073efc09623300b1fe4e67879d34c963786 Mon Sep 17 00:00:00 2001 From: Jonas Pacheco Date: Fri, 27 Mar 2026 16:56:29 -0300 Subject: [PATCH] feat(assemble): add task progress panel to Assemble Line Each agent row in the Assemble Line now has an expandable panel showing live Blackboard subtask progress (status icons, agent roles) when a task is running. statusColor/statusLabel moved to module scope. Co-Authored-By: Claude Sonnet 4.6 --- client/src/pages/DevCenter.tsx | 170 ++++++++++++++++++++++----------- 1 file changed, 113 insertions(+), 57 deletions(-) diff --git a/client/src/pages/DevCenter.tsx b/client/src/pages/DevCenter.tsx index c8ef688..76f96e8 100644 --- a/client/src/pages/DevCenter.tsx +++ b/client/src/pages/DevCenter.tsx @@ -89,6 +89,111 @@ type AgentDef = { updatedAt: string; }; +const statusColor: Record = { + draft: "bg-zinc-500", + assembling: "bg-blue-500", + ready: "bg-green-500", + deployed: "bg-purple-500", +}; + +const statusLabel: Record = { + draft: "Rascunho", + assembling: "Montando...", + ready: "Pronto", + deployed: "Implantado", +}; + +// ── AssembleRow: linha da Assemble Line com painel de progresso da task ────── + +function AssembleRow({ def, taskStatus, onAssemble, assembling }: { + def: AgentDef; + taskStatus?: string; + onAssemble: () => void; + assembling: boolean; +}) { + const [expanded, setExpanded] = useState(false); + + const { data: taskData } = useQuery<{ success: boolean; task: any; subtasks: any[]; logs: any[] }>({ + queryKey: [`/api/blackboard/task/${def.lastTaskId}`], + enabled: !!def.lastTaskId && def.status === "assembling" && expanded, + refetchInterval: 3000, + }); + + const subtasks: any[] = taskData?.subtasks ?? []; + + return ( +
+
+
+
+ {def.name} + + {statusLabel[def.status]} + + {def.status === "assembling" && ( + + )} +
+ {def.description &&

{def.description}

} + {def.lastTaskId && ( + + )} +
+
+ {def.status === "draft" && ( + + )} + {def.status === "assembling" && def.lastTaskId && ( + + )} +
+
+ + {/* Painel de progresso */} + {expanded && def.lastTaskId && ( +
+ {subtasks.length === 0 ? ( +

+ Aguardando subtasks... +

+ ) : ( +
+ {subtasks.map((st: any) => ( +
+ {st.status === "completed" ? ( + + ) : st.status === "failed" ? ( + + ) : st.status === "in_progress" ? ( + + ) : ( + + )} + + {st.title || st.description?.slice(0, 60) || `Subtask #${st.id}`} + + {st.agentRole ?? ""} +
+ ))} +
+ )} +
+ )} +
+ ); +} + function AgentFactoryTabs() { const { toast } = useToast(); const queryClient = useQueryClient(); @@ -271,20 +376,6 @@ function AgentFactoryTabs() { setIsCreatingNew(true); }; - const statusColor: Record = { - draft: "bg-zinc-500", - assembling: "bg-blue-500", - ready: "bg-green-500", - deployed: "bg-purple-500", - }; - - const statusLabel: Record = { - draft: "Rascunho", - assembling: "Montando...", - ready: "Pronto", - deployed: "Implantado", - }; - const galDefs = defs.filter(d => d.status === "deployed" && (d.name.toLowerCase().includes(galFilter.toLowerCase()) || @@ -474,52 +565,17 @@ function AgentFactoryTabs() {

Crie agentes na aba Design e monte-os aqui.

) : ( -
+
{defs.filter(d => d.status === "draft" || d.status === "assembling").map(def => { const taskStatus = assembleTaskStatus[def.id]; return ( -
-
-
- {def.name} - - {statusLabel[def.status]} - - {def.status === "assembling" && ( - - )} -
- {def.description &&

{def.description}

} - {def.lastTaskId && ( -

- Task #{def.lastTaskId} - {taskStatus && ` — ${taskStatus}`} -

- )} -
-
- {def.status === "draft" && ( - - )} - {def.status === "assembling" && ( - - Processando... - - )} -
-
+ assembleMutation.mutate(def.id)} + assembling={assembleMutation.isPending} + /> ); })}