| 1 | import { |
| 2 | isActiveSubagentStatus, |
| 3 | isTerminalSubagentStatus, |
| 4 | type RuntimeSubagent, |
| 5 | } from "@t3tools/client-runtime/state/subagentRuntime"; |
| 6 | |
| 7 | /** Summarize observed states without treating idle or missing agents as completed. */ |
| 8 | export function deriveAgentSpawnSummary({ |
| 9 | agents, |
| 10 | agentCount, |
| 11 | coordinatorStatus, |
| 12 | }: { |
| 13 | agents: ReadonlyArray<Pick<RuntimeSubagent, "kind" | "status">>; |
| 14 | agentCount: number; |
| 15 | coordinatorStatus?: RuntimeSubagent["status"] | undefined; |
| 16 | }) { |
| 17 | const working = agents.filter((agent) => isActiveSubagentStatus(agent.status)).length; |
| 18 | const failed = agents.filter((agent) => agent.status === "failed").length; |
| 19 | const idle = agents.filter((agent) => agent.status === "idle").length; |
| 20 | const stopped = agents.filter( |
| 21 | (agent) => agent.status === "cancelled" || agent.status === "interrupted", |
| 22 | ).length; |
| 23 | const batches = agents.filter((agent) => agent.kind === "subagent_batch").length; |
| 24 | const individuals = agentCount - batches; |
| 25 | // Workflow coordinators can keep running between dynamic member launches. |
| 26 | const live = |
| 27 | coordinatorStatus !== undefined ? !isTerminalSubagentStatus(coordinatorStatus) : working > 0; |
| 28 | const subjects = [ |
| 29 | individuals > 0 ? `${individuals} subagent${individuals === 1 ? "" : "s"}` : null, |
| 30 | batches > 0 |
| 31 | ? `${batches} ${individuals > 0 ? "" : "subagent "}batch${batches === 1 ? "" : "es"}` |
| 32 | : null, |
| 33 | ] |
| 34 | .filter(Boolean) |
| 35 | .join(" and "); |
| 36 | const lead = `${batches > 0 ? "Launched" : live ? "Kicked off" : "Ran"} ${subjects || "subagents"}`; |
| 37 | |
| 38 | const status = live |
| 39 | ? working > 0 |
| 40 | ? `${working} working` |
| 41 | : "working" |
| 42 | : coordinatorStatus === "failed" |
| 43 | ? "Workflow failed" |
| 44 | : coordinatorStatus === "cancelled" || coordinatorStatus === "interrupted" |
| 45 | ? "Workflow stopped" |
| 46 | : failed > 0 |
| 47 | ? `${failed} failed` |
| 48 | : stopped > 0 |
| 49 | ? `${stopped} stopped` |
| 50 | : idle > 0 |
| 51 | ? `${idle} idle` |
| 52 | : coordinatorStatus !== "completed" && |
| 53 | (agents.length === 0 || agents.length < agentCount) |
| 54 | ? "Status unavailable" |
| 55 | : "✓ completed"; |
| 56 | const tone = live |
| 57 | ? "working" |
| 58 | : failed > 0 || coordinatorStatus === "failed" |
| 59 | ? "failed" |
| 60 | : status === "✓ completed" |
| 61 | ? "completed" |
| 62 | : "inactive"; |
| 63 | return { live, lead, status, tone }; |
| 64 | } |