import { expect, test } from "vitest"; import { QDRANT_REQUIRED_INDEXES, reconcileCollection } from "../src/workspaces/qdrant-collection.js"; function fakeRequest(info: any | undefined, { create = true, index = true } = {}) { let current = info; let created = false; return async (url: string, init?: any) => { if (init?.method === "PUT" && /\/index$/.test(url)) { if (!index) return { status: 409, ok: false, json: async () => ({}) } as any; // Simulate the index being created: the collection becomes fully compatible. current = compatible(); return { status: 200, ok: true, json: async () => ({}) } as any; } if (init?.method === "PUT") { if (!create) return { status: 409, ok: false, json: async () => ({}) } as any; created = true; current = compatible(); return { status: 200, ok: true, json: async () => ({}) } as any; } if (current === undefined) return { status: 404, ok: false, json: async () => ({}) } as any; return { status: 200, ok: true, json: async () => ({ result: current }) } as any; }; } const payloadSchema = Object.fromEntries(QDRANT_REQUIRED_INDEXES.map((f) => [f, { data_type: "keyword" }])); const compatible = (size = 1024, distance = "Cosine", schema = payloadSchema) => ({ config: { params: { vectors: { size, distance } } }, payload_schema: schema, }); test("self-heal creates a missing compatible collection", async () => { const r = await reconcileCollection({ baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine", mode: "self_heal", request: fakeRequest(undefined), }); expect(r.ok).toBe(true); }); test("require_existing refuses a missing collection", async () => { const r = await reconcileCollection({ baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine", mode: "require_existing", request: fakeRequest(undefined), }); expect(r).toEqual({ ok: false, code: "semantic_index_incompatible" }); }); test("self-heal adds missing keyword indexes", async () => { const schema = { ...payloadSchema }; delete schema["workspace_revision"]; const r = await reconcileCollection({ baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine", mode: "self_heal", request: fakeRequest(compatible(1024, "Cosine", schema)), }); expect(r).toMatchObject({ ok: true, state: "repaired" }); }); test("refuses incompatible dimensions or distance without mutating", async () => { for (const info of [compatible(768, "Cosine"), compatible(1024, "Dot")]) { const r = await reconcileCollection({ baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine", mode: "self_heal", request: fakeRequest(info), }); expect(r).toEqual({ ok: false, code: "semantic_index_incompatible" }); } }); test("self-heal creates with the Qdrant-valid distance enum", async () => { let createdBody: any; const base = fakeRequest(undefined); const request = async (url: string, init?: any) => { if (init?.method === "PUT" && !/\/index$/.test(url)) createdBody = JSON.parse(String(init.body)); return base(url, init); }; const r = await reconcileCollection({ baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine", mode: "self_heal", request, }); expect(r.ok).toBe(true); expect(createdBody.vectors.distance).toBe("Cosine"); }); test("ready compatible collection passes", async () => { const r = await reconcileCollection({ baseUrl: "http://qdrant:6333", collection: "c", dimensions: 1024, distance: "cosine", mode: "require_existing", request: fakeRequest(compatible()), }); expect(r).toMatchObject({ ok: true, state: "ready" }); });