229 lines · 6.7 KB · TypeScript
RawDownload
import { describe, expect, it } from "vite-plus/test";import * as ThreadBackgroundLiveness from "./ThreadBackgroundLiveness.ts"; describe("ThreadBackgroundLiveness", () => {  it("does not let status-free progress or metadata restart an idle task", () => {    const liveness = ThreadBackgroundLiveness.make();    liveness.recordTaskLiveness({      threadId: "thread",      taskId: "task",      taskType: undefined,      status: undefined,      kind: "started",    });    liveness.recordTaskLiveness({      threadId: "thread",      taskId: "task",      taskType: undefined,      status: "idle",      kind: "updated",    });    liveness.recordTaskLiveness({      threadId: "thread",      taskId: "task",      taskType: undefined,      status: undefined,      kind: "progress",    });    liveness.recordTaskLiveness({      threadId: "thread",      taskId: "task",      taskType: undefined,      status: undefined,      kind: "updated",    });    expect(liveness.getThreadBackgroundLiveness("thread")).toBeNull();     liveness.recordTaskLiveness({      threadId: "thread",      taskId: "completed-task",      taskType: undefined,      status: undefined,      kind: "started",    });    liveness.recordTaskLiveness({      threadId: "thread",      taskId: "completed-task",      taskType: undefined,      status: "completed",      kind: "completed",    });    liveness.recordTaskLiveness({      threadId: "thread",      taskId: "completed-task",      taskType: undefined,      status: undefined,      kind: "updated",    });    expect(liveness.getThreadBackgroundLiveness("thread")).toBeNull();  });   it("agents present as working; monitors as monitoring; agents win", () => {    const liveness = ThreadBackgroundLiveness.make();    const threadId = "t-live-1";    liveness.recordTaskLiveness({      threadId,      taskId: "m1",      taskType: "local_bash",      status: undefined,      kind: "started",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBe("monitoring");    liveness.recordTaskLiveness({      threadId,      taskId: "a1",      taskType: "subagent",      status: undefined,      kind: "started",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBe("working");    liveness.recordTaskLiveness({      threadId,      taskId: "a1",      taskType: "subagent",      status: "completed",      kind: "completed",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBe("monitoring");    liveness.recordTaskLiveness({      threadId,      taskId: "m1",      taskType: "local_bash",      status: "completed",      kind: "completed",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBeNull();  });   it("terminal rows without a taskType still clear monitor entries", () => {    const liveness = ThreadBackgroundLiveness.make();    const threadId = "t-live-2";    liveness.recordTaskLiveness({      threadId,      taskId: "m1",      taskType: "local_bash",      status: undefined,      kind: "started",    });    // Terminal tick arrives with no taskType (common on task.completed).    liveness.recordTaskLiveness({      threadId,      taskId: "m1",      taskType: undefined,      status: "completed",      kind: "completed",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBeNull();  });   it("nested agents (agentId + agent taskType) still count toward liveness", () => {    const liveness = ThreadBackgroundLiveness.make();    const threadId = "t-live-nested";    liveness.recordTaskLiveness({      threadId,      taskId: "n1",      taskType: "local_agent",      status: undefined,      kind: "started",      agentId: "owner",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBe("working");    liveness.recordTaskLiveness({      threadId,      taskId: "n1",      taskType: "local_agent",      status: "completed",      kind: "completed",      agentId: "owner",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBeNull();  });   it("untyped rows count as agents; idle is not live; agent-owned tasks are ignored", () => {    const liveness = ThreadBackgroundLiveness.make();    const threadId = "t-live-3";    liveness.recordTaskLiveness({      threadId,      taskId: "wf:1",      taskType: undefined,      status: "running",      kind: "progress",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBe("working");    liveness.recordTaskLiveness({      threadId,      taskId: "wf:1",      taskType: undefined,      status: "idle",      kind: "updated",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBeNull();    liveness.recordTaskLiveness({      threadId,      taskId: "sh:1",      taskType: "local_bash",      status: undefined,      kind: "started",      agentId: "owner",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBeNull();  });   it("reclassification moves a task between buckets instead of duplicating it", () => {    const liveness = ThreadBackgroundLiveness.make();    const threadId = "t-live-reclass";    // First seen without a taskType: counts as an agent.    liveness.recordTaskLiveness({      threadId,      taskId: "x1",      taskType: undefined,      status: "running",      kind: "started",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBe("working");    // Later transition reveals it's a shell: downgrade to monitoring, not    // a stale duplicate pinning "working".    liveness.recordTaskLiveness({      threadId,      taskId: "x1",      taskType: "local_bash",      status: "running",      kind: "progress",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBe("monitoring");    // Turning out to be inert or agent-owned drops the prior entry too.    liveness.recordTaskLiveness({      threadId,      taskId: "x1",      taskType: "local_bash",      status: "running",      kind: "progress",      agentId: "owner",    });    expect(liveness.getThreadBackgroundLiveness(threadId)).toBeNull();  });   it("plan tasks are inert; clear removes everything; instances are isolated", () => {    const a = ThreadBackgroundLiveness.make();    const b = ThreadBackgroundLiveness.make();    a.recordTaskLiveness({      threadId: "t",      taskId: "p1",      taskType: "plan",      status: undefined,      kind: "started",    });    expect(a.getThreadBackgroundLiveness("t")).toBeNull();    a.recordTaskLiveness({      threadId: "t",      taskId: "a1",      taskType: "local_workflow",      status: undefined,      kind: "started",    });    expect(a.getThreadBackgroundLiveness("t")).toBe("working");    expect(b.getThreadBackgroundLiveness("t")).toBeNull();    a.clearThreadLiveness("t");    expect(a.getThreadBackgroundLiveness("t")).toBeNull();  });});