1import { describe, expect, it } from "vite-plus/test";
2import type { RuntimeSubagent } from "@t3tools/client-runtime/state/subagentRuntime";
3import { deriveAgentSpawnSummary } from "./agentSpawnSummary";
4
5const batch = (status: RuntimeSubagent["status"]) => ({ kind: "subagent_batch" as const, status });
6const agent = (status: RuntimeSubagent["status"]) => ({ kind: "subagent" as const, status });
7
8describe("deriveAgentSpawnSummary", () => {
9 it("counts a native batch without claiming the number of children", () => {
10 expect(deriveAgentSpawnSummary({ agents: [batch("running")], agentCount: 1 })).toEqual({
11 live: true,
12 lead: "Launched 1 subagent batch",
13 status: "1 working",
14 tone: "working",
15 });
16 expect(deriveAgentSpawnSummary({ agents: [batch("idle")], agentCount: 1 })).toEqual({
17 live: false,
18 lead: "Launched 1 subagent batch",
19 status: "1 idle",
20 tone: "inactive",
21 });
22 });
23
24 it("keeps individual agents and batches separate in a mixed group", () => {
25 expect(
26 deriveAgentSpawnSummary({
27 agents: [agent("running"), batch("running"), batch("idle")],
28 agentCount: 3,
29 }).lead,
30 ).toBe("Launched 1 subagent and 2 batches");
31 });
32
33 it.each([
34 ["idle", "1 idle", "inactive"],
35 ["cancelled", "1 stopped", "inactive"],
36 ["interrupted", "1 stopped", "inactive"],
37 ["failed", "1 failed", "failed"],
38 ["completed", "✓ completed", "completed"],
39 ] as const)("reports %s accurately alongside a completed agent", (state, status, tone) => {
40 expect(
41 deriveAgentSpawnSummary({ agents: [agent("completed"), agent(state)], agentCount: 2 }),
42 ).toMatchObject({ live: false, status, tone });
43 });
44
45 it("does not claim completion when the roster is missing a member", () => {
46 expect(deriveAgentSpawnSummary({ agents: [agent("completed")], agentCount: 2 })).toMatchObject({
47 status: "Status unavailable",
48 tone: "inactive",
49 });
50 });
51
52 it("keeps a workflow active between child launches", () => {
53 expect(
54 deriveAgentSpawnSummary({
55 agents: [agent("completed")],
56 agentCount: 1,
57 coordinatorStatus: "running",
58 }),
59 ).toMatchObject({ live: true, status: "working", tone: "working" });
60 });
61
62 it.each([
63 ["failed", "Workflow failed", "failed"],
64 ["cancelled", "Workflow stopped", "inactive"],
65 ] as const)(
66 "preserves a %s workflow outcome when its children completed",
67 (coordinatorStatus, status, tone) => {
68 expect(
69 deriveAgentSpawnSummary({ agents: [agent("completed")], agentCount: 1, coordinatorStatus }),
70 ).toMatchObject({ live: false, status, tone });
71 },
72 );
73});