import { expect, test } from "vitest"; import { ReadinessManager } from "../src/runtime/readiness-manager.js"; const workspace = { workspace: { schema_version: 4, id: "psd", name: "PSD", language: "it" }, dwh: { engine: "postgres", database: "warehouse", schema: "public", supported_transports: ["postgres_direct"], }, } as const; function deferred() { let resolve!: (value: T) => void; const promise = new Promise((r) => { resolve = r; }); return { promise, resolve }; } test("readiness is single-flight per workspace and caches a short-lived success", async () => { let now = 1_000; let calls = 0; const first = deferred(); const tht = { ollamaEnsure: async () => { calls += 1; return first.promise; }, } as any; const readiness = new ReadinessManager(tht, 60, 500, () => now); const a = readiness.ensure("psd"); const b = readiness.ensure("psd"); expect(calls).toBe(1); first.resolve({ ok: true, model_name: "embed" }); await expect(a).resolves.toMatchObject({ ok: true }); await expect(b).resolves.toMatchObject({ ok: true }); await readiness.ensure("psd"); expect(calls).toBe(1); now += 501; tht.ollamaEnsure = async () => { calls += 1; return { ok: true }; }; await readiness.ensure("psd"); expect(calls).toBe(2); }); test("readiness keys workspaces independently", async () => { const seen: string[] = []; const tht = { ollamaEnsure: async (workspace: string) => { seen.push(workspace); return { ok: true }; }, } as any; const readiness = new ReadinessManager(tht, 60); await Promise.all([readiness.ensure("a"), readiness.ensure("b")]); expect(seen.sort()).toEqual(["a", "b"]); }); test("readiness does not cache failed results", async () => { let calls = 0; const tht = { ollamaEnsure: async () => { calls += 1; return calls === 1 ? { ok: false, error: "down" } : { ok: true }; }, } as any; const readiness = new ReadinessManager(tht, 60); await expect(readiness.ensure("psd")).resolves.toMatchObject({ ok: false }); await expect(readiness.ensure("psd")).resolves.toMatchObject({ ok: true }); expect(calls).toBe(2); }); test("readiness checks Qdrant before Ollama and skips Ollama on semantic incompatibility", async () => { let ollamaCalls = 0; const tht = { qdrantEnsure: async () => ({ ok: false, code: "semantic_index_incompatible" }), ollamaEnsure: async () => { ollamaCalls += 1; return { ok: true }; }, } as any; const readiness = new ReadinessManager(tht, 60); await expect(readiness.ensure("/registry/psd.yaml", undefined, workspace as any)).resolves.toEqual({ ok: false, code: "semantic_index_incompatible", }); expect(ollamaCalls).toBe(0); }); test("readiness returns a sanitized activation code when a semantic probe throws", async () => { const tht = { qdrantEnsure: async () => { throw new Error("dial http://qdrant:6333/private"); }, ollamaEnsure: async () => ({ ok: true }), } as any; const readiness = new ReadinessManager(tht, 60); await expect(readiness.ensure("/registry/psd.yaml", undefined, workspace as any)).resolves.toEqual({ ok: false, code: "workspace_not_activatable", }); });