import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { configureAzureSession, extract, modelVerification, } from "../server/model"; import { modelLoad, retryAfterMs } from "../server/model-runtime"; import { parseCompactDraft } from "../server/compact"; import { groundedFact } from "../server/guards"; const source = [ { id: "load", title: "Synthetic load note", kind: "Synthetic", date: "2026-10-23", text: "Patient: Nora Test\nShe takes Metformin 500 mg twice daily.", }, ]; const good = () => new Response( JSON.stringify({ choices: [ { finish_reason: "stop", message: { content: JSON.stringify({ facts: [ [ 2, "Medication: Metformin; strength: 500 mg; frequency: 2/day", ], ], }), }, }, ], }), { status: 200 }, ); function configure() { configureAzureSession({ endpoint: "https://synthetic.services.ai.azure.com/openai/v1/chat/completions", key: "synthetic", model: "test", auth: "api-key", }); } beforeEach(configure); afterEach(() => { vi.unstubAllGlobals(); vi.restoreAllMocks(); }); describe("bounded provider work", () => { it("admits four calls, rejects overflow promptly, and releases capacity", async () => { const finish: Array<(r: Response) => void> = []; vi.stubGlobal( "fetch", vi.fn(() => new Promise((resolve) => finish.push(resolve))), ); const admitted = Array.from({ length: 4 }, () => extract(source, true, true), ); expect(modelLoad().active).toBe(4); const rejected = await Promise.allSettled( Array.from({ length: 8 }, () => extract(source, true, true)), ); expect( rejected.every( (r) => r.status === "rejected" && /slots are busy/.test(r.reason.message), ), ).toBe(true); for (const resolve of finish) resolve(good()); await Promise.all(admitted); expect(modelLoad().active).toBe(0); }); it("aborts provider work and permits a later successful retry", async () => { const fetcher = vi.fn( (_url, options) => new Promise((_r, reject) => options.signal.addEventListener( "abort", () => reject(new Error("private abort")), { once: true }, ), ), ); vi.stubGlobal("fetch", fetcher); const controller = new AbortController(); const pending = extract(source, true, true, controller.signal); controller.abort(); await expect(pending).rejects.toThrow("cancelled"); expect(fetcher).toHaveBeenCalledTimes(1); expect(modelLoad().active).toBe(0); vi.stubGlobal( "fetch", vi.fn(async () => good()), ); expect((await extract(source, true)).strategy).toBe("narrative"); }); it("does not publish or cache an in-flight result after reconfiguration", async () => { let finish!: (r: Response) => void; vi.stubGlobal( "fetch", vi.fn( () => new Promise((r) => { finish = r; }), ), ); const pending = extract(source, true, true); configure(); finish(good()); await expect(pending).rejects.toThrow("cancelled"); expect(modelVerification()).toBeNull(); expect(modelLoad().active).toBe(0); }); it("honors HTTP-date Retry-After and prevents a subsequent retry storm", async () => { const date = new Date(Date.now() + 60_000).toUTCString(); const fetcher = vi.fn( async () => new Response("", { status: 429, headers: { "Retry-After": date } }), ); vi.stubGlobal("fetch", fetcher); await expect(extract(source, true, true)).rejects.toThrow("busy"); await expect(extract(source, true, true)).rejects.toThrow("rate limited"); expect(fetcher).toHaveBeenCalledTimes(1); expect(modelLoad().active).toBe(0); }); it.each([null, [], {}, "invalid"])( "rejects invalid provider envelope %j with a safe message", async (body) => { vi.stubGlobal( "fetch", vi.fn(async () => new Response(JSON.stringify(body))), ); await expect(extract(source, true, true)).rejects.toThrow( "invalid response", ); expect(modelLoad().active).toBe(0); }, ); it("handles numeric, date and invalid retry delay formats", () => { expect(retryAfterMs("2")).toBe(2000); expect(retryAfterMs("garbage")).toBe(0); expect(retryAfterMs(new Date(60000).toUTCString(), 0)).toBe(60000); }); }); describe("expanded messy source boundaries", () => { it.each([ ["She has a Penicillin allergy.", "Allergies: Penicillin"], [ "Her eGFR was 38 mL/min/1.73m2 on 2026-10-12.", "Lab: eGFR; value: 38; unit: mL/min/1.73m2; date: 2026-10-12", ], ])( "withholds ambiguous pronouns after a relative on a previous line: %s", (quote, normalized) => { const sources = [ { ...source[0], text: "Patient: Nora Test\nHer sister came yesterday.\n" + quote, }, ]; const d = parseCompactDraft( { facts: [[3, normalized]] }, sources, "test", 0, ); expect(d.facts.at(-1)?.problem).toContain("subject"); }, ); it("retains an explicitly named patient after a relative", () => { const sources = [ { ...source[0], text: "Patient: Nora Test\nHer sister has a Penicillin allergy.\nNora has no known drug allergies.", }, ]; expect( parseCompactDraft( { facts: [[3, "Allergies: No known allergies"]] }, sources, "test", 0, ).facts.at(-1)?.problem, ).toBeNull(); }); it("does not turn a conditional prescription into a current medicine", () => { expect( groundedFact( "Medication: Amlodipine; strength: 5 mg", "If her pressure rises, Nora may start Amlodipine 5 mg.", ["Nora Test"], )?.problem, ).toBeTruthy(); }); it.each([ "Nora's eGFR was not 38 mL/min/1.73m2 on 2026-10-12.", "The old eGFR 38 mL/min/1.73m2 dated 2026-10-12 was entered in error.", ])("withholds negated/erroneous labs: %s", (quote) => { expect( groundedFact( "Lab: eGFR; value: 38; unit: mL/min/1.73m2; date: 2026-10-12", quote, ["Nora Test"], )?.problem, ).toBeTruthy(); }); });