diff --git a/packages/server/src/server/agent/agent-run-state.test.ts b/packages/server/src/server/agent/agent-run-state.test.ts new file mode 100644 index 0000000000..29e09a5f94 --- /dev/null +++ b/packages/server/src/server/agent/agent-run-state.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, test } from "vitest"; + +import { AgentRunState } from "./agent-run-state.js"; + +function track(promise: Promise): { readonly resolved: boolean } { + const state = { resolved: false }; + void (async () => { + await promise; + state.resolved = true; + })(); + return state; +} + +async function flushMicrotasks(): Promise { + await new Promise((resolve) => setImmediate(resolve)); +} + +describe("waitForForegroundStart", () => { + test("resolves once the starting turn has an id", async () => { + const runs = new AgentRunState(); + const run = runs.createPendingRun("agent"); + const wait = track(runs.waitForForegroundStart("agent")); + + await flushMicrotasks(); + expect(wait.resolved).toBe(false); + + runs.settleForegroundStart(run, { status: "started", turnId: "turn-1" }); + await flushMicrotasks(); + expect(wait.resolved).toBe(true); + }); + + test("waits for a failed start's run to be cleared", async () => { + const runs = new AgentRunState(); + const run = runs.createPendingRun("agent"); + const wait = track(runs.waitForForegroundStart("agent")); + + runs.settleForegroundStart(run, { status: "failed", error: "start failed" }); + await flushMicrotasks(); + expect(wait.resolved).toBe(false); + expect(runs.hasPendingRun("agent")).toBe(true); + + runs.settleForegroundRun("agent", run.token); + await flushMicrotasks(); + expect(wait.resolved).toBe(true); + }); + + test("resolves at once when no turn is starting", async () => { + const runs = new AgentRunState(); + await expect(runs.waitForForegroundStart("agent")).resolves.toBeUndefined(); + }); +});