187 lines
5.6 KiB
TypeScript
187 lines
5.6 KiB
TypeScript
import { describe, expect, test } from "bun:test"
|
|
import { foregroundSubagentCount, subagentDisplayState } from "../../src/util/subagent"
|
|
|
|
describe("foregroundSubagentCount", () => {
|
|
test("counts running subagent timeline rows before child session output is available", () => {
|
|
expect(
|
|
foregroundSubagentCount({
|
|
sessionID: "parent",
|
|
sessions: [],
|
|
messages: [
|
|
{
|
|
type: "assistant",
|
|
content: [
|
|
{ type: "tool", name: "subagent", state: { status: "running", structured: {} } },
|
|
{ type: "tool", name: "task", state: { status: "running", structured: {} } },
|
|
],
|
|
},
|
|
],
|
|
status: () => "idle",
|
|
}),
|
|
).toBe(2)
|
|
})
|
|
|
|
test("does not double-count running rows that match known child sessions", () => {
|
|
expect(
|
|
foregroundSubagentCount({
|
|
sessionID: "parent",
|
|
sessions: [{ id: "child-1", parentID: "parent", title: "Audit slow path" }],
|
|
messages: [
|
|
{
|
|
type: "assistant",
|
|
content: [
|
|
{
|
|
type: "tool",
|
|
name: "subagent",
|
|
state: { status: "running", input: { description: "Audit slow path" }, structured: {} },
|
|
},
|
|
],
|
|
},
|
|
],
|
|
status: () => "running",
|
|
}),
|
|
).toBe(1)
|
|
})
|
|
|
|
test("counts mixed timeline-only and session-only foreground subagents", () => {
|
|
expect(
|
|
foregroundSubagentCount({
|
|
sessionID: "parent",
|
|
sessions: [{ id: "child-1", parentID: "parent", title: "Known child" }],
|
|
messages: [
|
|
{
|
|
type: "assistant",
|
|
content: [
|
|
{
|
|
type: "tool",
|
|
name: "subagent",
|
|
state: { status: "running", input: { description: "New child" }, structured: {} },
|
|
},
|
|
],
|
|
},
|
|
],
|
|
status: () => "running",
|
|
}),
|
|
).toBe(2)
|
|
})
|
|
|
|
test("does not undercount duplicate descriptions when only one child session is synced", () => {
|
|
expect(
|
|
foregroundSubagentCount({
|
|
sessionID: "parent",
|
|
sessions: [{ id: "child-1", parentID: "parent", title: "Same task" }],
|
|
messages: [
|
|
{
|
|
type: "assistant",
|
|
content: [
|
|
{
|
|
type: "tool",
|
|
name: "subagent",
|
|
state: { status: "running", input: { description: "Same task" }, structured: {} },
|
|
},
|
|
{
|
|
type: "tool",
|
|
name: "subagent",
|
|
state: { status: "running", input: { description: "Same task" }, structured: {} },
|
|
},
|
|
],
|
|
},
|
|
],
|
|
status: () => "running",
|
|
}),
|
|
).toBe(2)
|
|
})
|
|
|
|
test("counts running child sessions", () => {
|
|
expect(
|
|
foregroundSubagentCount({
|
|
sessionID: "parent",
|
|
sessions: [
|
|
{ id: "child-1", parentID: "parent" },
|
|
{ id: "child-2", parentID: "parent" },
|
|
{ id: "child-3", parentID: "other" },
|
|
],
|
|
messages: [],
|
|
status: (sessionID) => (sessionID === "child-1" || sessionID === "child-3" ? "running" : "idle"),
|
|
}),
|
|
).toBe(1)
|
|
})
|
|
|
|
test("excludes running subagents already marked as backgrounded in the timeline", () => {
|
|
expect(
|
|
foregroundSubagentCount({
|
|
sessionID: "parent",
|
|
sessions: [
|
|
{ id: "child-1", parentID: "parent" },
|
|
{ id: "child-2", parentID: "parent" },
|
|
],
|
|
messages: [
|
|
{
|
|
type: "assistant",
|
|
content: [
|
|
{
|
|
type: "tool",
|
|
name: "subagent",
|
|
state: {
|
|
status: "completed",
|
|
structured: { sessionID: "child-1", background: true },
|
|
},
|
|
},
|
|
{
|
|
type: "tool",
|
|
name: "task",
|
|
state: {
|
|
status: "completed",
|
|
structured: { sessionId: "child-2", background: false },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
],
|
|
status: () => "running",
|
|
}),
|
|
).toBe(1)
|
|
})
|
|
})
|
|
|
|
describe("subagentDisplayState", () => {
|
|
test("keeps a backgrounded subagent spinning while the child session is running", () => {
|
|
expect(
|
|
subagentDisplayState({
|
|
toolStatus: "completed",
|
|
metadata: { sessionID: "child", status: "running", background: true },
|
|
sessionStatus: () => "running",
|
|
}),
|
|
).toEqual({ background: true, running: true, icon: "│" })
|
|
})
|
|
|
|
test("shows a checkmark once a backgrounded child session is no longer running", () => {
|
|
expect(
|
|
subagentDisplayState({
|
|
toolStatus: "completed",
|
|
metadata: { sessionID: "child", status: "running", background: true },
|
|
sessionStatus: () => "idle",
|
|
}),
|
|
).toEqual({ background: true, running: false, icon: "✓" })
|
|
})
|
|
|
|
test("does not spin forever from stale background metadata without a child session ID", () => {
|
|
expect(
|
|
subagentDisplayState({
|
|
toolStatus: "completed",
|
|
metadata: { status: "running", background: true },
|
|
sessionStatus: () => "idle",
|
|
}),
|
|
).toEqual({ background: true, running: false, icon: "✓" })
|
|
})
|
|
|
|
test("does not show a checkmark for errored subagent rows", () => {
|
|
expect(
|
|
subagentDisplayState({
|
|
toolStatus: "error",
|
|
metadata: { background: true },
|
|
sessionStatus: () => "idle",
|
|
}),
|
|
).toEqual({ background: true, running: false, icon: "│" })
|
|
})
|
|
})
|